private Expression ParseExpression() { Read (); // todo: really this should be in readTerm // but then grouping is much more complex if (iToken == ExpressionType.Minimum || iToken == ExpressionType.Maximum || iToken == ExpressionType.Count || iToken == ExpressionType.Sum || iToken == ExpressionType.Average) { ExpressionType type = iToken; Read (); Expression r = new Expression (type, ReadOr (), null); tTokenizer.Back (); return r; } Expression rx = ReadOr (); tTokenizer.Back (); return rx; }
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; }
private Expression AddCondition(Expression e1, Expression e2) { if (e1 == null) { return e2; } else if (e2 == null) { return e1; } else { return new Expression (ExpressionType.And, e1, e2); } }
/// <summary> /// Sets the second argument value. /// </summary> /// <param name="value"></param> public void SetArg2(object value) { eArg2 = new Expression( _columnType, value ); }
private Expression ReadTerm() { Expression r = null; if (iToken == ExpressionType.DatabaseColumn) { string name = sToken; r = new Expression (sTable, sToken); Read (); if (iToken == ExpressionType.Open) { Function f = new Function (dDatabase.GetAlias (name), cChannel); /*int len = */f.GetArgCount (); int i = 0; Read (); if (iToken != ExpressionType.Close) { while (true) { f.SetArgument (i++, ReadOr ()); if (iToken != ExpressionType.Comma) { break; } Read (); } } ReadThis (ExpressionType.Close); r = new Expression (f); } } else if (iToken == ExpressionType.Negate) { ExpressionType type = iToken; Read (); r = new Expression (type, ReadTerm (), null); } else if (iToken == ExpressionType.Plus) { Read (); r = ReadTerm (); } else if (iToken == ExpressionType.Open) { Read (); r = ReadOr (); if (iToken != ExpressionType.Close) { throw TracingHelper.Error (TracingHelper.UnexpectedToken, sToken); } Read (); } else if (iToken == ExpressionType.Value) { r = new Expression (iType, oData); Read (); } else if (iToken == ExpressionType.Select) { r = new Expression (ParseSelect ()); Read (); } else if (iToken == ExpressionType.Multiply) { r = new Expression (sTable, null); Read (); } else if (iToken == ExpressionType.IfNull || iToken == ExpressionType.Concat) { ExpressionType type = iToken; Read (); ReadThis (ExpressionType.Open); r = ReadOr (); ReadThis (ExpressionType.Comma); r = new Expression (type, r, ReadOr ()); ReadThis (ExpressionType.Close); } else if (iToken == ExpressionType.CaseWhen) { ExpressionType type = iToken; Read (); ReadThis (ExpressionType.Open); r = ReadOr (); ReadThis (ExpressionType.Comma); Expression thenelse = ReadOr (); ReadThis (ExpressionType.Comma); // thenelse part is never evaluated; only init thenelse = new Expression (type, thenelse, ReadOr ()); r = new Expression (type, r, thenelse); ReadThis (ExpressionType.Close); } else if (iToken == ExpressionType.Convert) { ExpressionType type = iToken; Read (); ReadThis (ExpressionType.Open); r = ReadOr (); ReadThis (ExpressionType.Comma); ColumnType t = Column.GetColumnType (sToken); r = new Expression (type, r, null); r.SetDataType (t); Read (); ReadThis (ExpressionType.Close); } else if (iToken == ExpressionType.Cast) { Read (); ReadThis (ExpressionType.Open); r = ReadOr (); TracingHelper.Check (sToken.Equals ("AS"), TracingHelper.UnexpectedToken, sToken); Read (); ColumnType t = Column.GetColumnType (sToken); r = new Expression (ExpressionType.Convert, r, null); r.SetDataType (t); Read (); ReadThis (ExpressionType.Close); } else if (iToken == ExpressionType.Variable) { ExpressionType type = iToken; r = new Expression (null, sToken); r.Type = type; string columnType = tTokenizer.GetString (); if (Column.IsValidDataType (columnType)) { ColumnType iType = Column.GetColumnType (columnType); if (iType == ColumnType.VarChar && dDatabase.IsIgnoreCase) { iType = ColumnType.VarCharIgnoreCase; } r.SetDataType (iType); r.SetArg (null); } else { tTokenizer.Back (); Declare declare = cChannel.GetDeclare (r.ColumnName); if (declare != null) { r = declare.Expression; } else { throw TracingHelper.Error (TracingHelper.VARIABLE_NOT_DECLARED, sToken); } } Read (); } else if (iToken == ExpressionType.SquareBracketLeft) { ReadThis (ExpressionType.SquareBracketLeft); var t = ReadTerm (); if (t.Type != ExpressionType.DatabaseColumn) { throw TracingHelper.Error (TracingHelper.FIELD_OF_TABLE_IS_EXPECTED, /*tTokenizer.GetString()*/ "???"); } ReadThis (ExpressionType.SquareBracketRight); return t; } else { throw TracingHelper.Error (TracingHelper.UnexpectedToken, sToken); } return r; }
private Expression ReadOr() { Expression r = ReadAnd (); while (iToken == ExpressionType.Or) { ExpressionType type = iToken; Expression a = r; Read (); r = new Expression (type, a, ReadAnd ()); } return r; }
private void AddAndCondition(Expression e) { Expression e2 = new Expression(e); if (eAnd == null) { eAnd = e2; } else { Expression and = new Expression(ExpressionType.And, eAnd, e2); eAnd = and; } e.SetTrue(); }
private Expression ReadCondition() { if (iToken == ExpressionType.Not) { ExpressionType type = iToken; Read (); return new Expression (type, ReadCondition (), null); } else if (iToken == ExpressionType.Exists) { ExpressionType type = iToken; Read (); ReadThis (ExpressionType.Open); TracingHelper.Check (iToken == ExpressionType.Select, TracingHelper.UnexpectedToken); Expression s = new Expression (ParseSelect ()); Read (); ReadThis (ExpressionType.Close); return new Expression (type, s, null); } else { Expression a = ReadConcat (); bool not = false; if (iToken == ExpressionType.Not) { not = true; Read (); } if (iToken == ExpressionType.Like) { Read (); Expression b = ReadConcat (); char escape = '0'; if (sToken.Equals ("ESCAPE")) { Read (); Expression c = ReadTerm (); TracingHelper.Check (c.Type == ExpressionType.Value, TracingHelper.InvalidEscape); string s = (string)c.GetValue (ColumnType.VarChar); if (s == null || s.Length < 1) { throw TracingHelper.Error (TracingHelper.InvalidEscape, s); } escape = Convert.ToChar (s.Substring (0, 1)); } a = new Expression (ExpressionType.Like, a, b); a.SetLikeEscape (escape); } else if (iToken == ExpressionType.Between) { Read (); Expression l = new Expression (ExpressionType.BiggerEqual, a, ReadConcat ()); ReadThis (ExpressionType.And); Expression h = new Expression (ExpressionType.SmallerEqual, a, ReadConcat ()); a = new Expression (ExpressionType.And, l, h); } else if (iToken == ExpressionType.In) { ExpressionType type = iToken; Read (); ReadThis (ExpressionType.Open); Expression b = null; if (iToken == ExpressionType.Select) { b = new Expression (ParseSelect ()); Read (); } else { tTokenizer.Back (); ArrayList v = new ArrayList (); while (true) { v.Add (GetValue (ColumnType.VarChar)); Read (); if (iToken != ExpressionType.Comma) { break; } } b = new Expression (v); } ReadThis (ExpressionType.Close); a = new Expression (type, a, b); } else { TracingHelper.Check (!not, TracingHelper.UnexpectedToken); if (Expression.IsCompare (iToken)) { ExpressionType type = iToken; Read (); return new Expression (type, a, ReadConcat ()); } return a; } if (not) { a = new Expression (ExpressionType.Not, a, null); } return a; } }
private Expression ReadFactor() { Expression r = ReadTableFieldExpression (); while (iToken == ExpressionType.Multiply || iToken == ExpressionType.Divide) { ExpressionType type = iToken; Expression a = r; Read (); r = new Expression (type, a, ReadTableFieldExpression ()); } return r; }
private Expression ReadConcat() { Expression r = ReadSum (); while (iToken == ExpressionType.StringConcat) { ExpressionType type = ExpressionType.Concat; Expression a = r; Read (); r = new Expression (type, a, ReadSum ()); } return r; }
/// <summary> /// Expression constructor using an <see cref="Expression"/>. /// </summary> /// <param name="e"></param> public Expression(Expression e) { _type = e.Type; _columnType = e.ColumnType; eArg = e.eArg; eArg2 = e.eArg2; cLikeEscape = e.cLikeEscape; sSelect = e.sSelect; fFunction = e.fFunction; }
/// <summary> /// Swaps the conditions for this expression. /// </summary> public void SwapCondition() { ExpressionType i = ExpressionType.Equal; switch (_type) { case ExpressionType.BiggerEqual: i = ExpressionType.SmallerEqual; break; case ExpressionType.SmallerEqual: i = ExpressionType.BiggerEqual; break; case ExpressionType.Smaller: i = ExpressionType.Bigger; break; case ExpressionType.Bigger: i = ExpressionType.Smaller; break; case ExpressionType.Equal: break; default: TracingHelper.Assert(false, "Expression.swapCondition"); break; } _type = i; Expression e = eArg; eArg = eArg2; eArg2 = e; }
public void SetArgument( int arg, Expression e ) { eArg[arg] = e; hasAggregate = hasAggregate || (e != null && e.IsAggregate); }
private Expression ReadSum() { Expression r = ReadFactor (); while (true) { ExpressionType type; if (iToken == ExpressionType.Plus) { type = ExpressionType.Add; } else if (iToken == ExpressionType.Negate) { type = ExpressionType.Subtract; } else { break; } Expression a = r; Read (); r = new Expression (type, a, ReadFactor ()); } return r; }
public void SetCondition(Expression e) { ExpressionType type = e.Type; Expression e1 = e.Arg; Expression e2 = e.Arg2; if (type == ExpressionType.And) { SetCondition(e1); SetCondition(e2); return; } int candidate; switch (type) { case ExpressionType.NotEqual: case ExpressionType.Like: // todo: maybe use index case ExpressionType.In: candidate = 0; break; case ExpressionType.Equal: candidate = 1; break; case ExpressionType.Bigger: case ExpressionType.BiggerEqual: candidate = 2; break; case ExpressionType.Smaller: case ExpressionType.SmallerEqual: candidate = 3; break; default: // not a condition so forget it return; } if (e1.Filter == this) { // ok include this } else if (e2.Filter == this && candidate != 0) { // swap and try again to allow index usage e.SwapCondition(); SetCondition(e); return; } else { // unrelated: don't include return; } TracingHelper.Assert(e1.Filter == this, "setCondition"); if (!e2.IsResolved) { return; } if (candidate == 0) { AddAndCondition(e); return; } int i = e1.ColumnNumber; Index index = tTable.GetIndexForColumn(i); if (index == null || (iIndex != index && iIndex != null)) { // no index or already another index is used AddAndCondition(e); return; } iIndex = index; if (candidate == 1) { // candidate for both start & end if (eStart != null || eEnd != null) { AddAndCondition(e); return; } eStart = new Expression(e); eEnd = eStart; } else if (candidate == 2) { // candidate for start if (eStart != null) { AddAndCondition(e); return; } eStart = new Expression(e); } else if (candidate == 3) { // candidate for end if (eEnd != null) { AddAndCondition(e); return; } eEnd = new Expression(e); } e.SetTrue(); }
private Expression ReadTableFieldExpression() { Expression r1 = ReadTerm (); if (r1.Type != ExpressionType.DatabaseColumn) { throw TracingHelper.Error (TracingHelper.FIELD_OF_TABLE_IS_EXPECTED, sToken); } //Read (); if (iToken == ExpressionType.Dot) { ReadThis (ExpressionType.Dot); Expression r2 = ReadTerm (); if (r2.Type != ExpressionType.DatabaseColumn) { throw TracingHelper.Error (TracingHelper.FIELD_OF_TABLE_IS_EXPECTED, sToken); } var r = new Expression (ExpressionType.Dot, r1, r2); return r; }/* else { tTokenizer.Back (); }*/ return r1; }
private bool Test(Expression e) { if (e == null) { return true; } return e.Test(); }
/// <summary> /// Expression constructor using two expressions as arguments. /// </summary> /// <param name="type"></param> /// <param name="e"></param> /// <param name="e2"></param> public Expression(ExpressionType type, Expression e, Expression e2) { _type = type; eArg = e; eArg2 = e2; }