Skip to content

Commit a9ce0d9

Browse files
authored
Support for calling stored prcoedure with array parameter (#1048)
* Support for calling stored prcoedure array parameter Signed-off-by: Earamma K <ek@rocketsoftware.com>
1 parent 53fdf2f commit a9ce0d9

8 files changed

Lines changed: 2372 additions & 7 deletions

ibm_db.c

Lines changed: 1196 additions & 7 deletions
Large diffs are not rendered by default.

ibm_db_tests/test_ArrayTypeAndSPCreation.py

Lines changed: 591 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from __future__ import print_function
2+
import unittest
3+
import ibm_db
4+
import config
5+
from datetime import date, time, datetime
6+
from testfunctions import IbmDbTestFunctions
7+
8+
class IbmDbTestCase(unittest.TestCase):
9+
10+
def test_scalarsp_create(self):
11+
obj = IbmDbTestFunctions()
12+
obj.assert_expectf(self.run_test_scalarsp_create)
13+
14+
def run_test_scalarsp_create(self):
15+
conn = ibm_db.connect(config.database, config.user, config.password)
16+
if not conn:
17+
print("no connection")
18+
return
19+
scalar_types = [
20+
("int_scalar", "INTEGER"),
21+
("sint_scalar", "SMALLINT"),
22+
("bint_scalar", "BIGINT"),
23+
("float_scalar", "FLOAT"),
24+
("double_scalar", "DOUBLE"),
25+
("real_scalar", "REAL"),
26+
("decfloat16_scalar", "DECFLOAT(16)"),
27+
("decfloat34_scalar", "DECFLOAT(34)"),
28+
("decimal_scalar", "DECIMAL(10,2)"),
29+
("date_scalar", "DATE"),
30+
("time_scalar", "TIME"),
31+
("ts_scalar", "TIMESTAMP"),
32+
]
33+
for proc_name, base_type in scalar_types:
34+
try:
35+
ibm_db.exec_immediate(conn, f"DROP PROCEDURE {proc_name}")
36+
except:
37+
pass
38+
if base_type in ["INTEGER", "SMALLINT", "BIGINT"]:
39+
operation = "SET var2 = var1 + 1;"
40+
elif base_type in ["FLOAT", "DOUBLE", "REAL"]:
41+
operation = "SET var2 = var1 + 1.0;"
42+
elif base_type in ["DECFLOAT(16)", "DECFLOAT(34)", "DECIMAL(10,2)"]:
43+
operation = "SET var2 = var1 + Decimal(1.25);"
44+
elif base_type == "DATE":
45+
operation = "SET var2 = var1 + 1 DAY;"
46+
elif base_type == "TIME":
47+
operation = "SET var2 = var1 + 1 MINUTE;"
48+
elif base_type == "TIMESTAMP":
49+
operation = "SET var2 = var1 + 1 SECOND;"
50+
else:
51+
operation = "SET var2 = var1;"
52+
ibm_db.exec_immediate(conn, f"""
53+
CREATE PROCEDURE {proc_name}(IN var1 {base_type}, OUT var2 {base_type})
54+
LANGUAGE SQL
55+
BEGIN
56+
{operation}
57+
END
58+
""")
59+
print("Preparation complete: scalar stored procedures with safe operations created.")
60+
61+
#__END__
62+
#__LUW_EXPECTED__
63+
#Preparation complete: scalar stored procedures with safe operations created.
64+
#__ZOS_EXPECTED__
65+
#... same as LUW ...
66+
#__SYSTEMI_EXPECTED__
67+
#... same as LUW ...
68+
#__IDS_EXPECTED__
69+
#... same as LUW ...
70+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from __future__ import print_function
2+
import unittest
3+
import ibm_db
4+
import config
5+
from datetime import date, time, datetime
6+
from testfunctions import IbmDbTestFunctions
7+
8+
class IbmDbTestCase(unittest.TestCase):
9+
10+
def test_scalarsp_execute(self):
11+
obj = IbmDbTestFunctions()
12+
obj.assert_expectf(self.run_test_scalarsp_execute)
13+
14+
def run_test_scalarsp_execute(self):
15+
conn = ibm_db.connect(config.database, config.user, config.password)
16+
if not conn:
17+
print("no connection")
18+
return
19+
scalar_procs = [
20+
("INTEGER", "int_scalar", 42),
21+
("SMALLINT", "sint_scalar", 7),
22+
("BIGINT", "bint_scalar", 1234),
23+
("FLOAT", "float_scalar", 3.14),
24+
("DOUBLE", "double_scalar", 20.25),
25+
("REAL", "real_scalar", 1.5),
26+
("DECFLOAT(16)", "decfloat16_scalar", 4.56),
27+
("DECFLOAT(34)", "decfloat34_scalar", 123456.1234),
28+
("DECIMAL(10,2)", "decimal_scalar", 56.78),
29+
("DATE", "date_scalar", date(2025, 1, 1)),
30+
("TIME", "time_scalar", time(12, 20, 30)),
31+
("TIMESTAMP", "ts_scalar", datetime(1989, 2, 12, 23, 55, 59)),
32+
]
33+
34+
for base_type, proc_name, input_val in scalar_procs:
35+
sql = f"CALL {proc_name}(?, ?)"
36+
stmt = ibm_db.prepare(conn, sql)
37+
output_val = input_val
38+
39+
ibm_db.bind_param(stmt, 1, input_val, ibm_db.SQL_PARAM_INPUT)
40+
ibm_db.bind_param(stmt, 2, output_val, ibm_db.SQL_PARAM_OUTPUT)
41+
42+
ibm_db.execute(stmt)
43+
result = ibm_db.fetch_callproc(stmt)
44+
print(f"Procedure: {proc_name} {base_type} input: {result[1]} {base_type} output: {result[2]}")
45+
46+
47+
48+
#__END__
49+
#__LUW_EXPECTED__
50+
#Procedure: int_scalar INTEGER input: 42 INTEGER output: 43
51+
#Procedure: sint_scalar SMALLINT input: 7 SMALLINT output: 8
52+
#Procedure: bint_scalar BIGINT input: 1234 BIGINT output: 1235
53+
#Procedure: float_scalar FLOAT input: 3.14 FLOAT output: 4.140000000000001
54+
#Procedure: double_scalar DOUBLE input: 20.25 DOUBLE output: 21.25
55+
#Procedure: real_scalar REAL input: 1.5 REAL output: 2.5
56+
#Procedure: decfloat16_scalar DECFLOAT(16) input: 4.56 DECFLOAT(16) output: 5.56
57+
#Procedure: decfloat34_scalar DECFLOAT(34) input: 123456.1234 DECFLOAT(34) output: 123457.1234
58+
#Procedure: decimal_scalar DECIMAL(10,2) input: 56.78 DECIMAL(10,2) output: 57.78
59+
#Procedure: date_scalar DATE input: 2025-01-01 DATE output: 2025-01-02
60+
#Procedure: time_scalar TIME input: 12:20:30 TIME output: 12:21:30
61+
#Procedure: ts_scalar TIMESTAMP input: 1989-02-12 23:55:59 TIMESTAMP output: 1989-02-12 23:56:00
62+
#__ZOS_EXPECTED__
63+
#... same as LUW ...
64+
#__SYSTEMI_EXPECTED__
65+
#... same as LUW ...
66+
#__IDS_EXPECTED__
67+
#... same as LUW ...
68+
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
from __future__ import print_function
2+
import unittest
3+
import ibm_db
4+
import config
5+
from datetime import date, time, datetime
6+
from testfunctions import IbmDbTestFunctions
7+
8+
class IbmDbTestCase(unittest.TestCase):
9+
10+
def test_sparray_cardinalities(self):
11+
obj = IbmDbTestFunctions()
12+
obj.assert_expectf(self.run_test_sparray_cardinalities)
13+
14+
def run_test_sparray_cardinalities(self):
15+
conn = ibm_db.connect(config.database, config.user, config.password)
16+
if not conn:
17+
print("no connection")
18+
return
19+
array_procs = [
20+
("int_array", "array_int12", [1, 2, 3, 4, 5, None]),
21+
("sint_array", "array_sint12", [7, 512, -29000, 32000]),
22+
("bint_array", "array_bint12", [1234567890123, None,-9876543210]),
23+
("float_array", "array_float12", [1.1, 2.2, 3.3]),
24+
("double_array", "array_double12", [10.5, 20.25, 30.75]),
25+
("real_array", "array_real12", [0.5, 1.5, 2.5]),
26+
("decfloat16_array", "array_decfloat1612", [1.23,None, 4.56, None]),
27+
("decfloat34_array", "array_decfloat3412", [1234567890.1234, None]),
28+
("decimal_array", "array_decimal12", [12.34, None, 56.78]),
29+
("time_array", "array_time12", [time(12, 20, 30), time(13, 30, 45)]),
30+
("date_array", "array_date12", [date(2025, 1, 1), date(2025, 12, 31)]),
31+
("ts_array", "array_ts12", [b'1981-07-08 10:42:34.000010',None, b'1982-07-08 10:42:34.000010']),
32+
("ts_array", "array_ts12", [ datetime(1989, 2, 12, 23, 55, 59, 342380), datetime(1990, 2, 12, 23, 55, 59, 342380)]),
33+
("char_array", "array_char12", ["abc", "defg", "jkl"]),
34+
("char_array", "array_char12", [b'abc', b'defg']),
35+
("vc_array", "array_vc12", ["hello", "world"]),
36+
("vc_array", "array_vc12", [b'hello', b'world']),
37+
("vcfbd_array", "array_vcfbd12",[b'abc', b'dog', b'deadbeef', None, b'foobar']),
38+
("clob_array", "array_clob12", [b'long text here', b'another clob']),
39+
("blob_array", "array_blob12", [b"binarydata", b"morebytes", None, b'abc'])
40+
]
41+
for type_name, proc_name, input_array in array_procs:
42+
sql = f"CALL {proc_name}(?,?)"
43+
stmt = ibm_db.prepare(conn, sql)
44+
output = 0
45+
46+
ibm_db.bind_param(stmt, 1, input_array, ibm_db.SQL_PARAM_INPUT)
47+
ibm_db.bind_param(stmt, 2, output, ibm_db.SQL_PARAM_OUTPUT, ibm_db.SQL_INTEGER)
48+
49+
ibm_db.execute(stmt)
50+
inout_value = ibm_db.fetch_callproc(stmt)
51+
52+
print(f"Procedure : {proc_name}")
53+
print(f"{type_name} input:", inout_value[1])
54+
print(f"{type_name} cardinality:", inout_value[2])
55+
56+
#__END__
57+
#__LUW_EXPECTED__
58+
#Procedure : array_int12
59+
#int_array input: [1, 2, 3, 4, 5, None]
60+
#int_array cardinality: 6
61+
#Procedure : array_sint12
62+
#sint_array input: [7, 512, -29000, 32000]
63+
#sint_array cardinality: 4
64+
#Procedure : array_bint12
65+
#bint_array input: [1234567890123, None, -9876543210]
66+
#bint_array cardinality: 3
67+
#Procedure : array_float12
68+
#float_array input: [1.1, 2.2, 3.3]
69+
#float_array cardinality: 3
70+
#Procedure : array_double12
71+
#double_array input: [10.5, 20.25, 30.75]
72+
#double_array cardinality: 3
73+
#Procedure : array_real12
74+
#real_array input: [0.5, 1.5, 2.5]
75+
#real_array cardinality: 3
76+
#Procedure : array_decfloat1612
77+
#decfloat16_array input: [1.23, None, 4.56, None]
78+
#decfloat16_array cardinality: 4
79+
#Procedure : array_decfloat3412
80+
#decfloat34_array input: [1234567890.1234, None]
81+
#decfloat34_array cardinality: 2
82+
#Procedure : array_decimal12
83+
#decimal_array input: [12.34, None, 56.78]
84+
#decimal_array cardinality: 3
85+
#Procedure : array_time12
86+
#time_array input: [datetime.time(12, 20, 30), datetime.time(13, 30, 45)]
87+
#time_array cardinality: 2
88+
#Procedure : array_date12
89+
#date_array input: [datetime.date(2025, 1, 1), datetime.date(2025, 12, 31)]
90+
#date_array cardinality: 2
91+
#Procedure : array_ts12
92+
#ts_array input: [b'1981-07-08 10:42:34.000010', None, b'1982-07-08 10:42:34.000010']
93+
#ts_array cardinality: 3
94+
#Procedure : array_ts12
95+
#ts_array input: [datetime.datetime(1989, 2, 12, 23, 55, 59, 342380), datetime.datetime(1990, 2, 12, 23, 55, 59, 342380)]
96+
#ts_array cardinality: 2
97+
#Procedure : array_char12
98+
#char_array input: ['abc', 'defg', 'jkl']
99+
#char_array cardinality: 3
100+
#Procedure : array_char12
101+
#char_array input: [b'abc', b'defg']
102+
#char_array cardinality: 2
103+
#Procedure : array_vc12
104+
#vc_array input: ['hello', 'world']
105+
#vc_array cardinality: 2
106+
#Procedure : array_vc12
107+
#vc_array input: [b'hello', b'world']
108+
#vc_array cardinality: 2
109+
#Procedure : array_vcfbd12
110+
#vcfbd_array input: [b'abc', b'dog', b'deadbeef', None, b'foobar']
111+
#vcfbd_array cardinality: 5
112+
#Procedure : array_clob12
113+
#clob_array input: [b'long text here', b'another clob']
114+
#clob_array cardinality: 2
115+
#Procedure : array_blob12
116+
#blob_array input: [b'binarydata', b'morebytes', None, b'abc']
117+
#blob_array cardinality: 4
118+
#__ZOS_EXPECTED__
119+
#... same as LUW ...
120+
#__SYSTEMI_EXPECTED__
121+
#... same as LUW ...
122+
#__IDS_EXPECTED__
123+
#... same as LUW ...
124+
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from __future__ import print_function
2+
import unittest
3+
import ibm_db
4+
import config
5+
from datetime import date, time, datetime
6+
from testfunctions import IbmDbTestFunctions
7+
8+
class IbmDbTestCase(unittest.TestCase):
9+
10+
def test_sparray_computations(self):
11+
obj = IbmDbTestFunctions()
12+
obj.assert_expectf(self.run_test_sparray_computations)
13+
14+
def run_test_sparray_computations(self):
15+
conn = ibm_db.connect(config.database, config.user, config.password)
16+
if not conn:
17+
print("no connection")
18+
return
19+
scalar_procs = [
20+
("int_array", "array_int22", 7),
21+
("sint_array", "array_sint22", 10),
22+
("bint_array", "array_bint22", 12345),
23+
("float_array", "array_float22", 3.14),
24+
("double_array", "array_double22", 20.25),
25+
("real_array", "array_real22", 1.5),
26+
("decfloat16_array", "array_decfloat1622", 4.56),
27+
("decfloat34_array", "array_decfloat3422", 123456.1234),
28+
("decimal_array", "array_decimal22", 56.78),
29+
("time_array", "array_time22", time(12, 20, 30)),
30+
("date_array", "array_date22", date(2025, 1, 1)),
31+
("ts_array", "array_ts22", datetime(1989, 2, 12, 23, 55, 59, 342380)),
32+
("char_array", "array_char22", b'HelloWorld'),
33+
("vc_array", "array_vc22", b'basketball'),
34+
("vcfbd_array", "array_vcfbd22", b'foobar'),
35+
]
36+
for type_name, proc_name, input_val in scalar_procs:
37+
sql = f"CALL {proc_name}(?, ?)"
38+
stmt = ibm_db.prepare(conn, sql)
39+
output_array = [input_val]*4
40+
41+
ibm_db.bind_param(stmt, 1, input_val, ibm_db.SQL_PARAM_INPUT)
42+
ibm_db.bind_param(stmt, 2, output_array, ibm_db.SQL_PARAM_OUTPUT)
43+
44+
ibm_db.execute(stmt)
45+
result = ibm_db.fetch_callproc(stmt)
46+
ibm_db.debug(False)
47+
48+
print(f"Procedure: {proc_name}")
49+
print(f"{type_name} input:", input_val)
50+
print(f"{type_name} output array:", result[2])
51+
52+
#__END__
53+
#__LUW_EXPECTED__
54+
#Procedure: array_int22
55+
#int_array input: 7
56+
#int_array output array: [49, 343, 28, 2]
57+
#Procedure: array_sint22
58+
#sint_array input: 10
59+
#sint_array output array: [100, 1000, 40, 5]
60+
#Procedure: array_bint22
61+
#bint_array input: 12345
62+
#bint_array output array: [152399025, 1881365963625, 49380, 12340]
63+
#Procedure: array_float22
64+
#float_array input: 3.14
65+
#float_array output array: [9.8596, 30.959144000000002, 12.56, -1.8599999999999999]
66+
#Procedure: array_double22
67+
#double_array input: 20.25
68+
#double_array output array: [410.0625, 8303.765625, 81.0, 15.25]
69+
#Procedure: array_real22
70+
#real_array input: 1.5
71+
#real_array output array: [2.25, 3.375, 6.0, -3.5]
72+
#Procedure: array_decfloat1622
73+
#decfloat16_array input: 4.56
74+
#decfloat16_array output array: [20.7936, 94.818816, 18.24, -0.44]
75+
#Procedure: array_decfloat3422
76+
#decfloat34_array input: 123456.1234
77+
#decfloat34_array output array: [15241414404.956028, 1881645937568789.0, 493824.4936, 123451.1234]
78+
#Procedure: array_decimal22
79+
#decimal_array input: 56.78
80+
#decimal_array output array: [3223.96, 183056.92, 227.12, 51.78]
81+
#Procedure: array_time22
82+
#time_array input: 12:20:30
83+
#time_array output array: [datetime.time(13, 21, 31), datetime.time(11, 19, 29), datetime.time(12, 20, 31), datetime.time(12, 20, 29)]
84+
#Procedure: array_date22
85+
#date_array input: 2025-01-01
86+
#date_array output array: [datetime.date(2026, 2, 2), datetime.date(2023, 11, 30), datetime.date(2025, 1, 2), datetime.date(2024, 12, 31)]
87+
#Procedure: array_ts22
88+
#ts_array input: 1989-02-12 23:55:59.342380
89+
#ts_array output array: [datetime.datetime(1990, 3, 14, 0, 57, 0, 342380), datetime.datetime(1988, 1, 11, 22, 54, 58, 342380), datetime.datetime(1989, 2, 13, 23, 56, 0, 342380), datetime.datetime(1989, 2, 11, 23, 55, 58, 342380)]
90+
#Procedure: array_char22
91+
#char_array input: b'HelloWorld'
92+
#char_array output array: [b'HelloWorld ', b'HelloWorld ', b'Hell ', b' ']
93+
#Procedure: array_vc22
94+
#vc_array input: b'basketball'
95+
#vc_array output array: [b'basketballbasketbal', b'basketballbasketbal', b'bask', b'tball']
96+
#Procedure: array_vcfbd22
97+
#vcfbd_array input: b'foobar'
98+
#vcfbd_array output array: [b'foobarfoobar', b'foobarfoobarfoobar', b'foobar', b'oobarr']
99+
#__ZOS_EXPECTED__
100+
#... same as LUW ...
101+
#__SYSTEMI_EXPECTED__
102+
#... same as LUW ...
103+
#__IDS_EXPECTED__
104+
#... same as LUW ...
105+

0 commit comments

Comments
 (0)