Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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)
            });
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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);
        }
    }
Beispiel #5
0
        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)
            });
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
        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);
            }
        }
Beispiel #10
0
        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);
            }
        }
Beispiel #12
0
        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));
        }
    }