== Vert.x Common SQL interface

The common SQL interface is used to interact with Vert.x SQL services.

You obtain a connection to the database via the service interface for the specific SQL service that
you are using (e.g. JDBC/MySQL/PostgreSQL).

To use this project, add the following dependency to the _dependencies_ section of your build descriptor:

* Maven (in your `pom.xml`):

[source,xml,subs="+attributes"]
----
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-sql-common</artifactId>
  <version>3.3.3</version>
</dependency>
----

* Gradle (in your `build.gradle` file):

[source,groovy,subs="+attributes"]
----
compile 'io.vertx:vertx-sql-common:3.3.3'
----

== The SQL Connection

A connection to the database is represented by `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html[SQLConnection]`.

=== Auto-commit

When you obtain a connection auto commit is set to `true`. This means that each operation you perform will effectively
execute in its own transaction.

If you wish to perform multiple operations in a single transaction you should set auto commit to false with
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#setAutoCommit[setAutoCommit]`.

When the operation is complete, the handler will be called:

[source,java]
----
connection.setAutoCommit(false, function (res, res_err) {
  if (res_err == null) {
    // OK!
  } else {
    // Failed!
  }
});

----

=== Executing queries

To execute a query use `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#query[query]`

The query string is raw SQL that is passed through without changes to the actual database.

The handler will be called with the results, represented by `link:../dataobjects.html#ResultSet[ResultSet]` when the query has
been run.

[source,java]
----
connection.query("SELECT ID, FNAME, LNAME, SHOE_SIZE from PEOPLE", function (res, res_err) {
  if (res_err == null) {
    // Get the result set
    var resultSet = res;
  } else {
    // Failed!
  }
});

----

The `link:../dataobjects.html#ResultSet[ResultSet]` instance represents the results of a query.

The list of column names are available with `link:../dataobjects.html#ResultSet#getColumnNames[getColumnNames]`, and the actual results
available with `link:../dataobjects.html#ResultSet#getResults[getResults]`

The results are a list of `JsonArray` instances, one for each row of the results.

[source,java]
----

var columnNames = resultSet.columnNames;

var results = resultSet.results;

Array.prototype.forEach.call(results, function(row) {

  var id = row[0];
  var fName = row[1];
  var lName = row[2];
  var shoeSize = row[3];

});


----

You can also retrieve the rows as a list of Json object instances with `link:../dataobjects.html#ResultSet#getRows[getRows]` -
this can give you a somewhat simpler API to work with, but please be aware that SQL results can contain duplicate
column names - if that's the case you should use `link:../dataobjects.html#ResultSet#getResults[getResults]` instead.

Here's an example of iterating through the results as Json object instances:

[source,java]
----

var rows = resultSet.rows;

Array.prototype.forEach.call(rows, function(row) {

  var id = row.ID;
  var fName = row.FNAME;
  var lName = row.LNAME;
  var shoeSize = row.SHOE_SIZE;

});


----

=== Prepared statement queries

To execute a prepared statement query you can use
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#queryWithParams[queryWithParams]`.

This takes the query, containing the parameter place holders, and a `JsonArray` or parameter
values.

[source,java]
----

var query = "SELECT ID, FNAME, LNAME, SHOE_SIZE from PEOPLE WHERE LNAME=? AND SHOE_SIZE > ?";
var params = [
  "Fox",
  9
];

connection.queryWithParams(query, params, function (res, res_err) {

  if (res_err == null) {
    // Get the result set
    var resultSet = res;
  } else {
    // Failed!
  }
});


----

=== Executing INSERT, UPDATE or DELETE

To execute an operation which updates the database use `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#update[update]`.

The update string is raw SQL that is passed through without changes to the actual database.

The handler will be called with the results, represented by `link:../dataobjects.html#UpdateResult[UpdateResult]` when the update has
been run.

The update result holds the number of rows updated with `link:../dataobjects.html#UpdateResult#getUpdated[getUpdated]`, and
if the update generated keys, they are available with `link:../dataobjects.html#UpdateResult#getKeys[getKeys]`.

[source,java]
----

connection.update("INSERT INTO PEOPLE VALUES (null, 'john', 'smith', 9)", function (res, res_err) {
  if (res_err == null) {

    var result = res;
    console.log("Updated no. of rows: " + result.updated);
    console.log("Generated keys: " + result.keys);

  } else {
    // Failed!
  }
});



----

=== Prepared statement updates

To execute a prepared statement update you can use
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#updateWithParams[updateWithParams]`.

This takes the update, containing the parameter place holders, and a `JsonArray` or parameter
values.

[source,java]
----

var update = "UPDATE PEOPLE SET SHOE_SIZE = 10 WHERE LNAME=?";
var params = [
  "Fox"
];

connection.updateWithParams(update, params, function (res, res_err) {

  if (res_err == null) {

    var updateResult = res;

    console.log("No. of rows updated: " + updateResult.updated);

  } else {

    // Failed!

  }
});


----

=== Callable statements

