6 // Juraj Skripsky (juraj@hotfeet.ch)
8 // (C) 2004 HotFeet GmbH (http://www.hotfeet.ch)
12 using System.Collections;
15 namespace Mono.Data.SqlExpressions {
17 internal class Parser {
20 if (Environment.GetEnvironmentVariable ("MONO_DEBUG_SQLEXPRESSIONS") != null)
21 yacc_verbose_flag = 2;
24 bool cacheAggregationResults = false;
25 DataRow[] aggregationRows = null;
26 static int yacc_verbose_flag;
28 //called by DataTable.Select
29 //called by DataColumn.set_Expression //FIXME: enable cache in this case?
31 ErrorOutput = System.IO.TextWriter.Null;
32 cacheAggregationResults = true;
35 //called by DataTable.Compute
36 public Parser (DataRow[] aggregationRows)
38 ErrorOutput = System.IO.TextWriter.Null;
39 this.aggregationRows = aggregationRows;
42 public IExpression Compile (string sqlExpr)
45 Tokenizer tokenizer = new Tokenizer (sqlExpr);
46 if (yacc_verbose_flag > 1)
47 return (IExpression) yyparse (tokenizer,
48 new yydebug.yyDebugSimple ());
50 return (IExpression) yyparse (tokenizer);
51 } catch (yyParser.yyException e) {
52 throw new SyntaxErrorException (String.Format ("Expression '{0}' is invalid.", sqlExpr));
57 %token PAROPEN PARCLOSE
76 %token COUNT SUM AVG MAX MIN STDEV VAR
77 %token IIF SUBSTRING ISNULL LEN TRIM CONVERT
79 %token StringLiteral NumberLiteral DateLiteral
104 : PAROPEN BoolExpr PARCLOSE
106 $$ = (IExpression)$2;
108 | BoolExpr AND BoolExpr
110 $$ = new BoolOperation (Operation.AND, (IExpression)$1, (IExpression)$3);
112 | BoolExpr OR BoolExpr
114 $$ = new BoolOperation (Operation.OR, (IExpression)$1, (IExpression)$3);
118 $$ = new Negation ((IExpression)$2);
131 : ArithExpr CompOp ArithExpr
133 $$ = new Comparison ((Operation)$2, (IExpression)$1, (IExpression)$3);
138 : EQ { $$ = Operation.EQ; }
139 | NE { $$ = Operation.NE; }
140 | LT { $$ = Operation.LT; }
141 | GT { $$ = Operation.GT; }
142 | LE { $$ = Operation.LE; }
143 | GE { $$ = Operation.GE; }
151 : PAROPEN ArithExpr PARCLOSE
153 $$ = (IExpression)$2;
155 | ArithExpr MUL ArithExpr
157 $$ = new ArithmeticOperation (Operation.MUL, (IExpression)$1, (IExpression)$3);
159 | ArithExpr DIV ArithExpr
161 $$ = new ArithmeticOperation (Operation.DIV, (IExpression)$1, (IExpression)$3);
163 | ArithExpr MOD ArithExpr
165 $$ = new ArithmeticOperation (Operation.MOD, (IExpression)$1, (IExpression)$3);
167 | ArithExpr PLUS ArithExpr
169 $$ = new ArithmeticOperation (Operation.ADD, (IExpression)$1, (IExpression)$3);
171 | ArithExpr MINUS ArithExpr
173 $$ = new ArithmeticOperation (Operation.SUB, (IExpression)$1, (IExpression)$3);
175 | MINUS ArithExpr %prec UMINUS
177 $$ = new Negative ((IExpression)$2);
189 : StringLiteral { $$ = new Literal ($1); }
190 | NumberLiteral { $$ = new Literal ($1); }
191 | DateLiteral { $$ = new Literal ($1); }
196 : TRUE { $$ = new Literal (true); }
197 | FALSE { $$ = new Literal (false); }
213 $$ = new ColumnReference ((string)$1);
218 : PARENT DOT ColumnName
220 $$ = new ColumnReference (ReferencedTable.Parent, null, (string)$3);
222 | PARENT PAROPEN RelationName PARCLOSE DOT ColumnName
224 $$ = new ColumnReference (ReferencedTable.Parent, (string)$3, (string)$6);
229 : CHILD DOT ColumnName
231 $$ = new ColumnReference (ReferencedTable.Child, null, (string)$3);
233 | CHILD PAROPEN RelationName PARCLOSE DOT ColumnName
235 $$ = new ColumnReference (ReferencedTable.Child, (string)$3, (string)$6);
241 | ColumnName DOT Identifier
243 $$ = (string)$1 + "." + (string)$3;
256 : AggFunctionName PAROPEN MultiColumnValue PARCLOSE
258 $$ = new Aggregation (cacheAggregationResults, aggregationRows, (AggregationFunction)$1, (ColumnReference)$3);
263 : COUNT { $$ = AggregationFunction.Count; }
264 | SUM { $$ = AggregationFunction.Sum; }
265 | AVG { $$ = AggregationFunction.Avg; }
266 | MAX { $$ = AggregationFunction.Max; }
267 | MIN { $$ = AggregationFunction.Min; }
268 | STDEV { $$ = AggregationFunction.StDev; }
269 | VAR { $$ = AggregationFunction.Var; }
273 : IIF PAROPEN BoolExpr COMMA Expr COMMA Expr PARCLOSE
275 $$ = new IifFunction ((IExpression)$3, (IExpression)$5, (IExpression)$7);
277 | SUBSTRING PAROPEN Expr COMMA NumberLiteral COMMA NumberLiteral PARCLOSE
279 long arg1 = (long) $5;
280 long arg2 = (long) $7;
281 $$ = new SubstringFunction ((IExpression)$3, Convert.ToInt32(arg1), Convert.ToInt32(arg2));
283 | ISNULL PAROPEN Expr COMMA Expr PARCLOSE
285 $$ = new IsNullFunction ((IExpression)$3, (IExpression)$5);
287 | LEN PAROPEN Expr PARCLOSE
289 $$ = new LenFunction ((IExpression)$3);
291 | TRIM PAROPEN Expr PARCLOSE
293 $$ = new TrimFunction ((IExpression)$3);
295 | CONVERT PAROPEN Expr COMMA TypeSpecifier PARCLOSE
297 $$ = new ConvertFunction ((IExpression)$3, (string)$5);
307 : SingleColumnValue IS NULL
309 $$ = new Comparison (Operation.EQ, (IExpression)$1, new Literal (null));
311 | SingleColumnValue IS NOT NULL
313 $$ = new Comparison (Operation.NE, (IExpression)$1, new Literal (null));
318 : ArithExpr LIKE StringLiteral
320 $$ = new Like ((IExpression)$1, (string)$3);
322 | ArithExpr NOT LIKE StringLiteral
324 $$ = new Negation (new Like ((IExpression)$1, (string)$3));
329 : SingleColumnValue IN InPredicateValue
331 $$ = new In ((IExpression)$1, (IList)$3);
333 | SingleColumnValue NOT IN InPredicateValue
335 $$ = new Negation (new In ((IExpression)$1, (IList)$4));
340 : PAROPEN InValueList PARCLOSE { $$ = $2; }
346 $$ = new ArrayList();
347 ((IList)$$).Add ($1);
349 | InValueList COMMA LiteralValue
351 ((IList)($$ = $1)).Add ($3);