diff --git a/core/src/main/java/lucee/runtime/db/HSQLDBHandler.java b/core/src/main/java/lucee/runtime/db/HSQLDBHandler.java index afaf7cc9ea..2c29a5b927 100644 --- a/core/src/main/java/lucee/runtime/db/HSQLDBHandler.java +++ b/core/src/main/java/lucee/runtime/db/HSQLDBHandler.java @@ -61,7 +61,7 @@ import lucee.runtime.type.StructImpl; import lucee.runtime.type.dt.TimeSpan; import lucee.runtime.type.util.CollectionUtil; - +import lucee.aprint; /** * class to reexecute queries on the resultset object inside the cfml environment */ @@ -374,6 +374,8 @@ private static Struct getUsedColumnsForQuery(Connection conn, SQL sql) { // TODO consider if worth doing, if recordcount / column count is too small + aprint.o(sql.toString()); + try { Statement stat = conn.createStatement(); stat.execute("CREATE VIEW " + view + " AS " + sql.toString()); // + StringUtil.toUpperCase(sql.toString())); @@ -403,8 +405,8 @@ private static Struct getUsedColumnsForQuery(Connection conn, SQL sql) { Struct tableCols = ((Struct) tables.get(tableName)); tableCols.setEL(Caster.toKey(rs.getString(colPos)), null); } - // aprint.o(rs); - // aprint.o(tables); + aprint.o(rs); + aprint.o(tables); // don't need the view anymore, bye bye stat.execute("DROP VIEW " + view); } @@ -569,19 +571,27 @@ public static QueryImpl __execute(PageContext pc, SQL sql, int maxrows, int fetc try { // we now only lock the data loading, not the execution of the query, but should this be done via // cflock by the developer? + aprint.out(tables); synchronized (lock) { Iterator it = tables.iterator(); String cfQueryName = null; // name of the source query variable String dbTableName = null; // name of the table in the database String modSql = null; // int len=tables.size(); + SystemOut.print("QoQ HSQLDB CREATED TABLES: " + sql.toString()); while (it.hasNext()) { cfQueryName = it.next().toString();// tables.get(i).toString(); dbTableName = cfQueryName.replace('.', '_'); + if (qoqTables.contains(dbTableName)){ + aprint.o("duplicate table name!!"); + } - // 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); + SystemOut.print("QoQ HSQLDB CREATED TABLES: " + 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 @@ -589,7 +599,7 @@ public static QueryImpl __execute(PageContext pc, SQL sql, int maxrows, int fetc qoqTables.add(dbTableName); } - // SystemOut.print("QoQ HSQLDB CREATED TABLES: " + sql.toString()); + // create the sql as a view, to find out which table columns are needed Struct allTableColumns = getUsedColumnsForQuery(conn, sql); diff --git a/test/tickets/LDEV5023.cfc b/test/tickets/LDEV5023.cfc new file mode 100644 index 0000000000..043eaf74dd --- /dev/null +++ b/test/tickets/LDEV5023.cfc @@ -0,0 +1,105 @@ +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 = extensionList(); + var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word + // native engine + cols = "name, id"; + systemOutput("native [#cols#]", true); + var q_native = QueryExecute( + sql = "SELECT #cols# FROM q", + options = { dbtype: 'query', maxrows=5 } + ); + var q_stash = duplicate( q_native ); + // hsqldb engine, coz join + systemOutput("hsqldb", true); + var q_hsqlb = QueryExecute( + sql = "SELECT t1.name FROM q_native t1, q_native t2 WHERE t1.id = t2.id", + options = { dbtype: 'query' } + ); + systemOutput( q_hsqlb, true ); + 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 = extensionList(); + var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word + // native engine + cols = "name, id"; + systemOutput("native [#cols#]", true); + var q_native = QueryExecute( + sql = "SELECT #cols# FROM q", + options = { dbtype: 'query', maxrows=5 } + ); + var q_stash = duplicate( q_native ); + // hsqldb engine, coz join + systemOutput("hsqldb", true); + 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' } + ); + systemOutput( q_hsqlb, true ); + 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 = extensionList(); + var cols = replaceNoCase( q.columnList, ",unique", "" ); // cleanup reserved word + // native engine + systemOutput("native [#cols#]", true); + var q_native = QueryExecute( + sql = "SELECT #cols# FROM q", + options = { dbtype: 'query', maxrows=5 } + ); + var q_stash = duplicate( q_native ); + // hsqldb engine, coz join + systemOutput("hsqldb", true); + var q_hsqlb = QueryExecute( + sql = "SELECT t1.name FROM q_native t1, q_native t2 WHERE t1.id = t2.id", + options = { dbtype: 'query' } + ); + systemOutput( q_hsqlb, true ); + 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 = extensionList(); + 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' } + ); + }); + }); + + } + + private function getDummyData (){ + var q = queryNew("id,name,data","integer,varchar, varchar"); + loop list="micha,zac,brad,pothys,gert" item="n" index="i" { + var r = queryAddRow(q); + querySetCell(q, "id", r, r) + querySetCell(q, "name", n, r) + querySetCell(q, "data", repeatString("lucee",1000), r); + } + return q; + } + +} \ No newline at end of file