6 // Juraj Skripsky (juraj@hotfeet.ch)
8 // (C) 2004 HotFeet GmbH (http://www.hotfeet.ch)
9 // Copyright 2011 Xamarin Inc (http://www.xamarin.com)
13 using System.Collections;
16 namespace Mono.Data.SqlExpressions {
18 internal class Parser {
21 if (Environment.GetEnvironmentVariable ("MONO_DEBUG_SQLEXPRESSIONS") != null)
22 yacc_verbose_flag = 2;
25 bool cacheAggregationResults = false;
26 DataRow[] aggregationRows = null;
27 static int yacc_verbose_flag;
29 //called by DataTable.Select
30 //called by DataColumn.set_Expression //FIXME: enable cache in this case?
32 ErrorOutput = System.IO.TextWriter.Null;
33 cacheAggregationResults = true;
36 //called by DataTable.Compute
37 public Parser (DataRow[] aggregationRows)
39 ErrorOutput = System.IO.TextWriter.Null;
40 this.aggregationRows = aggregationRows;
43 public IExpression Compile (string sqlExpr)
46 Tokenizer tokenizer = new Tokenizer (sqlExpr);
47 if (yacc_verbose_flag > 1)
48 return (IExpression) yyparse (tokenizer,
49 new yydebug.yyDebugSimple ());
51 return (IExpression) yyparse (tokenizer);
52 } catch (yyParser.yyException) {
53 throw new SyntaxErrorException (String.Format ("Expression '{0}' is invalid.", sqlExpr));
58 %token PAROPEN PARCLOSE
75 %token IS IN NOT_IN LIKE NOT_LIKE
77 %token COUNT SUM AVG MAX MIN STDEV VAR
78 %token IIF SUBSTRING ISNULL LEN TRIM CONVERT
80 %token StringLiteral NumberLiteral DateLiteral
105 : PAROPEN BoolExpr PARCLOSE
107 $$ = (IExpression)$2;
109 | BoolExpr AND BoolExpr
111 $$ = new BoolOperation (Operation.AND, (IExpression)$1, (IExpression)$3);
113 | BoolExpr OR BoolExpr
115 $$ = new BoolOperation (Operation.OR, (IExpression)$1, (IExpression)$3);
119 $$ = new Negation ((IExpression)$2);
132 : ArithExpr CompOp ArithExpr
134 $$ = new Comparison ((Operation)$2, (IExpression)$1, (IExpression)$3);
139 : EQ { $$ = Operation.EQ; }
140 | NE { $$ = Operation.NE; }
141 | LT { $$ = Operation.LT; }
142 | GT { $$ = Operation.GT; }
143 | LE { $$ = Operation.LE; }
144 | GE { $$ = Operation.GE; }
152 : PAROPEN ArithExpr PARCLOSE
154 $$ = (IExpression)$2;
156 | ArithExpr MUL ArithExpr
158 $$ = new ArithmeticOperation (Operation.MUL, (IExpression)$1, (IExpression)$3);
160 | ArithExpr DIV ArithExpr
162 $$ = new ArithmeticOperation (Operation.DIV, (IExpression)$1, (IExpression)$3);
164 | ArithExpr MOD ArithExpr
166 $$ = new ArithmeticOperation (Operation.MOD, (IExpression)$1, (IExpression)$3);
168 | ArithExpr PLUS ArithExpr
170 $$ = new ArithmeticOperation (Operation.ADD, (IExpression)$1, (IExpression)$3);
172 | ArithExpr MINUS ArithExpr
174 $$ = new ArithmeticOperation (Operation.SUB, (IExpression)$1, (IExpression)$3);
176 | MINUS ArithExpr %prec UMINUS
178 $$ = new Negative ((IExpression)$2);
190 : StringLiteral { $$ = new Literal ($1); }
191 | NumberLiteral { $$ = new Literal ($1); }
192 | DateLiteral { $$ = new Literal ($1); }
194 | NULL { $$ = new Literal (null); }
198 : TRUE { $$ = new Literal (true); }
199 | FALSE { $$ = new Literal (false); }
215 $$ = new ColumnReference ((string)$1);
220 : PARENT DOT ColumnName
222 $$ = new ColumnReference (ReferencedTable.Parent, null, (string)$3);
224 | PARENT PAROPEN RelationName PARCLOSE DOT ColumnName
226 $$ = new ColumnReference (ReferencedTable.Parent, (string)$3, (string)$6);
231 : CHILD DOT ColumnName
233 $$ = new ColumnReference (ReferencedTable.Child, null, (string)$3);
235 | CHILD PAROPEN RelationName PARCLOSE DOT ColumnName
237 $$ = new ColumnReference (ReferencedTable.Child, (string)$3, (string)$6);
243 | ColumnName DOT Identifier
245 $$ = (string)$1 + "." + (string)$3;
259 : AggFunctionName PAROPEN MultiColumnValue PARCLOSE
261 $$ = new Aggregation (cacheAggregationResults, aggregationRows, (AggregationFunction)$1, (ColumnReference)$3);
266 : COUNT { $$ = AggregationFunction.Count; }
267 | SUM { $$ = AggregationFunction.Sum; }
268 | AVG { $$ = AggregationFunction.Avg; }
269 | MAX { $$ = AggregationFunction.Max; }
270 | MIN { $$ = AggregationFunction.Min; }
271 | STDEV { $$ = AggregationFunction.StDev; }
272 | VAR { $$ = AggregationFunction.Var; }
277 | StringLiteral { $$ = new Literal ($1); }
282 : TRIM PAROPEN ArithExpr PARCLOSE
284 $$ = new TrimFunction ((IExpression)$3);
286 | SUBSTRING PAROPEN ArithExpr COMMA ArithExpr COMMA ArithExpr PARCLOSE
288 $$ = new SubstringFunction ((IExpression)$3, (IExpression)$5, (IExpression)$7);
293 : IIF PAROPEN Expr COMMA Expr COMMA Expr PARCLOSE
295 $$ = new IifFunction ((IExpression)$3, (IExpression)$5, (IExpression)$7);
297 | ISNULL PAROPEN Expr COMMA Expr PARCLOSE
299 $$ = new IsNullFunction ((IExpression)$3, (IExpression)$5);
301 | LEN PAROPEN Expr PARCLOSE
303 $$ = new LenFunction ((IExpression)$3);
305 | CONVERT PAROPEN Expr COMMA TypeSpecifier PARCLOSE
307 $$ = new ConvertFunction ((IExpression)$3, (string)$5);
319 $$ = new Comparison (Operation.EQ, (IExpression)$1, new Literal (null));
321 | ArithExpr IS NOT NULL
323 $$ = new Comparison (Operation.NE, (IExpression)$1, new Literal (null));
328 : StringExpr LIKE StringExpr
330 $$ = new Like ((IExpression)$1, (IExpression)$3);
332 | StringExpr NOT_LIKE StringExpr
334 $$ = new Negation (new Like ((IExpression)$1, (IExpression)$3));
339 : ArithExpr IN InPredicateValue
341 $$ = new In ((IExpression)$1, (IList)$3);
343 | ArithExpr NOT_IN InPredicateValue
345 $$ = new Negation (new In ((IExpression)$1, (IList)$3));
350 : PAROPEN InValueList PARCLOSE { $$ = $2; }
356 $$ = new ArrayList();
357 ((IList)$$).Add ($1);
359 | InValueList COMMA LiteralValue
361 ((IList)($$ = $1)).Add ($3);