public void Resolve(TableFilter filter) { foreach (Expression ex in eArg) { if (!ex.IsResolved) { ex.Resolve(filter); } } }
public void Resolve(TableFilter filter, bool ownfilter) { if (eCondition != null) { // first set the table filter in the condition eCondition.Resolve(filter); if (filter != null && ownfilter) { // the table filter tries to get as many conditions as possible // but only if the table filter belongs to this query filter.SetCondition(eCondition); } } int len = eColumn.Length; for (int i = 0; i < len; i++) { eColumn[i].Resolve(filter); } }
/// <summary> /// Resolve the current expression. /// </summary> /// <param name="filter"></param> public void Resolve(TableFilter filter) { if (filter != null && _type == ExpressionType.DatabaseColumn) { if (sTable == null || filter.Name.Equals(sTable)) { int i = filter.Table.SearchColumn(sColumn); if (i != -1) { // todo: other error message: multiple tables are possible Trace.Check(tFilter == null || tFilter == filter, Trace.COLUMN_NOT_FOUND, sColumn); tFilter = filter; iColumn = i; sTable = filter.Name; _columnType = filter.Table.GetColumnType(i); } } } // currently sets only data type // todo: calculate fixed expressions if possible if (eArg != null) { eArg.Resolve(filter); } if (eArg2 != null) { eArg2.Resolve(filter); } if (sSelect != null) { sSelect.Resolve(filter, false); sSelect.Resolve(); } if (fFunction != null) { fFunction.Resolve(filter); } if (_columnType != ColumnType.Null) { return; } switch (_type) { case ExpressionType.Function: _columnType = fFunction.GetReturnType(); break; case ExpressionType.Query: _columnType = sSelect.eColumn[0].ColumnType; break; case ExpressionType.Negate: _columnType = eArg.ColumnType; break; case ExpressionType.Add: case ExpressionType.Subtract: case ExpressionType.Multiply: case ExpressionType.Divide: _columnType = eArg._columnType; break; case ExpressionType.Concat: _columnType = ColumnType.VarChar; break; case ExpressionType.Not: case ExpressionType.BiggerEqual: case ExpressionType.Bigger: case ExpressionType.Smaller: case ExpressionType.SmallerEqual: case ExpressionType.NotEqual: case ExpressionType.Like: case ExpressionType.And: case ExpressionType.Or: case ExpressionType.In: case ExpressionType.Exists: _columnType = ColumnType.Bit; break; case ExpressionType.Equal: if (this.IsVarAssign) { _columnType = eArg2.ColumnType; } else { _columnType = ColumnType.Bit; } break; case ExpressionType.Count: _columnType = ColumnType.Integer; break; case ExpressionType.Maximum: case ExpressionType.Minimum: case ExpressionType.Sum: case ExpressionType.Average: _columnType = eArg.ColumnType; break; case ExpressionType.Convert: // it is already set break; case ExpressionType.IfNull: case ExpressionType.CaseWhen: _columnType = eArg2.ColumnType; break; case ExpressionType.Variable: _columnType = eArg.ColumnType; break; } }
public void Resolve( TableFilter filter ) { foreach( Expression ex in eArg ) { if( !ex.IsResolved ) ex.Resolve(filter); } }
// [email protected] end changes from 1.50 // [email protected] begin changes from 1.50 public Result GetResult(int start, int cnt, Channel cChannel) { 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.Type[i] = e.ColumnType; 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; } int count = 0; int filter = tFilter.Length; bool[] first = new bool[filter]; int level = 0; while (level >= 0) { bool found = false; if (filter > 0) { TableFilter t = tFilter[level]; if (!first[level]) { found = t.FindFirst(); first[level] = found; } else { found = t.Next(); first[level] = found; } } if (!found) { level--; if (!OnlyVars) { 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(); if (cChannel != null && eColumn[i].IsVarAssign) { cChannel.SetDeclareValue(eColumn[i].Arg.ColumnName, row[i]); } } count++; if (aggregated && !grouped) { 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.Root; Result x = new Result(len); for (int i = 0; i < len; i++) { x.Type[i] = r.Type[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.Type[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 maybe is 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.Label[i] = e.Alias; r.Table[i] = e.TableName; r.Name[i] = e.ColumnName; } if (sUnion != null) { Result x = sUnion.GetResult(0, cChannel); if (UnionType == SelectType.Union) { r.Append(x); r = RemoveDuplicates(r); } else if (UnionType == SelectType.UnionAll) { r.Append(x); } else if (UnionType == SelectType.Intersect) { r = RemoveDuplicates(r); x = RemoveDuplicates(x); r = RemoveDifferent(r, x); } else if (UnionType == SelectType.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); }
private Select ParseSelect() { Select select = new Select (); // [email protected] begin changes from 1.50 select.limitStart = 0; select.limitCount = cChannel.MaxRows; // [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 = int.Parse (limStart); select.limitCount = int.Parse (limEnd); // [email protected] end changes from 1.50 } else { tTokenizer.Back (); } // parse column list ArrayList vcolumn = new ArrayList (); select.OnlyVars = true; do { Expression e = ParseExpression (); token = tTokenizer.GetString (); if (token.Equals ("AS")) { e.Alias = tTokenizer.GetName (); token = tTokenizer.GetString (); } else if (tTokenizer.WasName) { e.Alias = token; token = tTokenizer.GetString (); } vcolumn.Add (e); select.OnlyVars = select.OnlyVars & (e.Type == ExpressionType.Variable); } while (token.Equals (",")); if (!select.OnlyVars) { if (token.Equals ("INTO")) { select.sIntoTable = tTokenizer.GetString (); token = tTokenizer.GetString (); } if (!token.Equals ("FROM")) { throw TracingHelper.Error (TracingHelper.UnexpectedToken, 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 (); } TracingHelper.Check (token.Equals ("JOIN"), TracingHelper.UnexpectedToken, 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.Type == ExpressionType.Asterix) { int current = i; Table table = null; string n = e.TableName; for (int t = 0; t < filter.Length; t++) { TableFilter f = filter [t]; e.Resolve (f); if (n != null && !n.Equals (f.Name)) { continue; } table = f.Table; int col = table.ColumnCount; for (int c = 0; c < col; c++) { Expression ins = new Expression (f.Name, table.GetColumnName (c)); vcolumn.Insert (current++, ins); // now there is one element more to parse len++; } } TracingHelper.Check (table != null, TracingHelper.TABLE_NOT_FOUND, n); // minus the asterix element len--; vcolumn.RemoveAt (current); } else if (e.Type == ExpressionType.DatabaseColumn) { if (e.TableName == 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.Type == ExpressionType.Value) { // order by 1,2,3 if (e.ColumnType == ColumnType.Integer) { int i = Convert.ToInt32 (e.GetValue ()); e = (Expression)vcolumn [i - 1]; } } else if (e.Type == ExpressionType.DatabaseColumn && e.TableName == null) { // this could be an alias column string s = e.ColumnName; for (int i = 0; i < vcolumn.Count; i++) { Expression ec = (Expression)vcolumn [i]; if (s.Equals (ec.Alias)) { e = ec; break; } } } token = tTokenizer.GetString (); if (token.Equals ("DESC")) { e.IsDescending = true; 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.UnionType = SelectType.UnionAll; } else { select.UnionType = SelectType.Union; tTokenizer.Back (); } tTokenizer.GetThis ("SELECT"); select.sUnion = ParseSelect (); } else if (token.Equals ("INTERSECT")) { tTokenizer.GetThis ("SELECT"); select.UnionType = SelectType.Intersect; select.sUnion = ParseSelect (); } else if (token.Equals ("EXCEPT") || token.Equals ("MINUS")) { tTokenizer.GetThis ("SELECT"); select.UnionType = SelectType.Except; select.sUnion = ParseSelect (); } else { tTokenizer.Back (); } } else { select.tFilter = new TableFilter[]{ }; int len = vcolumn.Count; select.iResultLen = len; select.eColumn = new Expression[len]; vcolumn.CopyTo (select.eColumn); } return select; }
public Result ProcessUpdate() { string token = tTokenizer.GetString (); cChannel.CheckReadWrite (); cChannel.Check (token, AccessType.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.GetColumnNumber (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]; ColumnType[] type = new ColumnType[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.ColumnCount; do { if (eCondition == null || eCondition.Test ()) { object[] nd = filter.oCurrentData; del.Add (nd); object[] ni = table.NewRow; 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 ()); lock (cChannel.SyncRoot) { cChannel.BeginNestedTransaction (); try { Record nd = del.Root; while (nd != null) { table.DeleteNoCheck (nd.Data, cChannel); nd = nd.Next; } Record ni = ins.Root; while (ni != null) { table.InsertNoCheck (ni.Data, cChannel); ni = ni.Next; count++; } table.CheckUpdate (col, del, ins); ni = ins.Root; 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.SetUpdateCount (count); return r; }
public Result ProcessDelete() { tTokenizer.GetThis ("FROM"); string token = tTokenizer.GetString (); cChannel.CheckReadWrite (); cChannel.Check (token, AccessType.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.Root; while (n != null) { table.Delete (n.Data, cChannel); count++; n = n.Next; } } Result r = new Result (); r.SetUpdateCount (count); return r; }
/// <summary> /// Resolve the current expression. /// </summary> /// <param name="filter"></param> public void Resolve(TableFilter filter) { if (filter != null && _type == ExpressionType.DatabaseColumn) { if (sTable == null || filter.Name.Equals(sTable)) { int i = filter.Table.SearchColumn(sColumn); if (i != -1) { // todo: other error message: multiple tables are possible TracingHelper.Check(tFilter == null || tFilter == filter, TracingHelper.COLUMN_NOT_FOUND, sColumn); tFilter = filter; iColumn = i; sTable = filter.Name; _columnType = filter.Table.GetColumnType(i); } } } // currently sets only data type // todo: calculate fixed expressions if possible if (eArg != null) { eArg.Resolve(filter); } if (eArg2 != null) { eArg2.Resolve(filter); } if (sSelect != null) { sSelect.Resolve(filter, false); sSelect.Resolve(); } if (fFunction != null) { fFunction.Resolve(filter); } if (_columnType != ColumnType.Null) { return; } switch (_type) { case ExpressionType.Function: _columnType = fFunction.GetReturnType(); break; case ExpressionType.Query: _columnType = sSelect.eColumn[0].ColumnType; break; case ExpressionType.Negate: _columnType = eArg.ColumnType; break; case ExpressionType.Add: case ExpressionType.Subtract: case ExpressionType.Multiply: case ExpressionType.Divide: _columnType = eArg._columnType; break; case ExpressionType.Concat: _columnType = ColumnType.VarChar; break; case ExpressionType.Not: case ExpressionType.BiggerEqual: case ExpressionType.Bigger: case ExpressionType.Smaller: case ExpressionType.SmallerEqual: case ExpressionType.NotEqual: case ExpressionType.Like: case ExpressionType.And: case ExpressionType.Or: case ExpressionType.In: case ExpressionType.Exists: _columnType = ColumnType.Bit; break; case ExpressionType.Equal: if( this.IsVarAssign ) { _columnType = eArg2.ColumnType; } else { _columnType = ColumnType.Bit; } break; case ExpressionType.Count: _columnType = ColumnType.Integer; break; case ExpressionType.Maximum: case ExpressionType.Minimum: case ExpressionType.Sum: case ExpressionType.Average: _columnType = eArg.ColumnType; break; case ExpressionType.Convert: // it is already set break; case ExpressionType.IfNull: case ExpressionType.CaseWhen: _columnType = eArg2.ColumnType; break; case ExpressionType.Variable: _columnType = eArg.ColumnType; break; } }