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

1660 SqlUtil op_in() for 0.8.12 #1666

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions doxygen/lang/900_release_notes.dox.tmpl
Expand Up @@ -12,6 +12,8 @@
- fixed bug in internal string generation with \c size_t arguments that could cause invalid data to be output or crashes on 32-bit platforms (<a href="https://github.com/qorelanguage/qore/issues/1640">issue 1640</a>)
- fixed a runtime memory leak and invalid runtime behavior with undetected recursive lvalue references (<a href="https://github.com/qorelanguage/qore/issues/1617">issue 1617</a>)
- improved @ref garbage_collection "prompt collection" performance with large graphs of objects by eliminating additional unnecessary graph scans, resulting in further large performance improvements in the garbage collector (<a href="https://github.com/qorelanguage/qore/issues/1363">issue 1363</a>)
- <a href="../../modules/OracleSqlUtil/html/index.html">OracleSqlUtil</a> module fixes:
- worked around ORA-22165 from op_in() caused by Oracle's limit on number of collection elements (<a href="https://github.com/qorelanguage/qore/issues/1660">issue 1660</a>)

@section qore_08126 Qore 0.8.12.6

Expand Down
24 changes: 24 additions & 0 deletions examples/test/qlib/SqlUtil/SqlUtilTestBase.qm
Expand Up @@ -514,6 +514,26 @@ public class SqlTestBase inherits QUnit::Test {
"data": (("id": 1),),
),
),
"op_in_empty": (
"in": (
"where": ("id": op_in(list())),
),
"out": (
"count": 0,
"data": (),
),
),
"op_in_large": (
"in": (
"where": ("id": op_in(range(32767))), # value 32767 is enough to trigger Oracle's ORA-22165
"orderby": ("id",)
),
"out": (
"count": 2,
"data": (("id": 1), ("id": 2)),
),
"skip_for": ("FreetdsTest"), # TODO: remove once support is implemented in FreetdsSqlUtil
),
"op_not": (
"in": (
"where": ("id": op_not (op_in((0,1,3)))),
Expand Down Expand Up @@ -619,6 +639,10 @@ public class SqlTestBase inherits QUnit::Test {
);

foreach hash t in (test_set.pairIterator()) {
if (inlist (self.className(), t.value.skip_for)) {
assertSkip (t.value.skip_for + " might fail this test");
continue;
}
*list rows = table.selectRows (t.value.in, \sql);
hash out = t.value.out;
assertEq (out.count, rows.size(), "checking where operator " + t.key);
Expand Down
40 changes: 26 additions & 14 deletions qlib/OracleSqlUtil.qm
Expand Up @@ -257,6 +257,7 @@ my hash $schema = (

@subsection v121 OracleSqlUtil v1.2.1
- implemented the \a force option (i.e. cascade) for dropping code objects (<a href="https://github.com/qorelanguage/qore/issues/1314">issue 1314</a>)
- worked around ORA-22165 from op_in() caused by Oracle's limit on number of collection elements (<a href="https://github.com/qorelanguage/qore/issues/1660">issue 1660</a>)

@subsection v12 OracleSqlUtil v1.2
- implemented support for the \c "returning" clause as an insert option
Expand Down Expand Up @@ -1837,8 +1838,8 @@ my any $v = $c.name;
case NT_NOTHING:
continue;
case NT_DATE:
case NT_FLOAT:
case NT_INT:
case NT_FLOAT:
case NT_NUMBER:
case NT_STRING:
ltype = it.getValue().typeCode();
Expand All @@ -1849,21 +1850,32 @@ my any $v = $c.name;
if (ltype) break;
}

# Bind to oracle by expected type
switch (ltype) {
case NT_DATE:
args += bindOracleCollection("SYS.ODCIDATELIST", arg);
break;
case NT_FLOAT:
case NT_NUMBER:
case NT_INT:
args += bindOracleCollection("SYS.ODCINUMBERLIST", arg);
break;
default:
args += bindOracleCollection("SYS.ODCIVARCHAR2LIST", arg);
# Split long array to chunks of no more than 32767 elements due to Oracle limitation
# "ORA-22165: OCI-22165: given index [32767] must be in the range of [0] to [32766]"
int count;
while (arg.size()) {
++count;
list chunk = extract arg, 0, 32767;

# Bind to Oracle by expected type
switch (ltype) {
case NT_DATE:
args += bindOracleCollection("SYS.ODCIDATELIST", chunk);
break;
case NT_INT:
case NT_FLOAT:
case NT_NUMBER:
args += bindOracleCollection("SYS.ODCINUMBERLIST", chunk);
break;
default:
args += bindOracleCollection("SYS.ODCIVARCHAR2LIST", chunk);
}
}

return cn + " in (select column_value from table(%v))";
if (count)
return cn + " in (" + (map "select column_value from table(%v)", xrange(1,count)).join(" union all ") + ")";
else
return "1 != 1";
%endif
%ifdef NO_ORACLE
throw "MISSING-ORACLE-DRIVER", "op_in requires oracle driver";
Expand Down
4 changes: 4 additions & 0 deletions qlib/SqlUtil.qm
Expand Up @@ -3826,6 +3826,8 @@ int rows_updated = t.update(("counter": uop_divide(2)));
@endcode

@return a where operation description hash for use in @ref where_clauses "where clauses"

@note Number of arguments may be constrained depending on the database server / driver used. Too many arguments may be a sign of an improper application design.
*/
public hash sub op_in() {
return make_op(OP_IN, argv);
Expand All @@ -3840,6 +3842,8 @@ int rows_updated = t.update(("counter": uop_divide(2)));
@param args a list of values for the \c "in" operator

@return a where operation description hash for use in @ref where_clauses "where clauses"

@note The argument list size may be constrained depending on the database server / driver used. Too long list may be a sign of an improper application design.
*/
public hash sub op_in(list args) {
return make_op(OP_IN, args);
Expand Down