package railo.runtime.sql; import java.util.ArrayList; import java.util.List; import railo.commons.lang.ParserString; import railo.commons.lang.types.RefBoolean; import railo.commons.lang.types.RefBooleanImpl; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.sql.exp.Column; import railo.runtime.sql.exp.ColumnExpression; import railo.runtime.sql.exp.Expression; import railo.runtime.sql.exp.op.Operation; import railo.runtime.sql.exp.op.Operation1; import railo.runtime.sql.exp.op.Operation2; import railo.runtime.sql.exp.op.Operation3; import railo.runtime.sql.exp.op.OperationN; import railo.runtime.sql.exp.value.ValueBoolean; import railo.runtime.sql.exp.value.ValueDate; import railo.runtime.sql.exp.value.ValueNull; import railo.runtime.sql.exp.value.ValueNumber; import railo.runtime.sql.exp.value.ValueString; public class SelectParser { /* SELECT [{LIMIT <offset> <limit> | TOP <limit>}[1]][ALL | DISTINCT] { <selectExpression> | table.* | * } [, ...] [INTO [CACHED | TEMP | TEXT][1] newTable] FROM tableList [WHERE Expression] [GROUP BY Expression [, ...]] [HAVING Expression] [{ UNION [ALL | DISTINCT] | {MINUS [DISTINCT] | EXCEPT [DISTINCT] } | INTERSECT [DISTINCT] } selectStatement] [ORDER BY orderExpression [, ...]] [LIMIT <limit> [OFFSET <offset>]]; * */ private int columnIndex=0; // select <select-statement> from <tables> where <where-statement> public Selects parse(String sql) throws SQLParserException { columnIndex=0; ParserString raw = new ParserString(sql.trim()); Selects selects = new Selects(); Select select = new Select(); boolean runAgain=false; do { // select if(!raw.forwardIfCurrentAndNoWordNumberAfter("select")) throw new SQLParserException("missing select"); raw.removeSpace(); // top if(raw.forwardIfCurrentAndNoWordNumberAfter("top")) { raw.removeSpace(); ValueNumber number = number(raw); if(number==null)throw new SQLParserException("missing top number"); select.setTop(number); raw.removeSpace(); } // distinct if(raw.forwardIfCurrentAndNoWordNumberAfter("distinct")) { select.setDistinct(true); raw.removeSpace(); } // all if(raw.forwardIfCurrentAndNoWordNumberAfter("all")) { select.setDistinct(false); raw.removeSpace(); } // select expression selectExpressions(raw,select); raw.removeSpace(); // from if(!raw.forwardIfCurrentAndNoWordNumberAfter("from")) throw new SQLParserException("missing from"); tableList(raw,select); raw.removeSpace(); // where if(raw.forwardIfCurrentAndNoWordNumberAfter("where")) whereExpressions(raw,select); raw.removeSpace(); // group by if(raw.forwardIfCurrentAndNoWordNumberAfter("group by")) { groupByExpressions(raw,select); raw.removeSpace(); // having if(raw.forwardIfCurrentAndNoWordNumberAfter("having")) havingExpressions(raw,select); raw.removeSpace(); } selects.addSelect(select); runAgain=false; // union if(raw.forwardIfCurrentAndNoWordNumberAfter("union")) { select = new Select(); raw.removeSpace(); if(raw.forwardIfCurrentAndNoWordNumberAfter("all")){ raw.removeSpace(); select.setUnionDistinct(false); } else if(raw.forwardIfCurrentAndNoWordNumberAfter("distinct")){ raw.removeSpace(); select.setUnionDistinct(true); } else select.setDistinct(true); raw.removeSpace(); runAgain=true; } } while(runAgain); // order by if(raw.forwardIfCurrentAndNoWordNumberAfter("order by")) orderByExpressions(raw,selects); raw.removeSpace(); if(raw.forwardIfCurrent(';'))raw.removeSpace(); if(!raw.isAfterLast()) throw new SQLParserException("can not read the full sql statement (stop at:"+raw.getCurrent()+")"); return selects; } private void orderByExpressions(ParserString raw, Selects selects) throws SQLParserException { Expression exp=null; do { raw.removeSpace(); //print.out(raw.getCurrent()); exp=expression(raw); if(!(exp instanceof Column)) throw new SQLParserException("invalid order by part of query"); Column col=(Column) exp; raw.removeSpace(); if(raw.forwardIfCurrent("desc")) col.setDirectionBackward(true); if(raw.forwardIfCurrent("asc")) col.setDirectionBackward(false); selects.addOrderByExpression(col); raw.removeSpace(); } while(raw.forwardIfCurrent(',')); raw.removeSpace(); } private void whereExpressions(ParserString raw, Select select) throws SQLParserException { raw.removeSpace(); Expression exp = expression(raw); if(exp==null) throw new SQLParserException("missing where expression"); if(!(exp instanceof Operation)) throw new SQLParserException("invalid where expression ("+Caster.toClassName(exp)+")"); select.setWhereExpression((Operation)exp); raw.removeSpace(); } private void havingExpressions(ParserString raw, Select select) throws SQLParserException { raw.removeSpace(); Expression exp = expression(raw); if(exp==null) throw new SQLParserException("missing having expression"); if(!(exp instanceof Operation)) throw new SQLParserException("invalid having expression"); select.setHaving((Operation)exp); raw.removeSpace(); } private void groupByExpressions(ParserString raw, Select select) throws SQLParserException { Expression exp=null; do { raw.removeSpace(); //print.out(raw.getCurrent()); exp=expression(raw); if(!(exp instanceof Column)) throw new SQLParserException("invalid group by part of query"); Column col=(Column) exp; select.addGroupByExpression(col); raw.removeSpace(); } while(raw.forwardIfCurrent(',')); raw.removeSpace(); } private void tableList(ParserString raw, Select select) throws SQLParserException { Column column=null; Expression exp=null; do { raw.removeSpace(); exp=column(raw); if(!(exp instanceof Column)) throw new SQLParserException("invalid table definition"); column=(Column) exp; raw.removeSpace(); if(raw.forwardIfCurrent("as ")) { String alias=identifier(raw,new RefBooleanImpl(false)); if(alias==null) throw new SQLParserException("missing alias in select part"); column.setAlias(alias); } else { int start=raw.getPos(); RefBoolean hasBracked = new RefBooleanImpl(false); String alias=identifier(raw,hasBracked);//TODO having usw if(!hasBracked.toBooleanValue()) { if("where".equalsIgnoreCase(alias)) raw.setPos(start); else if("group".equalsIgnoreCase(alias)) raw.setPos(start); else if("having".equalsIgnoreCase(alias)) raw.setPos(start); else if("union".equalsIgnoreCase(alias)) raw.setPos(start); else if("order".equalsIgnoreCase(alias)) raw.setPos(start); else if("limit".equalsIgnoreCase(alias)) raw.setPos(start); else if(alias!=null) column.setAlias(alias); } else { if(alias!=null) column.setAlias(alias); } } select.addFromExpression(column); raw.removeSpace(); } while(raw.forwardIfCurrent(',')); } // { (selectStatement) [AS] label | tableName [AS] label} private void selectExpressions(ParserString raw, Select select) throws SQLParserException { Expression exp=null; do { raw.removeSpace(); exp=expression(raw); if(exp==null) throw new SQLParserException("missing expression in select part of query"); raw.removeSpace(); if(raw.forwardIfCurrent("as ")) { String alias=identifier(raw,new RefBooleanImpl(false)); if(alias==null) throw new SQLParserException("missing alias in select part"); exp.setAlias(alias); } else { int start=raw.getPos(); RefBoolean hb = new RefBooleanImpl(false); String alias=identifier(raw,hb); if(!hb.toBooleanValue() && "from".equalsIgnoreCase(alias)) raw.setPos(start); else if(alias!=null) exp.setAlias(alias); } select.addSelectExpression(exp); raw.removeSpace(); } while(raw.forwardIfCurrent(',')); } private Expression expression(ParserString raw) throws SQLParserException { return xorOp(raw); } private Expression xorOp(ParserString raw) throws SQLParserException { Expression expr = orOp(raw); while(raw.forwardIfCurrentAndNoWordNumberAfter("xor")) { raw.removeSpace(); expr=new Operation2(expr, orOp(raw), Operation.OPERATION2_XOR); } return expr; } private Expression orOp(ParserString raw) throws SQLParserException { Expression expr = andOp(raw); while(raw.forwardIfCurrentAndNoWordNumberAfter("or")) { raw.removeSpace(); expr=new Operation2(expr, andOp(raw),Operation.OPERATION2_OR); } return expr; } private Expression andOp(ParserString raw) throws SQLParserException { Expression expr = notOp(raw); while(raw.forwardIfCurrentAndNoWordNumberAfter("and")) { raw.removeSpace(); expr=new Operation2(expr, notOp(raw), Operation.OPERATION2_AND); } return expr; } private Expression notOp(ParserString raw) throws SQLParserException { // NOT if (raw.forwardIfCurrentAndNoWordNumberAfter("not")) { raw.removeSpace(); return new Operation1(decsionOp(raw),Operation.OPERATION1_NOT); } return decsionOp(raw); } private Expression decsionOp(ParserString raw) throws SQLParserException { Expression expr = plusMinusOp(raw); boolean hasChanged=false; do { hasChanged=false; // value BETWEEN value AND value if (raw.forwardIfCurrent("between ")) { raw.removeSpace(); Expression left = plusMinusOp(raw); raw.removeSpace(); if(!raw.forwardIfCurrent("and "))throw new SQLParserException("invalid operation (between) missing operator and"); raw.removeSpace(); Expression right = plusMinusOp(raw); raw.removeSpace(); expr= new Operation3(expr,left,right, Operation.OPERATION3_BETWEEN); hasChanged=true; } // value like value [escape value] else if (raw.forwardIfCurrentAndNoWordNumberAfter("like")) { raw.removeSpace(); Expression left = plusMinusOp(raw); raw.removeSpace(); if(raw.forwardIfCurrentAndNoWordNumberAfter("escape ")){ raw.removeSpace(); Expression right = plusMinusOp(raw); raw.removeSpace(); expr= new Operation3(expr,left,right, Operation.OPERATION3_LIKE); } else { raw.removeSpace(); expr= new Operation2(expr,left, Operation.OPERATION2_LIKE); } hasChanged=true; } // IS [NOT] NULL else if (raw.isCurrent("is ")) { int start=raw.getPos(); if (raw.forwardIfCurrentAndNoWordNumberAfter("is null")) { raw.removeSpace(); return new Operation1(expr, Operation.OPERATION1_IS_NULL); } else if (raw.forwardIfCurrentAndNoWordNumberAfter("is not null")) { raw.removeSpace(); return new Operation1(expr, Operation.OPERATION1_IS_NOT_NULL); } else { raw.setPos(start); raw.removeSpace(); } } // not in else if (raw.forwardIfCurrent("not in",'(')) { expr=new OperationN("not_in",readArguments(raw,expr)); hasChanged=true; } // in else if (raw.forwardIfCurrent("in",'(')) { expr=new OperationN("in",readArguments(raw,expr)); hasChanged=true; } // not like if (raw.forwardIfCurrentAndNoWordNumberAfter("not like")) { expr = decisionOpCreate(raw,Operation.OPERATION2_NOT_LIKE,expr); hasChanged=true; } /* / like else if (raw.forwardIfCurrentAndNoWordNumberAfter("like")) { expr = decisionOpCreate(raw,Operation.OPERATION2_LIKE,expr); hasChanged=true; }*/ // = else if (raw.forwardIfCurrent('=')) { expr = decisionOpCreate(raw,Operation.OPERATION2_EQ,expr); hasChanged=true; } // != else if (raw.forwardIfCurrent("!=")) { expr = decisionOpCreate(raw,Operation.OPERATION2_NEQ,expr); hasChanged=true; } // <> else if (raw.forwardIfCurrent("<>")) { expr = decisionOpCreate(raw,Operation.OPERATION2_LTGT,expr); hasChanged=true; } // <, <= else if (raw.isCurrent('<')) { if (raw.forwardIfCurrent("<=")) { expr = decisionOpCreate(raw,Operation.OPERATION2_LTE,expr); hasChanged=true; } else { raw.next(); expr = decisionOpCreate(raw,Operation.OPERATION2_LT,expr); hasChanged=true; } } // >, => else if (raw.isCurrent('>')) { if (raw.forwardIfCurrent("=>")) { expr = decisionOpCreate(raw,Operation.OPERATION2_GTE,expr); hasChanged=true; } if (raw.forwardIfCurrent(">=")) { expr = decisionOpCreate(raw,Operation.OPERATION2_GTE,expr); hasChanged=true; } else { raw.next(); expr = decisionOpCreate(raw,Operation.OPERATION2_GT,expr); hasChanged=true; } } }while(hasChanged); return expr; } private Expression decisionOpCreate(ParserString raw,int operation, Expression left) throws SQLParserException { raw.removeSpace(); return new Operation2(left, plusMinusOp(raw), operation); } private Expression plusMinusOp(ParserString raw) throws SQLParserException { Expression expr = modOp(raw); while(!raw.isLast()) { // Plus Operation if (raw.forwardIfCurrent('+')) { raw.removeSpace(); expr=new Operation2(expr, modOp(raw), Operation.OPERATION2_PLUS); } // Minus Operation else if (raw.forwardIfCurrent('-')) { raw.removeSpace(); expr=new Operation2(expr, modOp(raw), Operation.OPERATION2_MINUS); } else break; } return expr; } private Expression modOp(ParserString raw) throws SQLParserException { Expression expr = divMultiOp(raw); // Modulus Operation while(raw.forwardIfCurrent('%')) { raw.removeSpace(); expr=new Operation2(expr, divMultiOp(raw), Operation.OPERATION2_MOD); } return expr; } private Expression divMultiOp(ParserString raw) throws SQLParserException { Expression expr = expoOp(raw); while (!raw.isLast()) { // Multiply Operation if(raw.forwardIfCurrent('*')) { raw.removeSpace(); expr=new Operation2(expr, expoOp(raw), Operation.OPERATION2_MULTIPLY); } // Divide Operation else if (raw.forwardIfCurrent('/')) { raw.removeSpace(); expr=new Operation2(expr, expoOp(raw), Operation.OPERATION2_DIVIDE); } else { break; } } return expr; } private Expression expoOp(ParserString raw) throws SQLParserException { Expression exp = negateMinusOp(raw); // Modulus Operation while(raw.forwardIfCurrent('^')) { raw.removeSpace(); exp=new Operation2(exp, negateMinusOp(raw),Operation.OPERATION2_EXP); } return exp; } private Expression negateMinusOp(ParserString raw) throws SQLParserException { // And Operation if (raw.forwardIfCurrent('-')) { raw.removeSpace(); return new Operation1(clip(raw),Operation.OPERATION1_MINUS); } else if (raw.forwardIfCurrent('+')) { raw.removeSpace(); return new Operation1(clip(raw),Operation.OPERATION1_PLUS); } return clip(raw); } // { Expression | COUNT(*) | {COUNT | MIN | MAX | SUM | AVG | SOME | EVERY | VAR_POP | VAR_SAMP | STDDEV_POP | STDDEV_SAMP} ([ALL | DISTINCT][1]] Expression) } [[AS] label] private Expression clip(ParserString raw) throws SQLParserException { Expression exp=column(raw); //if(exp==null)exp=brackedColumn(raw); if(exp==null)exp=date(raw); if(exp==null)exp=bracked(raw); if(exp==null)exp=number(raw); if(exp==null)exp=string(raw); return exp; } private Expression bracked(ParserString raw) throws SQLParserException { if(!raw.forwardIfCurrent('(')) return null; raw.removeSpace(); Expression exp = expression(raw); raw.removeSpace(); if(!raw.forwardIfCurrent(')')) throw new SQLParserException("missing closing )"); raw.removeSpace(); return exp;//new BracketExpression(exp); } private Expression column(ParserString raw) throws SQLParserException { RefBoolean hb = new RefBooleanImpl(false); String name = identifier(raw,hb); if(name==null) return null; if(!hb.toBooleanValue()) { if("true".equalsIgnoreCase(name)) return ValueBoolean.TRUE; if("false".equalsIgnoreCase(name)) return ValueBoolean.FALSE; if("null".equalsIgnoreCase(name)) return ValueNull.NULL; } ColumnExpression column=new ColumnExpression(name,name.equals("?")?columnIndex++:0); raw.removeSpace(); while(raw.forwardIfCurrent(".")) { raw.removeSpace(); String sub=identifier(raw,hb); if(sub==null) throw new SQLParserException("invalid column definition"); column.setSub(sub); } raw.removeSpace(); if(raw.forwardIfCurrent('(')) { return new OperationN(column.getFullName(),readArguments(raw)); } return column; } private List readArguments(ParserString raw) throws SQLParserException { return readArguments(raw,null); } private List readArguments(ParserString raw,Expression exp) throws SQLParserException { List args=new ArrayList(); Expression arg; if(exp!=null)args.add(exp); do { raw.removeSpace(); if(raw.isCurrent(')')) break; args.add(arg=expression(raw)); raw.removeSpace(); // check for alias if(raw.forwardIfCurrent("as ")) { raw.removeSpace(); arg.setAlias(identifier(raw,null)); raw.removeSpace(); } } while(raw.forwardIfCurrent(',')); if(!raw.forwardIfCurrent(')')) throw new SQLParserException("missing closing )"); raw.removeSpace(); return args; } private ValueNumber number(ParserString raw) throws SQLParserException { // check first character is a number literal representation if(!(raw.isCurrentBetween('0','9') || raw.isCurrent('.'))) return null; StringBuffer rtn=new StringBuffer(); // get digit on the left site of the dot if(raw.isCurrent('.')) rtn.append('0'); else rtn.append(digit(raw)); // read dot if exist if(raw.forwardIfCurrent('.')) { rtn.append('.'); String rightSite=digit(raw); if(rightSite.length()> 0 && raw.forwardIfCurrent('e')) { if(raw.isCurrentBetween('0','9')) { rightSite+='e'+digit(raw); } else { raw.previous(); } } // read right side of the dot if(rightSite.length()==0) throw new SQLParserException("Number can't end with [.]"); rtn.append(rightSite); } raw.removeSpace(); return new ValueNumber(rtn.toString()); } private String digit(ParserString raw) { String rtn=""; while (raw.isValidIndex()) { if(!raw.isCurrentBetween('0','9'))break; rtn+=raw.getCurrentLower(); raw.next(); } return rtn; } private ValueString string(ParserString raw) throws SQLParserException { // check starting character for a string literal if(!raw.isCurrent('\'')) return null; // Init Parameter StringBuffer str=new StringBuffer(); while(raw.hasNext()) { raw.next(); // check quoter if(raw.isCurrent('\'')) { // Ecaped sharp if(raw.isNext('\'')){ raw.next(); str.append('\''); } // finsish else { break; } } // all other character else { str.append(raw.getCurrent()); } } if(!raw.forwardIfCurrent('\'')) throw new SQLParserException("Invalid Syntax Closing ['] not found"); raw.removeSpace(); return new ValueString(str.toString()); } private ValueDate date(ParserString raw) throws SQLParserException { if(!raw.isCurrent('{')) return null; // Init Parameter StringBuilder str=new StringBuilder(); while(raw.hasNext()) { raw.next(); if(raw.isCurrent('}'))break; str.append(raw.getCurrent()); } if(!raw.forwardIfCurrent('}')) throw new SQLParserException("Invalid Syntax Closing [}] not found"); raw.removeSpace(); try { return new ValueDate("{"+str.toString()+"}"); } catch (PageException e) { throw new SQLParserException("can't cast value [{"+str.toString()+"}] to date object"); } } private String identifier(ParserString raw,RefBoolean hasBracked) throws SQLParserException { if(hasBracked!=null && raw.forwardIfCurrent('[')) { hasBracked.setValue(true); return identifierBracked(raw); } else if(!(raw.isCurrentLetter() || raw.isCurrent('*') || raw.isCurrent('?')|| raw.isCurrent('_'))) return null; int start = raw.getPos(); do { raw.next(); if(!(raw.isCurrentLetter() || raw.isCurrentBetween('0','9') || raw.isCurrent('*') || raw.isCurrent('?')|| raw.isCurrent('_'))) { break; } } while (raw.isValidIndex()); String str = raw.substring(start,raw.getPos()-start); raw.removeSpace(); return str; } private String identifierBracked(ParserString raw) throws SQLParserException { int start = raw.getPos(); do { raw.next(); } while (raw.isValidIndex() && !raw.isCurrent(']')); String str = raw.substring(start,raw.getPos()-start); if(!raw.forwardIfCurrent(']')) throw new SQLParserException("missing ending ] of identifier"); return str; } public static void main(String[] args) { //print.out(new SelectParser().parse("select a, b as c, d e from test limit 3").toString()); //String sql="select cast(susi as integer) as y,a=b as x from source";//WHERE (lft BETWEEN 1 AND 4 AND ID = 111) //print.out(new SelectParser().parse(sql).toString()); /* print.out(new SelectParser().parse("select (a and b) s,'abc'<b as c,'abc'+b as c,'abc'%b as c,'abc'*b as c,'susi''s lustige dings', 'sss' as a, 'xxx' b, 1.1,1.2 as c, 1.3 d, e, f as g, h i, a.b.c.d as j, 1^1 as k " + "from test, a as x, b y,a.b.c as y " + " where not t=d and x>y or x=0 xor '1'>'2' ").toString()); */ //print.out("*****************************"); /* print.out(new SelectParser().parse("select a, b as c, d e from test").toString()); print.out(new SelectParser().parse("select c is not null,c is null as x from test").toString()); print.out(new SelectParser().parse("select c between 'a' and 1,c between 'a' and 1 as x,a from test").toString()); print.out(new SelectParser().parse("select c from test where a like b and c=1").toString()); print.out(new SelectParser().parse("select true as x,b in(1,a,'x'), count(c),count(c) as x from test where s not in(1,2,3) and a like b and c=count(c)").toString()); */ //print.out(new SelectParser().parse("select c from test where x=y order by test,a.b desc , a.b.c asc ").toString()); //print.out(new SelectParser().parse("select *, *.lastname from test").toString()); //Selects select = new SelectParser().parse("SELECT * FROM qTest WHERE (ID = 7 AND data_ID = 1) OR (data_ID = 110422)"); //select = new SelectParser().parse("\nSELECT *\nFROM qAllTodos\nWHERE (\n (\n (\n toeditor_ID = ? OR\n workflowtaskseditor_ID = ? OR\n (editorgroup_ID IN (?) AND\n workflowmethod_ID = 1) OR\n (editorgroup_ID IN (?) AND\n workflowmethod_ID = 2 AND status <> 6) OR\n (editorgroup_ID IN (?,?) AND\n workflowmethod_ID = 3) OR\n (editorgroup_ID IN (?) AND\n workflowmethod_ID = 4) OR\n (editorgroup_ID IN (?) AND\n ? <> editor_ID AND\n workflowmethod_ID = 5) OR\n (acceptedbyeditor_ID = ?) OR\n (passedtoeditor_ID = ?)\n ) AND\n status IN (1,2,6) AND\n (acceptedbyeditor_ID = ? OR\n acceptedbyeditor_ID = 0) AND\n\n (site_ID = ? OR\n workflowprocessessite_ID = ? OR\n workflowprocessessite_ID = 0) AND\n\n startdate <= '2007-09-14 17:09:48' AND\n\n istimeouttask = 0\n )\n\n\n OR\n\n (\n\n confirm_needed <> 0 AND\n\n (confirm_editor_ID = ? OR\n\n (confirm_editorgroup_ID IN (?) AND\n confirm_method_ID = 1) OR\n\n (confirm_editorgroup_ID IN (?) AND\n confirm_method_ID = 2) OR\n\n (confirm_editorgroup_ID IN (?,?) AND\n confirm_method_ID = 3) OR\n\n (confirm_editorgroup_ID IN (?) AND\n confirm_method_ID = 4) OR\n\n (confirm_editorgroup_ID IN (?) AND\n donebyeditor_ID <> ? AND\n confirm_method_ID = 5)\n ) AND\n\n confirmedbyeditor_ID = 0 AND\n\n status = 3 AND\n\n (workflowprocessessite_ID = ? OR\n workflowprocessessite_ID = 0)\n )\n\n\n OR\n\n (\n\n istimeouttask <> 0 AND\n\n (timeout_editor_ID = ? OR\n\n (timeout_editorgroup_ID IN (?) AND\n timeout_method_ID = 1) OR\n\n (timeout_editorgroup_ID IN (?) AND\n timeout_method_ID = 2 AND\n status <> 6) OR\n\n (timeout_editorgroup_ID IN (?,?) AND\n timeout_method_ID = 3) OR\n\n (timeout_editorgroup_ID IN (?) AND\n timeout_method_ID = 4) OR\n\n (timeout_editorgroup_ID IN (?) AND\n ? <> deputyeditor_ID AND\n timeout_method_ID = 5) OR\n\n (acceptedbyeditor_ID = ?) OR\n\n (passedtoeditor_ID = ?)\n ) AND\n\n status IN (1,2,6) AND\n\n (acceptedbyeditor_ID = ? OR\n acceptedbyeditor_ID = 0) AND\n\n (workflowprocessessite_ID = ? OR\n workflowprocessessite_ID = 0)\n\n )\n )\n"); //print.out(select.toString()); //print.out(select.getTables().length); //railo.print.out(new SelectParser().parse("select * from qryData where tableName like '%@_array' or x=1").toString()); //railo.print.out(new SelectParser().parse("select * from qryData where tableName like '%@_array' escape '@' or x=1").toString()); } }