To execute a callable statement (either SQL functions or SQL procedures) you can use
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#callWithParams[callWithParams]`.

This takes the callable statement using the standard JDBC format `{ call func_proc_name() }`, optionally including
parameter place holders e.g.: `{ call func_proc_name(?, ?) }`, a `JsonArray` containing the
parameter values and finally a `JsonArray` containing the
output types e.g.: `[null, 'VARCHAR']`.

Note that the index of the output type is as important as the params array. If the return value is the second
argument then the output array must contain a null value as the first element.

A SQL function returns some output using the `return` keyword, and in this case one can call it like this:

[source,java]
----
// Assume that there is a SQL function like this:
//
// create function one_hour_ago() returns timestamp
//    return now() - 1 hour;

// note that you do not need to declare the output for functions
var func = "{ call one_hour_ago() }";

connection.call(func, function (res, res_err) {

  if (res_err == null) {
    var result = res;
  } else {
    // Failed!
  }
});

----

When working with Procedures you and still return values from your procedures via its arguments, in the case you do
not return anything the usage is as follows:

[source,java]
----
// Assume that there is a SQL procedure like this:
//
// create procedure new_customer(firstname varchar(50), lastname varchar(50))
//   modifies sql data
//   insert into customers values (default, firstname, lastname, current_timestamp);

var func = "{ call new_customer(?, ?) }";

connection.callWithParams(func, [
  "John",
  "Doe"
], null, function (res, res_err) {

  if (res_err == null) {
    // Success!
  } else {
    // Failed!
  }
});

----

However you can also return values like this:

[source,java]
----
// Assume that there is a SQL procedure like this:
//
// create procedure customer_lastname(IN firstname varchar(50), OUT lastname varchar(50))
//   modifies sql data
//   select lastname into lastname from customers where firstname = firstname;

var func = "{ call customer_lastname(?, ?) }";

connection.callWithParams(func, [
  "John"
], [
  null,
  "VARCHAR"
], function (res, res_err) {

  if (res_err == null) {
    var result = res;
  } else {
    // Failed!
  }
});

----

Note that the index of the arguments matches the index of the `?` and that the output parameters expect to be a
String describing the type you want to receive.

To avoid ambiguation the implementations are expected to follow the following rules:

* When a place holder in the `IN` array is `NOT NULL` it will be taken
* When the `IN` value is NULL a check is performed on the OUT
  * When the `OUT` value is not null it will be registered as a output parameter
  * When the `OUT` is also null it is expected that the IN value is the `NULL` value.

The registered `OUT` parameters will be available as an array in the result set under the output property.

=== Batch operations

The SQL common interface also defines how to execute batch operations. There are 3 types of batch operations:

* Batched statements `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#batch[batch]`
* Batched prepared statements `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#batchWithParams[batchWithParams]`
* Batched callable statements `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#batchCallableWithParams[batchCallableWithParams]`

A batches statement will exeucte a list of sql statements as for example:

[source,java]
----
// Batch values
var batch = [];
batch.push("INSERT INTO emp (NAME) VALUES ('JOE')");
batch.push("INSERT INTO emp (NAME) VALUES ('JANE')");

connection.batch(batch, function (res, res_err) {
  if (res_err == null) {
    var result = res;
  } else {
    // Failed!
  }
});

----

While a prepared or callable statement batch will reuse the sql statement and take an list of arguments as for example:

[source,java]
----
// Batch values
var batch = [];
batch.push([
  "joe"
]);
batch.push([
  "jane"
]);

connection.batchWithParams("INSERT INTO emp (name) VALUES (?)", batch, function (res, res_err) {
  if (res_err == null) {
    var result = res;
  } else {
    // Failed!
  }
});

----

=== Executing other operations

To execute any other database operation, e.g. a `CREATE TABLE` you can use
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#execute[execute]`.

The string is passed through without changes to the actual database. The handler is called when the operation
is complete

[source,java]
----

var sql = "CREATE TABLE PEOPLE (ID int generated by default as identity (start with 1 increment by 1) not null,FNAME varchar(255), LNAME varchar(255), SHOE_SIZE int);";

connection.execute(sql, function (execute, execute_err) {
  if (execute_err == null) {
    console.log("Table created !");
  } else {
    // Failed!
  }
});


----

=== Using transactions

To use transactions first set auto-commit to false with `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#setAutoCommit[setAutoCommit]`.

You then do your transactional operations and when you want to commit or rollback use
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#commit[commit]` or
`link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#rollback[rollback]`.

Once the commit/rollback is complete the handler will be called and the next transaction will be automatically started.

[source,java]
----

// Do stuff with connection - updates etc

// Now commit

connection.commit(function (res, res_err) {
  if (res_err == null) {
    // Committed OK!
  } else {
    // Failed!
  }
});


----

=== Closing connections

When you've done with the connection you should return it to the pool with `link:../../jsdoc/module-vertx-sql-js_sql_connection-SQLConnection.html#close[close]`.