Skip to content

Commit

Permalink
Merge pull request #2402 from zspitzer/LDEV-5023-qoq-regression
Browse files Browse the repository at this point in the history
LDEV-5023 test case for qoq regression
  • Loading branch information
michaeloffner authored Jul 18, 2024
2 parents 2fa1716 + 874d789 commit 7f74ec2
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 48 deletions.
84 changes: 36 additions & 48 deletions core/src/main/java/lucee/runtime/db/HSQLDBHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ private static String toUsableType(int type) {
* @throws DatabaseException
*/
private static void removeTable(Connection conn, String name) throws SQLException {
name = name.replace('.', '_');
Statement stat = conn.createStatement();
stat.execute("DROP TABLE " + name);
DBUtil.commitEL(conn);
Expand Down Expand Up @@ -362,11 +361,8 @@ private static void _executeStatement(Connection conn, String sql) throws SQLExc
* @throws DatabaseException
*/
private static Struct getUsedColumnsForQuery(Connection conn, SQL sql) {

// TODO this could be potentially cached against the sql text

Stopwatch stopwatch = new Stopwatch(Stopwatch.UNIT_MILLI);
stopwatch.start();
// Stopwatch stopwatch = new Stopwatch(Stopwatch.UNIT_MILLI);
// stopwatch.start();
ResultSet rs = null;
ResultSetMetaData rsmd = null;
String view = "V_QOQ_TEMP";
Expand Down Expand Up @@ -467,7 +463,6 @@ public QueryImpl execute(PageContext pc, final SQL sql, int maxrows, int fetchsi
}
catch (Exception ex) {
}

}
catch (Exception e) {
qoqException = e;
Expand All @@ -476,7 +471,6 @@ public QueryImpl execute(PageContext pc, final SQL sql, int maxrows, int fetchsi
// If our first pass at the QoQ failed, lets look at the exception to see what we want to do with
// it.
if (qoqException != null) {

// Track the root cause
Exception rootCause = qoqException;

Expand Down Expand Up @@ -557,31 +551,30 @@ public static QueryImpl __execute(PageContext pc, SQL sql, int maxrows, int fetc
ConfigPro config = (ConfigPro) pc.getConfig();
DatasourceConnection dc = null;
Connection conn = null;
try {
DatasourceConnPool pool = config.getDatasourceConnectionPool(config.getDataSource(QOQ_DATASOURCE_NAME), "sa", "");
dc = pool.borrowObject();
conn = dc.getConnection();

// executeStatement(conn, "CONNECT"); // create a new HSQLDB session for temp tables
DBUtil.setAutoCommitEL(conn, false);

// sql.setSQLString(HSQLUtil.sqlToZQL(sql.getSQLString(),false));
// TODO this is currently single threaded
synchronized (lock) {
try {
// we now only lock the data loading, not the execution of the query, but should this be done via
// cflock by the developer?
synchronized (lock) {
DatasourceConnPool pool = config.getDatasourceConnectionPool(config.getDataSource(QOQ_DATASOURCE_NAME), "sa", "");
dc = pool.borrowObject();
conn = dc.getConnection();
// executeStatement(conn, "CONNECT"); // TODO create a new HSQLDB session for temp tables
DBUtil.setAutoCommitEL(conn, false);

try {
Iterator<String> it = tables.iterator();
String cfQueryName = null; // name of the source query variable
String dbTableName = null; // name of the table in the database
String cfQueryName = null; // name of the source cfml query variable
String dbTableName = null; // name of the target table in the database
String modSql = null;
// int len=tables.size();
while (it.hasNext()) {
cfQueryName = it.next().toString();// tables.get(i).toString();
dbTableName = cfQueryName.replace('.', '_');

// this could match the wrong strings??
modSql = StringUtil.replace(sql.getSQLString(), cfQueryName, dbTableName, false);
sql.setSQLString(modSql);
if (!cfQueryName.toLowerCase().equals(dbTableName.toLowerCase())){
// TODO this could match the wrong strings??
modSql = StringUtil.replace(sql.getSQLString(), cfQueryName, dbTableName, false);
sql.setSQLString(modSql);
}
if (sql.getItems() != null && sql.getItems().length > 0) sql = new SQLImpl(sql.toString());
// temp tables still get created will all the source columns,
// only populateTables is driven by the required columns calculated from the view
Expand Down Expand Up @@ -630,32 +623,27 @@ public static QueryImpl __execute(PageContext pc, SQL sql, int maxrows, int fetc
}

}
catch (SQLException e) {
throw (IllegalQoQException) (new IllegalQoQException("QoQ HSQLDB: error executing sql statement on query.", e.getMessage(), sql, null).initCause(e));
}
}
catch (SQLException e) {
throw (IllegalQoQException) (new IllegalQoQException("QoQ HSQLDB: error executing sql statement on query.", e.getMessage(), sql, null).initCause(e));
// DatabaseException de = new DatabaseException("QoQ HSQLDB: error executing sql statement on query
// [" + e.getMessage() + "]", null , sql, null);
// throw de;
catch (Exception ee) {
throw (IllegalQoQException) (new IllegalQoQException("QoQ HSQLDB: error executing sql statement on query.", ee.getMessage(), sql, null).initCause(ee));
}
}
catch (Exception ee) {
throw (IllegalQoQException) (new IllegalQoQException("QoQ HSQLDB: error executing sql statement on query.", ee.getMessage(), sql, null).initCause(ee));
// DatabaseException de = new DatabaseException("QoQ HSQLDB: error executing sql statement on query
// [" + ee.getMessage() + "]", null , sql, null);
// throw ee;
}
finally {
if (conn != null) {
removeAll(conn, qoqTables);
// executeStatement(conn, "DISCONNECT"); // close HSQLDB session with temp tables
DBUtil.setAutoCommitEL(conn, true);
}
if (dc != null) ((DatasourceConnectionPro) dc).release();
finally {
if (conn != null) {
removeAll(conn, qoqTables);
//executeStatement(conn, "DISCONNECT"); // close HSQLDB session with temp tables
DBUtil.setAutoCommitEL(conn, true);
}
if (dc != null) ((DatasourceConnectionPro) dc).release();

// manager.releaseConnection(dc);
// manager.releaseConnection(dc);
}
// TODO we are swallowing errors, shouldn't be passing a null value back
if (nqr != null) nqr.setExecutionTime(stopwatch.time());
return nqr;
}
// TOOD we are swalloing errors, shouldn't be passing a null value bacl
if (nqr != null) nqr.setExecutionTime(stopwatch.time());
return nqr;

}
}
107 changes: 107 additions & 0 deletions test/tickets/LDEV5023.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
component extends="org.lucee.cfml.test.LuceeTestCase" labels="qoq" {

function run( testResults , testBox ) {

describe( title='QofQ' , body=function(){

it( title='QoQ select * from table same source table name HSQLDB', body=function() {
var q = getTestQuery();
var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word
// native engine
cols = "name, id";
var q_native = QueryExecute(
sql = "SELECT #cols# FROM q",
options = { dbtype: 'query', maxrows=5 }
);
var q_stash = duplicate( q_native );
expect( q_stash.recordcount ).toBe( q_native.recordcount );
// hsqldb engine, coz join
var q_hsqlb = QueryExecute(
sql = "SELECT t1.name FROM q_native t1, q_native t2 WHERE t1.id = t2.id",
options = { dbtype: 'query' }
);
expect( q_stash.recordcount ).toBe( q_hsqlb.recordcount );
expect( q_native.recordcount ).toBe( q_hsqlb.recordcount );
expect( q_stash.recordcount ).toBe( q_native.recordcount );
});

it( title='QoQ select * from table same source table name (arguments) HSQLDB', body=function() {
var q = getTestQuery();
var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word
// native engine
cols = "name, id";
var q_native = QueryExecute(
sql = "SELECT #cols# FROM q",
options = { dbtype: 'query', maxrows=5 }
);
var q_stash = duplicate( q_native );
// hsqldb engine, coz join
arguments.q_native = q_native;
var q_hsqlb = QueryExecute(
sql = "SELECT t1.name FROM q_native t1, arguments.q_native t2 WHERE t1.id = t2.id",
options = { dbtype: 'query' }
);

expect( q_stash.recordcount ).toBe( q_hsqlb.recordcount );
expect( q_native.recordcount ).toBe( q_hsqlb.recordcount );
expect( q_stash.recordcount ).toBe( q_native.recordcount );
});

it( title='QoQ select * from table same source table name (all cols) HSQLDB', body=function() {
var q = getTestQuery();
var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word
// native engine
var q_native = QueryExecute(
sql = "SELECT #cols# FROM q",
options = { dbtype: 'query', maxrows=5 }
);
var q_stash = duplicate( q_native );
// hsqldb engine, coz join
var q_hsqlb = QueryExecute(
sql = "SELECT t1.name FROM q_native t1, q_native t2 WHERE t1.id = t2.id",
options = { dbtype: 'query' }
);
expect( q_stash.recordcount ).toBe( q_hsqlb.recordcount );
expect( q_native.recordcount ).toBe( q_hsqlb.recordcount );
expect( q_stash.recordcount ).toBe( q_native.recordcount );
});

it( title='QoQ select * from table same source table name (all cols) HSQLDB, 5000 threads', body=function() {

var arr = [];
ArraySet(arr, 1, 1000, 0);
arrayEach(arr, function(){
var q = getTestQuery();
var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word
// native engine
q = QueryExecute(
sql = "SELECT #cols# FROM q",
options = { dbtype: 'query' }
);
// hsqldb engine, coz join
q = QueryExecute(
sql = "SELECT t1.name FROM q t1, q t2 WHERE t1.id = t2.id",
options = { dbtype: 'query' }
);
}, true);

});
});

}

private function getTestQuery(){
return extensionList(); // has arrays and the like
/*
var q = queryNew("id,name,data","integer,varchar, varchar");
loop list="micha,zac,brad,pothys,gert" item="local.n" index="local.i" {
var r = queryAddRow( q );
querySetCell(q, "id", r, r)
querySetCell(q, "name", n, r)
//querySetCell(q, "data", repeatString("lucee",1000), r);
}
return q;
*/
}

}

0 comments on commit 7f74ec2

Please sign in to comment.