Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve API docs #343

Merged
merged 6 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 53 additions & 48 deletions ballerina/Module.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ Follow one of the following ways to add the JAR in the file:

* Add JAR with a maven dependency params
```
[platform.java11.dependency]]
[[platform.java11.dependency]]
groupId = "mysql"
artifactId = "mysql-connector-java"
version = "8.0.20"
```

### Client
To access a database, you must first create a
[mysql:Client](https://docs.central.ballerina.io/ballerinax/mysql/latest/clients/Client) object.
[`mysql:Client`](https://docs.central.ballerina.io/ballerinax/mysql/latest/clients/Client) object.
The samples for creating a MySQL client can be found below.

#### Creating a Client
Expand All @@ -38,16 +38,16 @@ mysql:Client|sql:Error dbClient = new ();
```

The `dbClient` receives the host, username, and password. Since the properties are passed in the same order as they are defined
in the `mysql:Client`, you can pass them without named params.
in the `mysql:Client`, they can be passed without named parameters.

```ballerina
mysql:Client|sql:Error dbClient = new ("localhost", "rootUser", "rooPass",
mysql:Client|sql:Error dbClient = new ("localhost", "rootUser", "rootPass",
"information_schema", 3306);
```

The `dbClient` uses the named params to pass the attributes since it is skipping some params in the constructor.
The sample below shows a `mysql:Client` using named parameters to pass the attributes since some parameters are skipped in the constructor.
Further, the [`mysql:Options`](https://docs.central.ballerina.io/ballerinax/mysql/latest/records/Options)
property is passed to configure the SSL and connection timeout in the MySQL client.
property is passed to configure SSL and connection timeout properties in the MySQL client.

```ballerina
mysql:Options mysqlOptions = {
Expand All @@ -60,8 +60,8 @@ mysql:Client|sql:Error dbClient = new (user = "rootUser", password = "rootPass",
options = mysqlOptions);
```

Similarly, the `dbClient` uses the named params and it provides an unshared connection pool of the type of
[sql:ConnectionPool](https://docs.central.ballerina.io/ballerina/sql/latest/records/ConnectionPool)
Similarly in the sample below, the `mysql:Client` uses named parameters, and it provides an unshared connection pool of type
[`sql:ConnectionPool`](https://docs.central.ballerina.io/ballerina/sql/latest/records/ConnectionPool)
to be used within the client.
For more details about connection pooling, see the [`sql` Module](https://docs.central.ballerina.io/ballerina/sql/latest).

Expand All @@ -71,9 +71,9 @@ mysql:Client|sql:Error dbClient = new (user = "rootUser", password = "rootPass",
```

#### Using SSL
To connect the MySQL database using an SSL connection, you must add the SSL configurations to the `mysql:Options` when creating the `dbClient`.
To connect to the MySQL database using an SSL connection, you must add the SSL configurations to `mysql:Options` when creating the `mysql:Client`.
For the SSL Mode, you can select one of the modes: `mysql:SSL_PREFERRED`, `mysql:SSL_REQUIRED`, `mysql:SSL_VERIFY_CA`, or `mysql:SSL_VERIFY_IDENTITY` according to the requirement.
For the key and cert files, you must provide the files in the `.p12` format.
For the key and cert files must be provided in the `.p12` format.
kaneeldias marked this conversation as resolved.
Show resolved Hide resolved

```ballerina
string clientStorePath = "/path/to/keystore.p12";
Expand All @@ -96,11 +96,11 @@ mysql:Options mysqlOptions = {
#### Connection Pool Handling

All database modules share the same connection pooling concept and there are three possible scenarios for
connection pool handling. For its properties and possible values, see the [`sql:ConnectionPool`](https://docs.central.ballerina.io/ballerina/sql/latest/records/ConnectionPool).
connection pool handling. For its properties and possible values, see [`sql:ConnectionPool`](https://docs.central.ballerina.io/ballerina/sql/latest/records/ConnectionPool).

1. Global, shareable, default connection pool

If you do not provide the `poolOptions` field when creating the database client, a globally-shareable pool will be
If you do not provide the `connectionPool` field when creating the client, a globally-shareable pool will be
created for your database unless a connection pool matching with the properties you provided already exists.

```ballerina
Expand All @@ -109,7 +109,7 @@ connection pool handling. For its properties and possible values, see the [`sql

2. Client-owned, unsharable connection pool

If you define the `connectionPool` field inline when creating the database client with the `sql:ConnectionPool` type,
If you define the `connectionPool` field inline when creating the client with the `sql:ConnectionPool` type,
an unsharable connection pool will be created.

```ballerina
Expand Down Expand Up @@ -139,14 +139,14 @@ connection pool handling. For its properties and possible values, see the [`sql

For more details about each property, see the [`mysql:Client`](https://docs.central.ballerina.io/ballerinax/mysql/latest/clients/Client) constructor.

The [mysql:Client](https://docs.central.ballerina.io/ballerinax/mysql/latest/clients/Client) references
[sql:Client](https://docs.central.ballerina.io/ballerina/sql/latest/clients/Client) and all the operations
The [`mysql:Client`](https://docs.central.ballerina.io/ballerinax/mysql/latest/clients/Client) references
the [`sql:Client`](https://docs.central.ballerina.io/ballerina/sql/latest/clients/Client) and all the operations
defined by the `sql:Client` will be supported by the `mysql:Client` as well.

#### Closing the Client

Once all the database operations are performed, you can close the database client you have created by invoking the `close()`
operation. This will close the corresponding connection pool if it is not shared by any other database clients.
Once all the database operations are performed, you can close the client you have created by invoking the `close()`
operation. This will close the corresponding connection pool if it is not shared by any other clients.

```ballerina
error? e = dbClient.close();
Expand All @@ -159,7 +159,7 @@ check dbClient.close();
### Database Operations

Once the client is created, database operations can be executed through that client. This module defines the interface
and common properties that are shared among multiple database clients. It also supports querying, inserting, deleting,
and common properties that are shared among multiple database clients. It also supports querying, inserting, deleting,
updating, and batch updating data.

#### Parameterized Query
Expand All @@ -186,7 +186,7 @@ sql:ParameterizedQuery query = `SELECT * FROM students
Moreover, the SQL package has `sql:queryConcat()` and `sql:arrayFlattenQuery()` util functions which make it easier
to create a dynamic/constant complex query.

The `sql:queryConcat()` is used to create a parameterized query by concatenating a set of parameterized queries.
`sql:queryConcat()` is used to create a single parameterized query by concatenating a set of parameterized queries.
The sample below shows how to concatenate queries.

```ballerina
Expand All @@ -197,15 +197,15 @@ sql:ParameterizedQuery query1 = ` WHERE id < ${id} AND age > ${age}`;
sql:ParameterizedQuery sqlQuery = sql:queryConcat(query, query1);
```

The query with the `IN` operator can be created using the `sql:ParameterizedQuery` like below. Here you need to flatten the array and pass each element separated by a comma.
A query with the `IN` operator can be created using the `sql:ParameterizedQuery` as shown below. Here you need to flatten the array and pass each element separated by a comma.

```ballerina
int[] ids = [1, 2, 3];
sql:ParameterizedQuery query = `SELECT count(*) as total FROM DataTable
WHERE row_id in (${ids[0]}, ${ids[1]}, ${ids[2]})`;
WHERE row_id IN (${ids[0]}, ${ids[1]}, ${ids[2]})`;
```

The util function `sql:arrayFlattenQuery()` is introduced to make the array flatten easier. It makes the inclusion of varying array elements into the query easier by flattening the array to return a parameterized query. You can construct the complex dynamic query with the `IN` operator by using both functions like below.
The util function `sql:arrayFlattenQuery()` is used to make array flattening easier. It makes the inclusion of varying array elements into the query easier by flattening the array to return a parameterized query. You can construct a complex dynamic query with the `IN` operator by using both functions as shown below.

```ballerina
int[] ids = [1, 2];
Expand All @@ -216,19 +216,20 @@ sql:ParameterizedQuery sqlQuery =

#### Creating Tables

This sample creates a table with two columns. One column is of type `int` and the other is of type `varchar`.
This sample creates a table with three columns. The first column is a primary key of type `int`, while the second
column is of type `int` and the other is of type `varchar`.
The `CREATE` statement is executed via the `execute` remote function of the client.

```ballerina
// Create the ‘Students’ table with the ‘id’, 'name', and ‘age’ fields.
// Create the ‘Students’ table with the ‘id’, 'age', and ‘name’ fields.
sql:ExecutionResult result =
check dbClient->execute(`CREATE TABLE student (
id INT AUTO_INCREMENT,
age INT,
name VARCHAR(255),
PRIMARY KEY (id)
)`);
//A value of the sql:ExecutionResult type is returned for 'result'.
// A value of the sql:ExecutionResult type is returned for 'result'.
```

#### Inserting Data
Expand All @@ -244,10 +245,10 @@ sql:ExecutionResult result = check dbClient->execute(`INSERT INTO student(age, n
VALUES (23, 'john')`);
```

In this sample, the parameter values, which are in local variables are used to parameterize the SQL query in
the `execute` remote function. This type of a parameterized SQL query can be used with any primitive Ballerina type
like `string`, `int`, `float`, or `boolean` and in that case, the corresponding SQL type of the parameter is derived
from the type of the Ballerina variable that is passed in.
In this sample, the parameter values, which are assigned to local variables are used to parameterize the SQL query in
the `execute` remote function. This type of parameterized SQL query can be used with any primitive Ballerina type
such as `string`, `int`, `float`, or `boolean` and in that case, the corresponding SQL type of the parameter is derived
from the type of the Ballerina variable that is passed.

```ballerina
string name = "Anne";
Expand Down Expand Up @@ -283,9 +284,11 @@ string name = "Kate";
sql:ParameterizedQuery query = `INSERT INTO student(age, name)
VALUES (${age}, ${name})`;
sql:ExecutionResult result = check dbClient->execute(query);
//Number of rows affected by the execution of the query.

// Number of rows affected by the execution of the query.
int? count = result.affectedRowCount;
//The integer or string generated by the database in response to a query execution.

// The integer or string generated by the database in response to a query execution.
string|int? generatedKey = result.lastInsertId;
```

Expand All @@ -299,11 +302,11 @@ First, a type is created to represent the returned result set. This record can b
according to the requirement. If an open record is defined, the returned stream type will include both defined fields
in the record and additional database columns fetched by the SQL query which are not defined in the record.
Note the mapping of the database column to the returned record's property is case-insensitive if it is defined in the
record(i.e., the `ID` column in the result can be mapped to the `id` property in the record). Additional Column names
added to the returned record as in the SQL query. If the record is defined as a close record, only defined fields in the
record(i.e., the `ID` column in the result can be mapped to the `id` property in the record). Additional column names are
added to the returned record as in the SQL query. If the record is defined as a closed record, only defined fields in the
record are returned or gives an error when additional columns present in the SQL query. Next, the `SELECT` query is executed
via the `query` remote function of the client. Once the query is executed, each data record can be retrieved by looping
the result set. The `stream` returned by the select operation holds a pointer to the actual data in the database and it
via the `query` remote function of the client. Once the query is executed, each data record can be retrieved by iterating through
the result set. The `stream` returned by the `SELECT` operation holds a pointer to the actual data in the database, and it
loads data from the table only when it is accessed. This stream can be iterated only once.

```ballerina
Expand All @@ -324,12 +327,13 @@ sql:ParameterizedQuery query = `SELECT * FROM students
stream<Student, sql:Error?> resultStream = dbClient->query(query);

// Iterating the returned table.
error? e = resultStream.forEach(function(Student student) {
//Can perform operations using the record 'student' of type `Student`.
});
check from Student student in resultStream
do {
// Can perform operations using the record 'student' of type `Student`.
}
kaneeldias marked this conversation as resolved.
Show resolved Hide resolved
```

Defining the return type is optional and you can query the database without providing the result type. Hence,
Defining the return type is optional, and you can query the database without providing the result type. Hence,
the above sample can be modified as follows with an open record type as the return type. The property name in the open record
type will be the same as how the column is defined in the database.

Expand All @@ -344,10 +348,11 @@ sql:ParameterizedQuery query = `SELECT * FROM students
stream<record{}, sql:Error?> resultStream = dbClient->query(query);

// Iterating the returned table.
error? e = resultStream.forEach(function(record{} student) {
// Can perform operations using the record 'student'.
io:println("Student name: ", student.value["name"]);
});
check from record{} student in resultStream
do {
// Can perform operations using the record 'student'.
io:println("Student name: ", student.value["name"]);
}
kaneeldias marked this conversation as resolved.
Show resolved Hide resolved
```

There are situations in which you may not want to iterate through the database and in that case, you may decide
Expand Down Expand Up @@ -413,7 +418,7 @@ sql:ParameterizedQuery[] batch = from var row in data
sql:ExecutionResult[] result = check dbClient->batchExecute(batch);
```

#### Execute SQL Stored Procedures
#### Execute Stored Procedures

This sample demonstrates how to execute a stored procedure with a single `INSERT` statement that is executed via the
`call` remote function of the client.
Expand All @@ -426,10 +431,10 @@ sql:ProcedureCallResult result =
check dbClient->call(`call InsertPerson(${uid}, ${insertId})`);
stream<record{}, sql:Error?>? resultStr = result.queryResult;
if resultStr is stream<record{}, sql:Error?> {
sql:Error? e = resultStr.forEach(function(record{} result) {
// Can perform operations using the record 'result'.
});
}
check from record{} value in resultStr
do {
// Can perform operations using the record 'value'.
}}
kaneeldias marked this conversation as resolved.
Show resolved Hide resolved
check result.close();
```
Note that you have to invoke the close operation explicitly on the `sql:ProcedureCallResult` to release the connection resources and avoid a connection leak as shown above.
Expand Down
Loading