public static void Evaluate(ProcedureStatementBodyBase exec, Scope scope) { switch (exec) { case AlterFunctionStatement alterFunc: scope.Env.GetSchema(alterFunc.Name).Functions.Set( alterFunc.Name.BaseIdentifier.Value, BuildFunc(alterFunc)); return; case AlterProcedureStatement alterProc: scope.Env.GetSchema(alterProc.ProcedureReference.Name).Procedures.Set( alterProc.ProcedureReference.Name.BaseIdentifier.Value, BuildProc(alterProc)); return; case CreateFunctionStatement createFunc: scope.Env.GetSchema(createFunc.Name).Functions.Declare( createFunc.Name.BaseIdentifier.Value, BuildFunc(createFunc)); return; case CreateProcedureStatement createProc: scope.Env.GetSchema(createProc.ProcedureReference.Name).Procedures.Declare( createProc.ProcedureReference.Name.BaseIdentifier.Value, BuildProc(createProc)); return; default: throw FeatureNotSupportedException.Subtype(exec); } }
public static EngineResult Evaluate(InsertSpecification insert, IOutputSink sink, Scope scope) { var table = scope.Env.GetTable((NamedTableReference)insert.Target); return(insert.InsertSource switch { ValuesInsertSource values => Evaluate(table, insert.Columns, values, NullArgument.It, sink, scope), SelectInsertSource select => Evaluate(table, insert.Columns, Evaluate(@select.Select, scope).ResultSet, sink, scope), _ => throw FeatureNotSupportedException.Subtype(insert.InsertSource) });
public static object Evaluate(FunctionCall funCall, IArgument arg, Scope scope) { switch (arg) { case GroupArgument group: return(GroupedFunctionCall(funCall, group, scope)); case NullArgument _: case RowArgument _: return(UngroupedFunctionCall(funCall, arg, scope)); default: throw FeatureNotSupportedException.Subtype(arg); } }
public static EngineResult Evaluate(DataModificationSpecification dml, Scope scope) { IOutputSink sink; // TODO: support scalar expressions in TableOutputSink, not just column names // how to handle INSERTED. and DELETED. aliases? if (dml.OutputClause != null || dml.OutputIntoClause != null) { sink = new TableOutputSink( (dml.OutputClause?.SelectColumns ?? dml.OutputIntoClause?.SelectColumns)? .Select(s => new Column { Name = ((ColumnReferenceExpression)((SelectScalarExpression)s).Expression) .MultiPartIdentifier.Identifiers.Select(x => x.Value).ToArray(), Type = DbType.AnsiString }).ToList()); } else { sink = new NullOutputSink(); } var result = dml switch { InsertSpecification insert => Evaluate(insert, sink, scope), MergeSpecification merge => Evaluate(merge, sink, scope), DeleteSpecification delete => Evaluate(delete, sink, scope), UpdateSpecification update => Evaluate(update, sink, scope), _ => throw FeatureNotSupportedException.Subtype(dml) }; if (dml.OutputIntoClause != null) { var(table, scope2) = Evaluate(dml.OutputIntoClause.IntoTable, null, scope); Evaluate( table, dml.OutputIntoClause.IntoTableColumns, ((TableOutputSink)sink).Output, new NullOutputSink(), scope2); } return(dml.OutputClause != null ? new EngineResult(((TableOutputSink)sink).Output) : result); } }
public static EngineResult Evaluate(StatementWithCtesAndXmlNamespaces statement, Scope scope) { if (statement.WithCtesAndXmlNamespaces?.CommonTableExpressions != null) { scope = Evaluate(statement.WithCtesAndXmlNamespaces.CommonTableExpressions, scope); } return(statement switch { SelectStatement select => Evaluate(select, scope), InsertStatement insert => Evaluate(insert.InsertSpecification, scope), UpdateStatement update => Evaluate(update.UpdateSpecification, scope), DeleteStatement delete => Evaluate(delete.DeleteSpecification, scope), MergeStatement merge => Evaluate(merge.MergeSpecification, scope), _ => throw FeatureNotSupportedException.Subtype(statement) });
public static (Table, Scope) Evaluate(TableReference tableRef, Table joinedTables, Scope scope) { switch (tableRef) { case NamedTableReference named: var baseName = named.SchemaObject.BaseIdentifier.Value; var schema = scope.Env.GetSchema(named.SchemaObject); return( schema.Views.GetMaybe(baseName) .Select(v => Evaluate(v.Query, scope).ResultSet) .Or(() => scope.Ctes.GetMaybe(baseName)) .OrElse(() => schema.Tables[baseName]), named.Alias == null ? scope : scope.PushAlias( named.Alias.Value, scope.ExpandTableName(named.SchemaObject.Identifiers.Select(x => x.Value).ToArray()))); case DataModificationTableReference dml: // TODO: how does this work? return(Evaluate(dml.DataModificationSpecification, scope).ResultSet, scope); case JoinParenthesisTableReference paren: return(Evaluate(paren.Join, joinedTables, scope)); case OdbcQualifiedJoinTableReference odbc: return(Evaluate(odbc.TableReference, joinedTables, scope)); case QueryDerivedTable query: var table = Evaluate(query.QueryExpression, scope).ResultSet; table.Name = Guid.NewGuid().ToString().Replace("-", ""); return(table, scope.PushAlias(query.Alias.Value, new[] { table.Name })); case QualifiedJoin qjoin: var(leftTable, leftScope) = Evaluate(qjoin.FirstTableReference, joinedTables, scope); var(rightTable, rightScope) = Evaluate(qjoin.SecondTableReference, leftTable, leftScope); return(Join(leftTable, rightTable, qjoin.SearchCondition, qjoin.QualifiedJoinType, rightScope)); case UnqualifiedJoin ujoin: var(leftTable2, leftScope2) = Evaluate(ujoin.FirstTableReference, joinedTables, scope); var(rightTable2, rightScope2) = Evaluate(ujoin.SecondTableReference, leftTable2, leftScope2); return(Join(leftTable2, rightTable2, ujoin.UnqualifiedJoinType, rightScope2)); default: throw FeatureNotSupportedException.Subtype(tableRef); } }
private static WhenClause MatchingClause(CaseExpression expr, IArgument arg, Scope scope) { switch (expr) { case SimpleCaseExpression simple: var input = Evaluate(simple.InputExpression, arg, scope); return(simple.WhenClauses .FirstOrDefault(x => Equality.Equal(input, Evaluate(x.WhenExpression, arg, scope)))); case SearchedCaseExpression searched: return(searched.WhenClauses .FirstOrDefault(x => Evaluate(x.WhenExpression, arg, scope))); default: throw FeatureNotSupportedException.Subtype(expr); } }
public static bool Evaluate(BooleanExpression expr, IArgument arg, Scope scope) { switch (expr) { case BooleanParenthesisExpression paren: return(Evaluate(paren.Expression, arg, scope)); case BooleanBinaryExpression binaryExpr: return(Evaluate( binaryExpr.BinaryExpressionType, Evaluate(binaryExpr.FirstExpression, arg, scope), Evaluate(binaryExpr.SecondExpression, arg, scope))); case BooleanTernaryExpression ternaryExpr: return(Evaluate( ternaryExpr.TernaryExpressionType, Evaluate(ternaryExpr.FirstExpression, arg, scope), Evaluate(ternaryExpr.SecondExpression, arg, scope), Evaluate(ternaryExpr.ThirdExpression, arg, scope))); case BooleanComparisonExpression compareExpr: return(Evaluate( compareExpr.ComparisonType, Evaluate(compareExpr.FirstExpression, arg, scope), Evaluate(compareExpr.SecondExpression, arg, scope))); case BooleanNotExpression notExpr: return(!Evaluate(notExpr.Expression, arg, scope)); case BooleanIsNullExpression isNullExpr: return(Evaluate(isNullExpr.Expression, arg, scope) == null); case InPredicate inExpr: var value = Evaluate(inExpr.Expression, arg, scope); return(value != null && inExpr.Values.Any(x => value.Equals(Evaluate(x, arg, scope)))); case ExistsPredicate existsExpr: return(Evaluate(existsExpr.Subquery.QueryExpression, scope).ResultSet.Rows.Count > 0); default: throw FeatureNotSupportedException.Subtype(expr); } }
public static void Evaluate(CursorStatement statement, Scope scope) { // TODO: global cursors? statement.Cursor.IsGlobal var name = statement.Cursor.Name.Value; var cursor = (Cursor)scope.Env.Vars[name]; switch (statement) { case OpenCursorStatement _: cursor.Open(scope); return; case CloseCursorStatement _: cursor.Close(); return; case DeallocateCursorStatement _: cursor.Deallocate(); return; case FetchCursorStatement fetch: var result = CursorFetch(fetch, cursor, scope); scope.Env.FetchStatus = result == null ? 1 : 0; if (result == null) { return; } foreach (var(v, x) in fetch.IntoVariables.Zip(result.Values, (v, x) => (v, x))) { scope.Env.Vars.DeclareOrSet(v.Name, x); } return; default: throw FeatureNotSupportedException.Subtype(statement); } }
public static void Evaluate(IList <SetClause> clauses, Row targetRow, Row sourceRow, IOutputSink sink, Scope scope) { var originalTargetRow = targetRow.Copy(); foreach (var clause in clauses) { switch (clause) { case AssignmentSetClause set: var columnName = set.Column.MultiPartIdentifier.Identifiers.Last().Value; targetRow.Values[targetRow.GetColumnOrdinal(columnName)] = Evaluate( set.AssignmentKind, sourceRow.Values[sourceRow.GetColumnOrdinal(columnName)], Evaluate(set.NewValue, new RowArgument(sourceRow), scope)); break; default: throw FeatureNotSupportedException.Subtype(clause); } } sink.Updated(originalTargetRow, targetRow, scope.Env); }
public static void Evaluate(DropObjectsStatement drop, Scope scope) { switch (drop) { case DropFunctionStatement _: DropAll(drop, scope.Env.Functions); return; case DropProcedureStatement _: DropAll(drop, scope.Env.Procedures); return; case DropTableStatement _: DropAll(drop, scope.Env.Tables); return; case DropViewStatement _: DropAll(drop, scope.Env.Views); return; default: throw FeatureNotSupportedException.Subtype(drop); } }
public static void Evaluate(MergeAction action, Table targetTable, Row row, IOutputSink sink, Scope scope) { Row GetTargetRow() => row.Sources[EquatableArray.Of(scope.ExpandTableName(new[] { targetTable.Name }))]; switch (action) { case InsertMergeAction insert: Evaluate(targetTable, insert.Columns, insert.Source, new RowArgument(row), sink, scope); return; case UpdateMergeAction update: Evaluate(update.SetClauses, GetTargetRow(), row, sink, scope); return; case DeleteMergeAction _: var r = GetTargetRow(); sink.Deleted(r, scope.Env); targetTable.Rows.Remove(r); return; default: throw FeatureNotSupportedException.Subtype(action); } }
public static EngineResult Evaluate(QueryExpression queryExpr, Scope scope) { var result = queryExpr switch { QuerySpecification querySpec => Evaluate(querySpec, scope), QueryParenthesisExpression paren => Evaluate(paren.QueryExpression, scope), BinaryQueryExpression binaryExpr => Evaluate( binaryExpr.BinaryQueryExpressionType, binaryExpr.All, Evaluate(binaryExpr.FirstQueryExpression, scope).ResultSet, Evaluate(binaryExpr.SecondQueryExpression, scope).ResultSet, scope.Env), _ => throw FeatureNotSupportedException.Subtype(queryExpr) }; if (result.ResultSet == null) { return(result); } var projection = result.ResultSet; // ORDER BY if (queryExpr.OrderByClause != null) { var elements = queryExpr.OrderByClause.OrderByElements; var firstElement = elements.First(); var restElements = elements.Skip(1); var temp = projection.CopyLayout(); foreach (var row in restElements.Aggregate( Order(projection.Rows, firstElement, scope), (orderedRows, element) => Order(orderedRows, element, scope))) { CopyOnto(row, temp, scope.Env); } projection.Rows.Clear(); CopyOnto(temp, projection, scope.Env); } // OFFSET if (queryExpr.OffsetClause != null) { var offset = Evaluate <int>(queryExpr.OffsetClause.OffsetExpression, NullArgument.It, scope); for (var i = 0; i < offset; ++i) { projection.Rows.RemoveAt(0); } if (queryExpr.OffsetClause.FetchExpression != null) { var fetch = Evaluate <int>(queryExpr.OffsetClause.FetchExpression, NullArgument.It, scope); while (projection.Rows.Count > fetch) { projection.Rows.RemoveAt(projection.Rows.Count - 1); } } } return(new EngineResult(projection)); } }