Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
niveathika authored Jan 21, 2022
2 parents 0513f0b + f43d719 commit 0627188
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 178 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ jobs:
sed -i 's/ballerinaLangVersion=\(.*\)-[0-9]\{8\}-[0-9]\{6\}-.*$/ballerinaLangVersion=\1/g' gradle.properties
sed -i 's/stdlib\(.*\)=\(.*\)-SNAPSHOT/stdlib\1=\2/g' gradle.properties
sed -i 's/stdlib\(.*\)=\(.*\)-[0-9]\{8\}-[0-9]\{6\}-.*$/stdlib\1=\2/g' gradle.properties
sed -i 's/observe\(.*\)=\(.*\)-SNAPSHOT/observe\1=\2/g' gradle.properties
sed -i 's/observe\(.*\)=\(.*\)-[0-9]\{8\}-[0-9]\{6\}-.*$/observe\1=\2/g' gradle.properties
git add gradle.properties
git commit -m "Move dependencies to stable version" || echo "No changes to commit"
- name: Publish artifact
Expand Down
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "observe"
version = "1.0.0"
version = "1.0.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
Expand Down
109 changes: 58 additions & 51 deletions ballerina/Module.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
## Overview

This module provides the generic interface and functionality to interact with a SQL database. The corresponding database
clients can be created by using specific database modules such as `mysql` or using the Java Database Connectivity
This module provides the generic interface and functionality to interact with an SQL database. The corresponding database
clients can be created by using specific database modules such as `mysql` or using the Java Database Connectivity
module `jdbc`.

