From 6bae2f33b609137f5cb9c4f15d84f484d68bd019 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Wed, 14 Sep 2022 18:18:17 +0530 Subject: [PATCH 01/12] [Automated] Update native jar versions in toml files --- ballerina/Ballerina.toml | 8 ++++---- ballerina/CompilerPlugin.toml | 2 +- ballerina/Dependencies.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 2197cc96..08d13c28 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "sql" -version = "1.5.0" +version = "1.5.1" authors = ["Ballerina"] keywords = ["database", "client", "network", "SQL", "RDBMS"] repository = "https://github.com/ballerina-platform/module-ballerina-sql" @@ -12,11 +12,11 @@ distribution = "2201.2.0" [[platform.java11.dependency]] groupId = "io.ballerina.stdlib" artifactId = "sql-native" -version = "1.5.0" -path = "../native/build/libs/sql-native-1.5.0.jar" +version = "1.5.1" +path = "../native/build/libs/sql-native-1.5.1-SNAPSHOT.jar" [[platform.java11.dependency]] -path = "../test-utils/build/libs/sql-test-utils-1.5.0.jar" +path = "../test-utils/build/libs/sql-test-utils-1.5.1-SNAPSHOT.jar" scope = "testOnly" [[platform.java11.dependency]] diff --git a/ballerina/CompilerPlugin.toml b/ballerina/CompilerPlugin.toml index bbd97688..dcf1a87f 100644 --- a/ballerina/CompilerPlugin.toml +++ b/ballerina/CompilerPlugin.toml @@ -3,4 +3,4 @@ id = "sql-compiler-plugin" class = "io.ballerina.stdlib.sql.compiler.SQLCompilerPlugin" [[dependency]] -path = "../compiler-plugin/build/libs/sql-compiler-plugin-1.5.0.jar" +path = "../compiler-plugin/build/libs/sql-compiler-plugin-1.5.1-SNAPSHOT.jar" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index e3c82002..b236dbdd 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -290,7 +290,7 @@ dependencies = [ [[package]] org = "ballerina" name = "sql" -version = "1.5.0" +version = "1.5.1" dependencies = [ {org = "ballerina", name = "file"}, {org = "ballerina", name = "io"}, From 248345932f7f5d118967521d20dd2edbfeec210a Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Tue, 25 Oct 2022 11:25:45 +0530 Subject: [PATCH 02/12] [Automated] Update native jar versions in toml files --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b236dbdd..4801d5b4 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -225,7 +225,7 @@ dependencies = [ [[package]] org = "ballerina" name = "log" -version = "2.4.0" +version = "2.4.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "io"}, From 6a6f25cae161ec1389ec920187820b4e501af56f Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Thu, 23 Feb 2023 21:30:17 +0530 Subject: [PATCH 03/12] [Automated] Update native jar versions in toml files --- ballerina/Dependencies.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 4801d5b4..40253d00 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -34,7 +34,7 @@ dependencies = [ [[package]] org = "ballerina" name = "constraint" -version = "1.0.0" +version = "1.0.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} @@ -99,7 +99,7 @@ dependencies = [ [[package]] org = "ballerina" name = "io" -version = "1.3.0" +version = "1.3.1" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} @@ -261,7 +261,7 @@ dependencies = [ [[package]] org = "ballerina" name = "observe" -version = "1.0.5" +version = "1.0.6" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} @@ -280,7 +280,7 @@ dependencies = [ [[package]] org = "ballerina" name = "regex" -version = "1.3.0" +version = "1.3.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, From e03d15a7ae082133a6fabb5a924f5ae0a8a12045 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Wed, 20 Sep 2023 11:44:30 +0530 Subject: [PATCH 04/12] [Automated] Update native jar versions in toml files --- ballerina/Dependencies.toml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 13debdb1..c6ea8edd 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.0-20230726-145300-b2bdf796" +distribution-version = "2201.8.0-20230908-135700-74a59dff" [[package]] org = "ballerina" @@ -99,11 +99,13 @@ dependencies = [ org = "ballerina" name = "io" version = "1.6.0" -scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -235,7 +237,6 @@ modules = [ org = "ballerina" name = "lang.value" version = "0.0.0" -scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -302,12 +303,14 @@ name = "sql" version = "1.11.0" dependencies = [ {org = "ballerina", name = "file"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.object"}, {org = "ballerina", name = "lang.runtime"}, {org = "ballerina", name = "lang.string"}, {org = "ballerina", name = "lang.transaction"}, {org = "ballerina", name = "test"}, + {org = "ballerina", name = "time"}, {org = "ballerinai", name = "transaction"} ] modules = [ @@ -341,10 +344,12 @@ modules = [ org = "ballerina" name = "time" version = "2.4.0" -scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +modules = [ + {org = "ballerina", packageName = "time", moduleName = "time"} +] [[package]] org = "ballerina" From 99c1d8618e58e2cc34b79c617a72279892b990bd Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Mon, 11 Dec 2023 16:49:18 +0530 Subject: [PATCH 05/12] [Automated] Update native jar versions in toml files --- ballerina/Ballerina.toml | 8 ++++---- ballerina/CompilerPlugin.toml | 2 +- ballerina/Dependencies.toml | 9 +++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 6aa1f059..d31ae2fc 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "sql" -version = "1.11.1" +version = "1.11.2" authors = ["Ballerina"] keywords = ["database", "client", "network", "SQL", "RDBMS"] repository = "https://github.com/ballerina-platform/module-ballerina-sql" @@ -15,11 +15,11 @@ graalvmCompatible = true [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "sql-native" -version = "1.11.1" -path = "../native/build/libs/sql-native-1.11.1.jar" +version = "1.11.2" +path = "../native/build/libs/sql-native-1.11.2-SNAPSHOT.jar" [[platform.java17.dependency]] -path = "../test-utils/build/libs/sql-test-utils-1.11.1.jar" +path = "../test-utils/build/libs/sql-test-utils-1.11.2-SNAPSHOT.jar" scope = "testOnly" [[platform.java17.dependency]] diff --git a/ballerina/CompilerPlugin.toml b/ballerina/CompilerPlugin.toml index d27b59f7..c8b0a2cc 100644 --- a/ballerina/CompilerPlugin.toml +++ b/ballerina/CompilerPlugin.toml @@ -3,4 +3,4 @@ id = "sql-compiler-plugin" class = "io.ballerina.stdlib.sql.compiler.SQLCompilerPlugin" [[dependency]] -path = "../compiler-plugin/build/libs/sql-compiler-plugin-1.11.1.jar" +path = "../compiler-plugin/build/libs/sql-compiler-plugin-1.11.2-SNAPSHOT.jar" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 136d61c7..3e7adf48 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.0" +distribution-version = "2201.9.0-20231211-150600-888c06e1" [[package]] org = "ballerina" @@ -35,7 +35,7 @@ dependencies = [ [[package]] org = "ballerina" name = "constraint" -version = "1.4.0" +version = "1.5.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} @@ -69,7 +69,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.10.0" +version = "2.10.5" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -111,6 +111,7 @@ modules = [ org = "ballerina" name = "jballerina.java" version = "0.0.0" +scope = "testOnly" modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] @@ -300,7 +301,7 @@ dependencies = [ [[package]] org = "ballerina" name = "sql" -version = "1.11.1" +version = "1.11.2" dependencies = [ {org = "ballerina", name = "file"}, {org = "ballerina", name = "io"}, From c6e968369baa57dc1567105df5eeec567412ffe4 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Wed, 21 Feb 2024 14:24:40 +0530 Subject: [PATCH 06/12] Add Ref Cursor support for the procedure call --- ballerina/types.bal | 15 ++++++++- .../io/ballerina/stdlib/sql/Constants.java | 1 + .../stdlib/sql/nativeimpl/CallProcessor.java | 4 +++ .../sql/nativeimpl/OutParameterProcessor.java | 15 +++++++++ .../stdlib/sql/nativeimpl/QueryProcessor.java | 13 +------- .../AbstractResultParameterProcessor.java | 4 +++ .../DefaultResultParameterProcessor.java | 31 +++++++++++++++++++ .../io/ballerina/stdlib/sql/utils/Utils.java | 13 ++++++++ 8 files changed, 83 insertions(+), 13 deletions(-) diff --git a/ballerina/types.bal b/ballerina/types.bal index 9142a5b7..4020e5f0 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -1321,6 +1321,19 @@ public distinct class XMLOutParameter { } external; } +# Represents the generic OUT Cursor Parameters in `sql:ParameterizedCallQuery`. +public class CursorOutParameter { + + # Parses returned SQL result set values to a ballerina stream value. + # + # + typeDesc - The `typedesc` of the record to which the result needs to be returned + # + return - Stream of records in the `rowType` type + public isolated function get(typedesc rowType = <>) returns stream = @java:Method { + 'class: "io.ballerina.stdlib.sql.nativeimpl.OutParameterProcessor", + name: "getOutCursorValue" + } external; +}; + # Represents SQL InOutParameter in `sql:ParameterizedCallQuery`. public class InOutParameter { Value 'in; @@ -1340,7 +1353,7 @@ public class InOutParameter { } # Generic type that can be passed to `sql:ParameterizedCallQuery` to indicate procedure/function parameters. -public type Parameter Value|InOutParameter|OutParameter; +public type Parameter Value|InOutParameter|OutParameter|CursorOutParameter; # The object constructed through backtick surrounded strings. Dynamic parameters of `sql:Parameter` type can be indicated using `${}` # such as `` `The sql:ParameterizedQuery is ${variable_name}` ``. diff --git a/native/src/main/java/io/ballerina/stdlib/sql/Constants.java b/native/src/main/java/io/ballerina/stdlib/sql/Constants.java index 92dfeaf7..1c7c1b4e 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/Constants.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/Constants.java @@ -297,6 +297,7 @@ private OutParameterTypes() { public static final String BOOLEAN = "BooleanOutParameter"; public static final String BOOLEAN_ARRAY = "BooleanArrayOutParameter"; public static final String REF = "RefOutParameter"; + public static final String REF_CURSOR = "CursorOutParameter"; public static final String STRUCT = "StructOutParameter"; public static final String XML = "XMLOutParameter"; } diff --git a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java index 17d8d70a..b0e5067f 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java @@ -334,6 +334,7 @@ private static void populateOutParameters(CallableStatement statement, BObject p result = resultParameterProcessor.processBoolean(statement, paramIndex); break; case Types.REF: + case Types.REF_CURSOR: result = resultParameterProcessor.processRef(statement, paramIndex); break; case Types.STRUCT: @@ -462,6 +463,9 @@ private static int getOutParameterType(BObject typedValue, case Constants.OutParameterTypes.REF: sqlTypeValue = Types.REF; break; + case Constants.OutParameterTypes.REF_CURSOR: + sqlTypeValue = Types.REF_CURSOR; + break; case Constants.OutParameterTypes.STRUCT: sqlTypeValue = Types.STRUCT; break; diff --git a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java index 9c711302..6871a8a8 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java @@ -19,9 +19,11 @@ package io.ballerina.stdlib.sql.nativeimpl; import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BStream; import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.stdlib.sql.Constants; import io.ballerina.stdlib.sql.exception.ApplicationError; @@ -35,6 +37,7 @@ import java.sql.Clob; import java.sql.Date; import java.sql.NClob; +import java.sql.ResultSet; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLXML; @@ -61,10 +64,22 @@ public static Object getOutParameterValue(BObject result, BTypedesc typeDesc) { return get(result, typeDesc, DefaultResultParameterProcessor.getInstance(), "OutParameter"); } + public static BStream getOutCursorValue(BObject result, BTypedesc typeDesc) { + return get(result, typeDesc, DefaultResultParameterProcessor.getInstance()); + } + public static Object getInOutParameterValue(BObject result, BTypedesc typeDesc) { return get(result, typeDesc, DefaultResultParameterProcessor.getInstance(), "InOutParameter"); } + public static BStream get(BObject result, Object recordType, + AbstractResultParameterProcessor resultParameterProcessor) { + Object value = result.getNativeData(Constants.ParameterObject.VALUE_NATIVE_DATA); + RecordType streamConstraint = (RecordType) TypeUtils.getReferredType( + ((BTypedesc) recordType).getDescribingType()); + return resultParameterProcessor.convertCursorValue((ResultSet) value, streamConstraint); + } + public static Object get(BObject result, BTypedesc typeDesc, AbstractResultParameterProcessor resultParameterProcessor, String parameterType) { int sqlType = (int) result.getNativeData(Constants.ParameterObject.SQL_TYPE_NATIVE_DATA); diff --git a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/QueryProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/QueryProcessor.java index b3662195..441c943d 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/QueryProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/QueryProcessor.java @@ -44,7 +44,6 @@ import io.ballerina.stdlib.sql.parameterprocessor.AbstractStatementParameterProcessor; import io.ballerina.stdlib.sql.utils.ColumnDefinition; import io.ballerina.stdlib.sql.utils.ErrorGenerator; -import io.ballerina.stdlib.sql.utils.ModuleUtils; import io.ballerina.stdlib.sql.utils.PrimitiveTypeColumnDefinition; import io.ballerina.stdlib.sql.utils.Utils; @@ -55,6 +54,7 @@ import java.util.List; import static io.ballerina.stdlib.sql.datasource.SQLWorkerThreadPool.SQL_EXECUTOR_SERVICE; +import static io.ballerina.stdlib.sql.utils.Utils.getErrorStream; /** * This class provides the query processing implementation which executes sql queries. @@ -266,17 +266,6 @@ private static Object getRecordOrPrimitiveTypeBValue( return createValue(resultSet, 1, definition, resultParameterProcessor); } - private static BStream getErrorStream(Object recordType, BError errorValue) { - return ValueCreator.createStreamValue( - TypeCreator.createStreamType(((BTypedesc) recordType).getDescribingType(), - PredefinedTypes.TYPE_NULL), createRecordIterator(errorValue)); - } - - private static BObject createRecordIterator(BError errorValue) { - return ValueCreator.createObjectValue(ModuleUtils.getModule(), Constants.RESULT_ITERATOR_OBJECT, - errorValue, null); - } - public static BMap createRecord(ResultSet resultSet, List columnDefinitions, RecordType recordConstraint, AbstractResultParameterProcessor resultParameterProcessor) diff --git a/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/AbstractResultParameterProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/AbstractResultParameterProcessor.java index 1a5cd68c..8edd7307 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/AbstractResultParameterProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/AbstractResultParameterProcessor.java @@ -19,12 +19,14 @@ import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.types.Field; +import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.StructureType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.utils.JsonUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BStream; import io.ballerina.runtime.api.values.BString; import io.ballerina.stdlib.sql.Constants; import io.ballerina.stdlib.sql.exception.ConversionError; @@ -116,6 +118,8 @@ public abstract Object convertBoolean(boolean value, int sqlType, Type type, boo public abstract Object convertStruct(Struct value, int sqlType, Type type) throws DataError, SQLException; + public abstract BStream convertCursorValue(ResultSet value, RecordType recordType); + public abstract Object convertXml(SQLXML value, int sqlType, Type type) throws DataError, SQLException; public abstract Object convertCustomOutParameter(Object value, String outParamObjectName, int sqlType, diff --git a/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java index ea1ce022..0220dd30 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java @@ -30,15 +30,21 @@ import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.utils.XmlUtils; import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BStream; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.api.values.BXml; import io.ballerina.stdlib.sql.Constants; +import io.ballerina.stdlib.sql.exception.ApplicationError; import io.ballerina.stdlib.sql.exception.DataError; import io.ballerina.stdlib.sql.exception.FieldMismatchError; import io.ballerina.stdlib.sql.exception.TypeMismatchError; import io.ballerina.stdlib.sql.exception.UnsupportedTypeError; +import io.ballerina.stdlib.sql.utils.ColumnDefinition; +import io.ballerina.stdlib.sql.utils.ErrorGenerator; +import io.ballerina.stdlib.sql.utils.ModuleUtils; import io.ballerina.stdlib.sql.utils.PrimitiveTypeColumnDefinition; import io.ballerina.stdlib.sql.utils.Utils; @@ -62,6 +68,7 @@ import java.util.List; import static io.ballerina.runtime.api.utils.StringUtils.fromString; +import static io.ballerina.stdlib.sql.utils.Utils.getErrorStream; /** * This class implements methods required convert SQL types into ballerina types and @@ -325,6 +332,30 @@ protected BMap createUserDefinedType(Struct structValue, Struct return struct; } + public BStream convertCursorValue(ResultSet resultSet, RecordType streamConstraint) { + if (resultSet == null) { + return null; + } + try { + List columnDefinitions = Utils.getColumnDefinitions(resultSet, streamConstraint); + BObject resultIterator = ValueCreator.createObjectValue(ModuleUtils.getModule(), + Constants.RESULT_ITERATOR_OBJECT, null, getBalStreamResultIterator()); + resultIterator.addNativeData(Constants.RESULT_SET_NATIVE_DATA_FIELD, resultSet); + resultIterator.addNativeData(Constants.COLUMN_DEFINITIONS_DATA_FIELD, columnDefinitions); + resultIterator.addNativeData(Constants.RECORD_TYPE_DATA_FIELD, streamConstraint); + return ValueCreator.createStreamValue(TypeCreator.createStreamType(streamConstraint, + PredefinedTypes.TYPE_NULL), + resultIterator); + } catch (ApplicationError applicationError) { + BError errorValue = ErrorGenerator.getSQLApplicationError(applicationError); + return getErrorStream(streamConstraint, errorValue); + } catch (SQLException sqlException) { + BError errorValue = ErrorGenerator.getSQLDatabaseError(sqlException, + "Error while retrieving column definition from result set."); + return getErrorStream(streamConstraint, errorValue); + } + } + @Override protected void createUserDefinedTypeSubtype(Field internalField, StructureType structType) throws DataError { diff --git a/native/src/main/java/io/ballerina/stdlib/sql/utils/Utils.java b/native/src/main/java/io/ballerina/stdlib/sql/utils/Utils.java index c7ba4d4d..019ce43c 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/utils/Utils.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/utils/Utils.java @@ -37,7 +37,9 @@ import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BMapInitialValueEntry; import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BStream; import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.api.values.BValue; import io.ballerina.runtime.transactions.TransactionResourceManager; import io.ballerina.stdlib.sql.Constants; @@ -1374,4 +1376,15 @@ public static void disableHikariLogs() { } } } + + public static BStream getErrorStream(Object recordType, BError errorValue) { + return ValueCreator.createStreamValue( + TypeCreator.createStreamType(((BTypedesc) recordType).getDescribingType(), + PredefinedTypes.TYPE_NULL), createRecordIterator(errorValue)); + } + + private static BObject createRecordIterator(BError errorValue) { + return ValueCreator.createObjectValue(ModuleUtils.getModule(), Constants.RESULT_ITERATOR_OBJECT, + errorValue, null); + } } From 736eccacfd48d1faebefe99cf39d5a171f39a6c5 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Wed, 21 Feb 2024 15:41:11 +0530 Subject: [PATCH 07/12] Change the spec to add new out parameter --- ballerina/types.bal | 2 +- changelog.md | 1 + docs/spec/spec.md | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ballerina/types.bal b/ballerina/types.bal index 4020e5f0..2ecff877 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -1321,7 +1321,7 @@ public distinct class XMLOutParameter { } external; } -# Represents the generic OUT Cursor Parameters in `sql:ParameterizedCallQuery`. +# Represents the Cursor Out Parameters in `sql:ParameterizedCallQuery`. public class CursorOutParameter { # Parses returned SQL result set values to a ballerina stream value. diff --git a/changelog.md b/changelog.md index aaa2eb2c..d16211c1 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Support for Cursor based result set retrieval in procedure calls ### Changed - [Revert Accept escaped backtick as insertions in parameterised query](https://github.com/ballerina-platform/ballerina-standard-library/issues/2056) diff --git a/docs/spec/spec.md b/docs/spec/spec.md index 7a2b4cea..d68946f1 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -240,6 +240,24 @@ These types can be used to retrieve values from SQL stored procedures using the ``` Type of the returned value is inferred from LHS of the expression. +In addition to the above parameters, it has `CursorOutParameter` to retrieve the result set from the SQL stored procedure. + + ```ballerina + # Parses returned SQL result set values to a ballerina stream value. + # + # + typeDesc - The `typedesc` of the record to which the result needs to be returned + # + return - Stream of records in the `rowType` type + public isolated function get(typedesc typeDesc = <>) returns stream; + ``` + + ```ballerina + CursorOutParameter cursor = new; + + // Execute the DB call method + + stream resultStream = cursor.get(); + ``` + ## 3.3. Query concatenation `sql:ParameterizedQuery` can be concatenated using util methods such as `sql:queryConcat()` and From 22d315d3d4881078bea5aca8a55e91b067b7b941 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Wed, 21 Feb 2024 16:08:43 +0530 Subject: [PATCH 08/12] Update ballerina/Dependencies.toml --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 3e7adf48..debcc15f 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.9.0-20231211-150600-888c06e1" +distribution-version = "2201.8.0 [[package]] org = "ballerina" From 0183d8ec5dde4a43d30d06a217222cfcded9fb1d Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Wed, 21 Feb 2024 16:08:57 +0530 Subject: [PATCH 09/12] Update ballerina/Dependencies.toml --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index debcc15f..2c1c4283 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.0 +distribution-version = "2201.8.0" [[package]] org = "ballerina" From 4c4352e2437820a600aa5e3dcfe55f58e5d60242 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Thu, 22 Feb 2024 11:54:50 +0530 Subject: [PATCH 10/12] [Automated] Update native jar versions in toml files --- ballerina/Dependencies.toml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 3e7adf48..4877c40f 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.9.0-20231211-150600-888c06e1" +distribution-version = "2201.8.0" [[package]] org = "ballerina" @@ -23,7 +23,7 @@ dependencies = [ [[package]] org = "ballerina" name = "cache" -version = "3.7.0" +version = "3.7.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "constraint"}, @@ -69,7 +69,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.10.5" +version = "2.10.6" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -282,7 +282,7 @@ dependencies = [ [[package]] org = "ballerina" name = "observe" -version = "1.2.0" +version = "1.2.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} @@ -345,6 +345,7 @@ modules = [ org = "ballerina" name = "time" version = "2.4.0" +scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] From cbb7a2d97f2a8aad411e4a91a9e2627ea02db70d Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Thu, 22 Feb 2024 15:37:44 +0530 Subject: [PATCH 11/12] Add logic to clean up the resultset along with proc result close --- .../main/java/io/ballerina/stdlib/sql/Constants.java | 1 + .../stdlib/sql/nativeimpl/CallProcessor.java | 7 +++++-- .../stdlib/sql/utils/ProcedureCallResultUtils.java | 11 +++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/native/src/main/java/io/ballerina/stdlib/sql/Constants.java b/native/src/main/java/io/ballerina/stdlib/sql/Constants.java index 1c7c1b4e..71cbad2d 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/Constants.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/Constants.java @@ -56,6 +56,7 @@ private Constants() { public static final String STATEMENT_NATIVE_DATA_FIELD = "Statement"; public static final String COLUMN_DEFINITIONS_DATA_FIELD = "ColumnDefinition"; public static final String RECORD_TYPE_DATA_FIELD = "recordType"; + public static final String REF_CURSOR_VALUE_NATIVE_DATA = "RefCursorValue"; public static final String PROCEDURE_CALL_RESULT = "ProcedureCallResult"; public static final String TYPE_DESCRIPTIONS_NATIVE_DATA_FIELD = "TypeDescription"; diff --git a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java index b0e5067f..7ca42d4d 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java @@ -159,7 +159,7 @@ private static Object nativeCallExecutable(BObject client, BObject paramSQLStrin } populateOutParameters(statement, paramSQLString, outputParamTypes, - resultParameterProcessor); + resultParameterProcessor, procedureCallResult); procedureCallResult.addNativeData(STATEMENT_NATIVE_DATA_FIELD, statement); procedureCallResult.addNativeData(CONNECTION_NATIVE_DATA_FIELD, connection); @@ -227,7 +227,8 @@ private static void setCallParameters(Connection connection, CallableStatement s private static void populateOutParameters(CallableStatement statement, BObject paramSQLString, HashMap outputParamTypes, - AbstractResultParameterProcessor resultParameterProcessor) + AbstractResultParameterProcessor resultParameterProcessor, + BObject procedureCallResult) throws SQLException, ApplicationError { if (outputParamTypes.size() == 0) { return; @@ -336,6 +337,8 @@ private static void populateOutParameters(CallableStatement statement, BObject p case Types.REF: case Types.REF_CURSOR: result = resultParameterProcessor.processRef(statement, paramIndex); + // This is to clean up the result set attached to the ref cursor out parameter when procedure call result is closed. + procedureCallResult.addNativeData(Constants.REF_CURSOR_VALUE_NATIVE_DATA, result); break; case Types.STRUCT: result = resultParameterProcessor.processStruct(statement, paramIndex); diff --git a/native/src/main/java/io/ballerina/stdlib/sql/utils/ProcedureCallResultUtils.java b/native/src/main/java/io/ballerina/stdlib/sql/utils/ProcedureCallResultUtils.java index 6d4b6012..69255e93 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/utils/ProcedureCallResultUtils.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/utils/ProcedureCallResultUtils.java @@ -114,6 +114,17 @@ public static Object getNextQueryResult( public static Object closeCallResult(BObject procedureCallResult) { Statement statement = (Statement) procedureCallResult.getNativeData(Constants.STATEMENT_NATIVE_DATA_FIELD); Connection connection = (Connection) procedureCallResult.getNativeData(Constants.CONNECTION_NATIVE_DATA_FIELD); + // This is to clean up the result set attached to the ref cursor out parameter. + // This is to avoid the result set to be open after the call result is closed. + Object resultSet = procedureCallResult.getNativeData(Constants.REF_CURSOR_VALUE_NATIVE_DATA); + if (resultSet instanceof ResultSet) { + try { + ((ResultSet) resultSet).close(); + procedureCallResult.addNativeData(Constants.REF_CURSOR_VALUE_NATIVE_DATA, null); + } catch (SQLException e) { + return ErrorGenerator.getSQLDatabaseError(e, "Error when closing the result set."); + } + } return cleanUpConnection(procedureCallResult, null, statement, connection); } } From 750a77ce17dcf17ad36ef9040beda9527ed51d06 Mon Sep 17 00:00:00 2001 From: Danesh Kuruppu Date: Thu, 22 Feb 2024 16:49:03 +0530 Subject: [PATCH 12/12] fix checkstyle issue --- .../java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java index 7ca42d4d..1ec68153 100644 --- a/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java +++ b/native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java @@ -337,7 +337,8 @@ private static void populateOutParameters(CallableStatement statement, BObject p case Types.REF: case Types.REF_CURSOR: result = resultParameterProcessor.processRef(statement, paramIndex); - // This is to clean up the result set attached to the ref cursor out parameter when procedure call result is closed. + // This is to clean up the result set attached to the ref cursor out parameter + // when procedure call result is closed. procedureCallResult.addNativeData(Constants.REF_CURSOR_VALUE_NATIVE_DATA, result); break; case Types.STRUCT: