Skip to content

Commit

Permalink
Add Ref Cursor support for the procedure call
Browse files Browse the repository at this point in the history
  • Loading branch information
daneshk committed Feb 21, 2024
1 parent b1bb550 commit c6e9683
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 13 deletions.
15 changes: 14 additions & 1 deletion ballerina/types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -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<record {}> rowType = <>) returns stream <rowType, Error?> = @java:Method {
'class: "io.ballerina.stdlib.sql.nativeimpl.OutParameterProcessor",
name: "getOutCursorValue"
} external;

Check warning on line 1334 in ballerina/types.bal

View check run for this annotation

Codecov / codecov/patch

ballerina/types.bal#L1334

Added line #L1334 was not covered by tests
};

# Represents SQL InOutParameter in `sql:ParameterizedCallQuery`.
public class InOutParameter {
Value 'in;
Expand All @@ -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 `${<variable name>}`
# such as `` `The sql:ParameterizedQuery is ${variable_name}` ``.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;

Check warning on line 468 in native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/CallProcessor.java#L467-L468

Added lines #L467 - L468 were not covered by tests
case Constants.OutParameterTypes.STRUCT:
sqlTypeValue = Types.STRUCT;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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());

Check warning on line 68 in native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java#L68

Added line #L68 was not covered by tests
}

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);

Check warning on line 80 in native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/nativeimpl/OutParameterProcessor.java#L77-L80

Added lines #L77 - L80 were not covered by tests
}

public static Object get(BObject result, BTypedesc typeDesc,
AbstractResultParameterProcessor resultParameterProcessor, String parameterType) {
int sqlType = (int) result.getNativeData(Constants.ParameterObject.SQL_TYPE_NATIVE_DATA);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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.
Expand Down Expand Up @@ -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<BString, Object> createRecord(ResultSet resultSet, List<ColumnDefinition> columnDefinitions,
RecordType recordConstraint,
AbstractResultParameterProcessor resultParameterProcessor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -325,6 +332,30 @@ protected BMap<BString, Object> createUserDefinedType(Struct structValue, Struct
return struct;
}

public BStream convertCursorValue(ResultSet resultSet, RecordType streamConstraint) {
if (resultSet == null) {
return null;

Check warning on line 337 in native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java#L337

Added line #L337 was not covered by tests
}
try {
List<ColumnDefinition> 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,

Check warning on line 346 in native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java#L340-L346

Added lines #L340 - L346 were not covered by tests
PredefinedTypes.TYPE_NULL),
resultIterator);
} catch (ApplicationError applicationError) {
BError errorValue = ErrorGenerator.getSQLApplicationError(applicationError);
return getErrorStream(streamConstraint, errorValue);
} catch (SQLException sqlException) {
BError errorValue = ErrorGenerator.getSQLDatabaseError(sqlException,

Check warning on line 353 in native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java#L349-L353

Added lines #L349 - L353 were not covered by tests
"Error while retrieving column definition from result set.");
return getErrorStream(streamConstraint, errorValue);

Check warning on line 355 in native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java

View check run for this annotation

Codecov / codecov/patch

native/src/main/java/io/ballerina/stdlib/sql/parameterprocessor/DefaultResultParameterProcessor.java#L355

Added line #L355 was not covered by tests
}
}

@Override
protected void createUserDefinedTypeSubtype(Field internalField, StructureType structType)
throws DataError {
Expand Down
13 changes: 13 additions & 0 deletions native/src/main/java/io/ballerina/stdlib/sql/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

0 comments on commit c6e9683

Please sign in to comment.