### List of Database Modules
Ballerina now has the [`jdbc` module](https://docs.central.ballerina.io/ballerinax/java.jdbc/latest) as the generic DB connector module to connect to any relational database by simply providing the JDBC URL and the other related properties.
Ballerina also provides specially designed various database-specific DB connectors so that you can work with different databases and you can access their DB-specific functionalities.

Ballerina also provides specially designed various database-specific DB connectors so that you can work with different databases, and you can access their DB-specific functionalities.
* [`MySQL` module](https://central.ballerina.io/ballerinax/mysql)
* [`PostgreSQL` module](https://central.ballerina.io/ballerinax/postgresql)
* [`MSSQL` module](https://central.ballerina.io/ballerinax/mssql)
* [`OracleDB` module](https://central.ballerina.io/ballerinax/oracledb)

### Client

The database client should be created using any of the above-listed database modules and once it is created, the operations and functionality explained below can be used.
The database client should be created using any of the above-listed database modules and once it is created, the operations and functionality explained below can be used.

#### 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).
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).

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
created for your database unless a connection pool matching with the properties you provided already exists.
The JDBC module sample below shows how the global connection pool is used.
If you do not provide the `poolOptions` field when creating the database client, a globally-shareable pool will be
created for your database unless a connection pool matching with the properties you provided already exists.
The `jdbc` module sample below shows how the global connection pool is used.

```ballerina
jdbc:Client|sql:Error dbClient =
Expand All @@ -31,9 +36,9 @@ 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,
an unsharable connection pool will be created. The JDBC module sample below shows how the global
connection pool is used.
If you define the `connectionPool` field inline when creating the database client with the `sql:ConnectionPool` type,
an unsharable connection pool will be created. The `jdbc` module sample below shows how the global
connection pool is used.
```ballerina
jdbc:Client|sql:Error dbClient =
Expand All @@ -43,9 +48,8 @@ connection pool handling. For its properties and possible values, see the [`sql
3. Local, shareable connection pool
If you create a record of the `sql:ConnectionPool` type and reuse that in the configuration of multiple clients,
for each set of clients that connects to the same database instance with the same set of properties, a shared
connection pool will be created. The JDBC module sample below shows how the global connection pool is used.
If you create a record of the `sql:ConnectionPool` type and reuse that in the configuration of multiple clients,
a shared connection pool will be created for each set of clients that connects to the same database instance with the same set of properties. The `jdbc` module sample below shows how the global connection pool is used.
```ballerina
sql:ConnectionPool connPool = {maxOpenConnections: 5};
Expand All @@ -60,11 +64,11 @@ connection pool handling. For its properties and possible values, see the [`sql
new (url = "jdbc:mysql://localhost:3306/testdb",
connectionPool = connPool);
```
#### 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.
operation. This will close the corresponding connection pool if it is not shared by any other database clients.
```ballerina
error? e = dbClient.close();
Expand All @@ -76,9 +80,9 @@ check dbClient.close();

### Database Operations

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

#### Parameterized Query

Expand Down Expand Up @@ -151,21 +155,21 @@ sql:ExecutionResult result =

#### Inserting Data

These samples show the data insertion by executing an `INSERT` statement using the `execute` remote function
These samples show the data insertion by executing an `INSERT` statement using the `execute` remote function
of the client.

In this sample, the query parameter values are passed directly into the query statement of the `execute`
In this sample, the query parameter values are passed directly into the query statement of the `execute`
remote function.

```ballerina
sql:ExecutionResult result = check dbClient->execute(`INSERT INTO student(age, name)
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 parameterization can be performed 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 parameterization can be performed 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.

```ballerina
string name = "Anne";
Expand All @@ -176,8 +180,8 @@ sql:ParameterizedQuery query = `INSERT INTO student(age, name)
sql:ExecutionResult result = check dbClient->execute(query);
```

In this sample, the parameter values are passed as a `sql:TypedValue` to the `execute` remote function. Use the
corresponding subtype of the `sql:TypedValue` such as `sql:VarcharValue`, `sql:CharValue`, `sql:IntegerValue`, etc., when you need to
In this sample, the parameter values are passed as a `sql:TypedValue` to the `execute` remote function. Use the
corresponding subtype of the `sql:TypedValue` such as `sql:VarcharValue`, `sql:CharValue`, `sql:IntegerValue`, etc., when you need to
provide more details such as the exact SQL type of the parameter.

```ballerina
Expand All @@ -191,7 +195,7 @@ sql:ExecutionResult result = check dbClient->execute(query);

#### Inserting Data With Auto-generated Keys

This sample demonstrates inserting data while returning the auto-generated keys. It achieves this by using the
This sample demonstrates inserting data while returning the auto-generated keys. It achieves this by using the
`execute` remote function to execute the `INSERT` statement.

```ballerina
Expand Down Expand Up @@ -220,8 +224,8 @@ Note the mapping of the database column to the returned record's property is cas
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 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 looping
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 @@ -242,14 +246,15 @@ 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`.
}
```

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.
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.

```ballerina
// Select the data from the database table. The query parameters are passed
Expand All @@ -262,14 +267,15 @@ 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"]);
}
```

There are situations in which you may not want to iterate through the database and in that case, you may decide
to use the `sql:queryRow()` operation. If the provided return type is a record, this method returns only the first row
to use the `sql:queryRow()` operation. If the provided return type is a record, this method returns only the first row
retrieved by the query as a record.

```ballerina
Expand All @@ -278,7 +284,7 @@ sql:ParameterizedQuery query = `SELECT * FROM students WHERE id = ${id}`;
Student retrievedStudent = check dbClient->queryRow(query);
```

The `sql:queryRow()` operation can also be used to retrieve a single value from the database (e.g., when querying using
The `sql:queryRow()` operation can also be used to retrieve a single value from the database (e.g., when querying using
`COUNT()` and other SQL aggregation functions). If the provided return type is not a record (i.e., a primitive data type)
, this operation will return the value of the first column of the first row retrieved by the query.

Expand All @@ -290,7 +296,7 @@ int youngStudents = check dbClient->queryRow(query);

#### Updating Data

This sample demonstrates modifying data by executing an `UPDATE` statement via the `execute` remote function of
This sample demonstrates modifying data by executing an `UPDATE` statement via the `execute` remote function of
the client.

```ballerina
Expand All @@ -301,7 +307,7 @@ sql:ExecutionResult result = check dbClient->execute(query);

#### Deleting Data

This sample demonstrates deleting data by executing a `DELETE` statement via the `execute` remote function of
This sample demonstrates deleting data by executing a `DELETE` statement via the `execute` remote function of
the client.

```ballerina
Expand All @@ -312,8 +318,8 @@ sql:ExecutionResult result = check dbClient->execute(query);

#### Batch Updating Data

This sample demonstrates how to insert multiple records with a single `INSERT` statement that is executed via the
`batchExecute` remote function of the client. This is done by creating a `table` with multiple records and
This sample demonstrates how to insert multiple records with a single `INSERT` statement that is executed via the
`batchExecute` remote function of the client. This is done by creating a `table` with multiple records and a
parameterized SQL query as same as the above `execute` operations.

```ballerina
Expand All @@ -333,7 +339,7 @@ sql:ExecutionResult[] result = check dbClient->batchExecute(batch);

#### Execute SQL Stored Procedures

This sample demonstrates how to execute a stored procedure with a single `INSERT` statement that is executed via the
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.

```ballerina
Expand All @@ -344,9 +350,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 'result'.
}
}
check result.close();
```
Expand Down
16 changes: 8 additions & 8 deletions ballerina/client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import ballerina/jballerina.java;

# Represents a SQL client.
# Represents an SQL client.
#
public type Client client object {

Expand All @@ -29,11 +29,11 @@ public type Client client object {
returns stream <rowType, Error?>;

# Executes the query, which is expected to return at most one row of the result.
# If the query does not return any results, `sql:NoRowsError` is returned
# If the query does not return any results, `sql:NoRowsError` is returned.
#
# + sqlQuery - The SQL query
# + returnType - The `typedesc` of the record to which the result needs to be returned.
# It can be a basic type if the query contains only one column
# It can be a basic type if the query result contains only one column
# + return - Result in the `returnType` type or an `sql:Error`
remote isolated function queryRow(ParameterizedQuery sqlQuery, typedesc<anydata> returnType = <>)
returns returnType|Error;
Expand All @@ -44,25 +44,25 @@ public type Client client object {
# + return - Metadata of the query execution as an `sql:ExecutionResult` or an `sql:Error`
remote isolated function execute(ParameterizedQuery sqlQuery) returns ExecutionResult|Error;

# Executes the SQL query with multiple sets of parameters in a batch. Only the metadata of the execution is returned (not results from the query).
# If one of the commands in the batch fails, this will return an `sql:BatchExecuteError`. However, the driver may
# Executes the SQL query with multiple sets of parameters in a batch. Only the metadata of the execution is returned (not the results from the query).
# If one of the commands in the batch fails, an `sql:BatchExecuteError` will be returned. However, the driver may
# or may not continue to process the remaining commands in the batch after a failure.
#
# + sqlQueries - The SQL query with multiple sets of parameters
# + return - Metadata of the query execution as an `sql:ExecutionResult[]` or an `sql:Error`
remote isolated function batchExecute(ParameterizedQuery[] sqlQueries) returns ExecutionResult[]|Error;

# Executes a SQL query, which calls a stored procedure. This can either return results or nil.
# Executes an SQL query, which calls a stored procedure. This may or may not return results.
#
# + sqlQuery - The SQL query
# + rowTypes - The array `typedesc` of the records to which the results needs to be returned
# + rowTypes - `typedesc` array of the records to which the results need to be returned
# + return - Summary of the execution and results are returned in an `sql:ProcedureCallResult`, or an `sql:Error`
remote isolated function call(ParameterizedCallQuery sqlQuery, typedesc<record {}>[] rowTypes = [])
returns ProcedureCallResult|Error;

# Closes the SQL client and shuts down the connection pool.
#
# + return - Possible error when closing the client
# + return - Possible `sql:Error` when closing the client
public isolated function close() returns Error?;
};

Expand Down
Loading

0 comments on commit 0627188

Please sign in to comment.