/** * Method declaration * * * @param f * @param ownfilter * * @throws Exception */ public void resolve(TableFilter f, bool ownfilter) { if (eCondition != null) { // first set the table filter in the condition eCondition.resolve(f); if (f != null && ownfilter) { // the table filter tries to get as many conditions as possible // but only if the table filter belongs to this query f.setCondition(eCondition); } } int len = eColumn.Length; for (int i = 0; i < len; i++) { eColumn[i].resolve(f); } }
/** * Method declaration * * * @param f * * @throws Exception */ public void resolve(TableFilter f) { if (f != null && iType == COLUMN) { if (sTable == null || f.getName().Equals(sTable)) { int i = f.getTable().searchColumn(sColumn); if (i != -1) { // todo: other error message: multiple tables are possible Trace.check(tFilter == null || tFilter == f, Trace.COLUMN_NOT_FOUND, sColumn); tFilter = f; iColumn = i; sTable = f.getName(); iDataType = f.getTable().getColumnType(i); } } } // currently sets only data type // todo: calculate fixed expressions if possible if (eArg != null) { eArg.resolve(f); } if (eArg2 != null) { eArg2.resolve(f); } if (sSelect != null) { sSelect.resolve(f, false); sSelect.resolve(); } /* if (fFunction != null) * { * fFunction.resolve(f); * } */ if (iDataType != 0) { return; } switch (iType) { /* case FUNCTION: * iDataType = fFunction.getReturnType(); * * break; */ case QUERY: iDataType = sSelect.eColumn[0].iDataType; break; case NEGATE: iDataType = eArg.iDataType; break; case ADD: case SUBTRACT: case MULTIPLY: case DIVIDE: iDataType = eArg.iDataType; break; case CONCAT: iDataType = Column.VARCHAR; break; case NOT: case EQUAL: case BIGGER_EQUAL: case BIGGER: case SMALLER: case SMALLER_EQUAL: case NOT_EQUAL: case LIKE: case AND: case OR: case IN: case EXISTS: iDataType = Column.BIT; break; case COUNT: iDataType = Column.INTEGER; break; case MAX: case MIN: case SUM: case AVG: iDataType = eArg.iDataType; break; case CONVERT: // it is already set break; case IFNULL: case CASEWHEN: iDataType = eArg2.iDataType; break; } }
// [email protected] end changes from 1.50 // [email protected] begin changes from 1.50 public Result getResult(int start, int cnt) { int maxrows = start + cnt; //<-new, cut definitly // [email protected] begin changes from 1.50 resolve(); checkResolved(); if (sUnion != null && sUnion.iResultLen != iResultLen) { throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH); } int len = eColumn.Length; Result r = new Result(len); bool aggregated = false; bool grouped = false; for (int i = 0; i < len; i++) { Expression e = eColumn[i]; r.iType[i] = e.getDataType(); if (e.isAggregate()) { aggregated = true; } } object[] agg = null; if (aggregated) { agg = new object[len]; } if (iGroupLen > 0) { // has been set in Parser grouped = true; } bool simple_maxrows = false; if (maxrows != 0 && grouped == false && sUnion == null && iOrderLen == 0) { simple_maxrows = true; } else { simple_maxrows = false; } int count = 0; int filter = tFilter.Length; bool[] first = new bool[filter]; int level = 0; while (level >= 0) { TableFilter t = tFilter[level]; bool found; if (!first[level]) { found = t.findFirst(); first[level] = found; } else { found = t.next(); first[level] = found; } if (!found) { level--; continue; } if (level < filter - 1) { level++; continue; } if (eCondition == null || eCondition.test()) { object[] row = new object[len]; for (int i = 0; i < len; i++) { row[i] = eColumn[i].getValue(); } count++; if (aggregated) { updateAggregateRow(agg, row, len); } else { r.add(row); if (simple_maxrows && count >= maxrows) { break; } } } } if (aggregated && !grouped) { addAggregateRow(r, agg, len, count); } else if (grouped) { int[] order = new int[iGroupLen]; int[] way = new int[iGroupLen]; for (int i = iResultLen, j = 0; j < iGroupLen; i++, j++) { order[j] = i; way[j] = 1; } r = sortResult(r, order, way); Record n = r.rRoot; Result x = new Result(len); for (int i = 0; i < len; i++) { x.iType[i] = r.iType[i]; } do { object[] row = new object[len]; count = 0; bool newgroup = false; while (n != null && newgroup == false) { count++; for (int i = 0; i < iGroupLen; i++) { if (n.next == null) { newgroup = true; } else if (Column.compare(n.data[i], n.next.data[i], r.iType[i]) != 0) { // can't use .Equals because 'null' is also one group newgroup = true; } } updateAggregateRow(row, n.data, len); n = n.next; } addAggregateRow(x, row, len, count); } while (n != null); r = x; } if (iOrderLen != 0) { int[] order = new int[iOrderLen]; int[] way = new int[iOrderLen]; for (int i = iResultLen, j = 0; j < iOrderLen; i++, j++) { order[j] = i; way[j] = eColumn[i].isDescending() ? -1 : 1; } r = sortResult(r, order, way); } // the result is maybe bigger (due to group and order by) // but don't tell this anybody else r.setColumnCount(iResultLen); if (bDistinct) { r = removeDuplicates(r); } for (int i = 0; i < iResultLen; i++) { Expression e = eColumn[i]; r.sLabel[i] = e.getAlias(); r.sTable[i] = e.getTableName(); r.sName[i] = e.getColumnName(); } if (sUnion != null) { Result x = sUnion.getResult(0); if (iUnionType == UNION) { r.append(x); r = removeDuplicates(r); } else if (iUnionType == UNIONALL) { r.append(x); } else if (iUnionType == INTERSECT) { r = removeDuplicates(r); x = removeDuplicates(x); r = removeDifferent(r, x); } else if (iUnionType == EXCEPT) { r = removeDuplicates(r); x = removeDuplicates(x); r = removeSecond(r, x); } } if (maxrows > 0 && !simple_maxrows) { trimResult(r, maxrows); } // [email protected] begin changes from 1.50 if (start > 0) { //then cut the first 'start' elements trimResultFront(r, start); } // [email protected] end changes from 1.50 return(r); }
/** * Method declaration * * * @param f * * @throws Exception */ public void resolve(TableFilter f) { if (f != null && iType == COLUMN) { if (sTable == null || f.getName().Equals(sTable)) { int i = f.getTable().searchColumn(sColumn); if (i != -1) { // todo: other error message: multiple tables are possible Trace.check(tFilter == null || tFilter == f, Trace.COLUMN_NOT_FOUND, sColumn); tFilter = f; iColumn = i; sTable = f.getName(); iDataType = f.getTable().getColumnType(i); } } } // currently sets only data type // todo: calculate fixed expressions if possible if (eArg != null) { eArg.resolve(f); } if (eArg2 != null) { eArg2.resolve(f); } if (sSelect != null) { sSelect.resolve(f, false); sSelect.resolve(); } /* if (fFunction != null) { fFunction.resolve(f); } */ if (iDataType != 0) { return; } switch (iType) { /* case FUNCTION: iDataType = fFunction.getReturnType(); break; */ case QUERY: iDataType = sSelect.eColumn[0].iDataType; break; case NEGATE: iDataType = eArg.iDataType; break; case ADD: case SUBTRACT: case MULTIPLY: case DIVIDE: iDataType = eArg.iDataType; break; case CONCAT: iDataType = Column.VARCHAR; break; case NOT: case EQUAL: case BIGGER_EQUAL: case BIGGER: case SMALLER: case SMALLER_EQUAL: case NOT_EQUAL: case LIKE: case AND: case OR: case IN: case EXISTS: iDataType = Column.BIT; break; case COUNT: iDataType = Column.INTEGER; break; case MAX: case MIN: case SUM: case AVG: iDataType = eArg.iDataType; break; case CONVERT: // it is already set break; case IFNULL: case CASEWHEN: iDataType = eArg2.iDataType; break; } }
/** * Method declaration * * * @return * * @throws Exception */ public Result processUpdate() { string token = tTokenizer.getstring(); cChannel.checkReadWrite(); cChannel.check(token, Access.UPDATE); Table table = dDatabase.getTable(token, cChannel); TableFilter filter = new TableFilter(table, null, false); tTokenizer.getThis("SET"); ArrayList vColumn = new ArrayList(); ArrayList eColumn = new ArrayList(); int len = 0; token = null; do { len++; int i = table.getColumnNr(tTokenizer.getstring()); vColumn.Add(i); tTokenizer.getThis("="); Expression e = parseExpression(); e.resolve(filter); eColumn.Add(e); token = tTokenizer.getstring(); } while (token.Equals(",")); Expression eCondition = null; if (token.Equals("WHERE")) { eCondition = parseExpression(); eCondition.resolve(filter); filter.setCondition(eCondition); } else { tTokenizer.back(); } // do the update Expression[] exp = new Expression[len]; eColumn.CopyTo(exp); int[] col = new int[len]; int[] type = new int[len]; for (int i = 0; i < len; i++) { col[i] = ((int) vColumn[i]); type[i] = table.getType(col[i]); } int count = 0; if (filter.findFirst()) { Result del = new Result(); // don't need column count and so on Result ins = new Result(); int size = table.getColumnCount(); do { if (eCondition == null || eCondition.test()) { object[] nd = filter.oCurrentData; del.add(nd); object[] ni = table.getNewRow(); for (int i = 0; i < size; i++) { ni[i] = nd[i]; } for (int i = 0; i < len; i++) { ni[col[i]] = exp[i].getValue(type[i]); } ins.add(ni); } } while (filter.next()); cChannel.beginNestedTransaction(); try { Record nd = del.rRoot; while (nd != null) { table.deleteNoCheck(nd.data, cChannel); nd = nd.next; } Record ni = ins.rRoot; while (ni != null) { table.insertNoCheck(ni.data, cChannel); ni = ni.next; count++; } table.checkUpdate(col, del, ins); ni = ins.rRoot; while (ni != null) { ni = ni.next; } cChannel.endNestedTransaction(false); } catch (Exception e) { // update failed (violation of primary key / referential integrity) cChannel.endNestedTransaction(true); throw e; } } Result r = new Result(); r.iUpdateCount = count; return r; }
/** * Method declaration * * * @return * * @throws Exception */ public Result processDelete() { tTokenizer.getThis("FROM"); string token = tTokenizer.getstring(); cChannel.checkReadWrite(); cChannel.check(token, Access.DELETE); Table table = dDatabase.getTable(token, cChannel); TableFilter filter = new TableFilter(table, null, false); token = tTokenizer.getstring(); Expression eCondition = null; if (token.Equals("WHERE")) { eCondition = parseExpression(); eCondition.resolve(filter); filter.setCondition(eCondition); } else { tTokenizer.back(); } int count = 0; if (filter.findFirst()) { Result del = new Result(); // don't need column count and so on do { if (eCondition == null || eCondition.test()) { del.add(filter.oCurrentData); } } while (filter.next()); Record n = del.rRoot; while (n != null) { table.delete(n.data, cChannel); count++; n = n.next; } } Result r = new Result(); r.iUpdateCount = count; return r; }
/** * Method declaration * * * @return * * @throws Exception */ private Select parseSelect() { Select select = new Select(); // [email protected] begin changes from 1.50 select.limitStart = 0; select.limitCount = cChannel.getMaxRows(); // [email protected] end changes from 1.50 string token = tTokenizer.getstring(); if (token.Equals("DISTINCT")) { select.bDistinct = true; // [email protected] begin changes from 1.50 } else if( token.Equals("LIMIT")) { string limStart = tTokenizer.getstring(); string limEnd = tTokenizer.getstring(); //System.out.println( "LIMIT used from "+limStart+","+limEnd); select.limitStart = limStart.ToInt32(); select.limitCount = limEnd.ToInt32(); // [email protected] end changes from 1.50 } else { tTokenizer.back(); } // parse column list ArrayList vcolumn = new ArrayList(); do { Expression e = parseExpression(); token = tTokenizer.getstring(); if (token.Equals("AS")) { e.setAlias(tTokenizer.getName()); token = tTokenizer.getstring(); } else if (tTokenizer.wasName()) { e.setAlias(token); token = tTokenizer.getstring(); } vcolumn.Add(e); } while (token.Equals(",")); if (token.Equals("INTO")) { select.sIntoTable = tTokenizer.getstring(); token = tTokenizer.getstring(); } if (!token.Equals("FROM")) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } Expression condition = null; // parse table list ArrayList vfilter = new ArrayList(); vfilter.Add(parseTableFilter(false)); while (true) { token = tTokenizer.getstring(); if (token.Equals("LEFT")) { token = tTokenizer.getstring(); if (token.Equals("OUTER")) { token = tTokenizer.getstring(); } Trace.check(token.Equals("JOIN"), Trace.UNEXPECTED_TOKEN, token); vfilter.Add(parseTableFilter(true)); tTokenizer.getThis("ON"); condition = addCondition(condition, parseExpression()); } else if (token.Equals("INNER")) { tTokenizer.getThis("JOIN"); vfilter.Add(parseTableFilter(false)); tTokenizer.getThis("ON"); condition = addCondition(condition, parseExpression()); } else if (token.Equals(",")) { vfilter.Add(parseTableFilter(false)); } else { break; } } tTokenizer.back(); int len = vfilter.Count; TableFilter[] filter = new TableFilter[len]; vfilter.CopyTo(filter); select.tFilter = filter; // expand [table.]* columns len = vcolumn.Count; for (int i = 0; i < len; i++) { Expression e = (Expression) (vcolumn[i]); if (e.getType() == Expression.ASTERIX) { int current = i; Table table = null; string n = e.getTableName(); for (int t = 0; t < filter.Length; t++) { TableFilter f = filter[t]; e.resolve(f); if (n != null &&!n.Equals(f.getName())) { continue; } table = f.getTable(); int col = table.getColumnCount(); for (int c = 0; c < col; c++) { Expression ins = new Expression(f.getName(), table.getColumnName(c)); vcolumn.Insert(current++,ins); // now there is one element more to parse len++; } } Trace.check(table != null, Trace.TABLE_NOT_FOUND, n); // minus the asterix element len--; vcolumn.RemoveAt(current); } else if (e.getType()==Expression.COLUMN) { if (e.getTableName() == null) { for (int filterIndex=0; filterIndex < filter.Length; filterIndex++) { e.resolve(filter[filterIndex]); } } } } select.iResultLen = len; // where token = tTokenizer.getstring(); if (token.Equals("WHERE")) { condition = addCondition(condition, parseExpression()); token = tTokenizer.getstring(); } select.eCondition = condition; if (token.Equals("GROUP")) { tTokenizer.getThis("BY"); len = 0; do { vcolumn.Add(parseExpression()); token = tTokenizer.getstring(); len++; } while (token.Equals(",")); select.iGroupLen = len; } if (token.Equals("ORDER")) { tTokenizer.getThis("BY"); len = 0; do { Expression e = parseExpression(); if (e.getType() == Expression.VALUE) { // order by 1,2,3 if (e.getDataType() == Column.INTEGER) { int i = ((int) e.getValue()).ToInt32(); e = (Expression) vcolumn[i - 1]; } } else if (e.getType() == Expression.COLUMN && e.getTableName() == null) { // this could be an alias column string s = e.getColumnName(); for (int i = 0; i < vcolumn.Count; i++) { Expression ec = (Expression) vcolumn[i]; if (s.Equals(ec.getAlias())) { e = ec; break; } } } token = tTokenizer.getstring(); if (token.Equals("DESC")) { e.setDescending(); token = tTokenizer.getstring(); } else if (token.Equals("ASC")) { token = tTokenizer.getstring(); } vcolumn.Add(e); len++; } while (token.Equals(",")); select.iOrderLen = len; } len = vcolumn.Count; select.eColumn = new Expression[len]; vcolumn.CopyTo(select.eColumn); if (token.Equals("UNION")) { token = tTokenizer.getstring(); if (token.Equals("ALL")) { select.iUnionType = Select.UNIONALL; } else { select.iUnionType = Select.UNION; tTokenizer.back(); } tTokenizer.getThis("SELECT"); select.sUnion = parseSelect(); } else if (token.Equals("INTERSECT")) { tTokenizer.getThis("SELECT"); select.iUnionType = Select.INTERSECT; select.sUnion = parseSelect(); } else if (token.Equals("EXCEPT") || token.Equals("MINUS")) { tTokenizer.getThis("SELECT"); select.iUnionType = Select.EXCEPT; select.sUnion = parseSelect(); } else { tTokenizer.back(); } return select; }