protected override async ValueTask <IQsiAnalysisResult> OnExecute(IAnalyzerContext context)
        {
            if (context.Tree is CqlDerivedTableNode {
                IsJson : true
            } cqlTableNode)
            {
                using var scope = new TableCompileContext(context);
                var table = await BuildTableStructure(scope, cqlTableNode);

                var jsonTable = new QsiTableStructure
                {
                    Identifier = table.Identifier,
                    Type       = table.Type,
                    IsSystem   = table.IsSystem
                };

                jsonTable.References.AddRange(table.References);

                var jsonColumn = jsonTable.NewColumn();

                jsonColumn.Name = new QsiIdentifier("[json]", false);
                jsonColumn.References.AddRange(table.Columns);

                return(new CqlJsonTableAnalysisResult(jsonTable));
            }

            return(await base.OnExecute(context));
        }
Example #2
0
        protected virtual async ValueTask <QsiTableStructure> BuildTableAccessStructure(TableCompileContext context, IQsiTableAccessNode table)
        {
            context.ThrowIfCancellationRequested();

            var lookup = ResolveTableStructure(context, table.Identifier);

            // view
            if (context.Options.UseViewTracing &&
                !lookup.IsSystem &&
                (lookup.Type == QsiTableType.View || lookup.Type == QsiTableType.MaterializedView))
            {
                var script = context.Engine.RepositoryProvider.LookupDefinition(lookup.Identifier, lookup.Type) ??
                             throw new QsiException(QsiError.UnableResolveDefinition, lookup.Identifier);

                var viewTable = (IQsiTableNode)context.Engine.TreeParser.Parse(script) ??
                                throw new QsiException(QsiError.Internal, "Invalid view node");

                var typeBackup = lookup.Type;

                using var viewCompileContext = new TableCompileContext(context);

                if (lookup.Identifier.Level > 1)
                {
                    viewCompileContext.PushIdentifierScope(lookup.Identifier.SubIdentifier(..^ 1));
                }

                var viewTableStructure = await BuildTableStructure(viewCompileContext, viewTable);

                viewTableStructure.Identifier = ResolveQualifiedIdentifier(context, viewTableStructure.Identifier);
                lookup      = viewTableStructure;
                lookup.Type = typeBackup;
            }

            return(lookup);
        }
Example #3
0
        protected override async ValueTask <IQsiAnalysisResult> ExecuteDataDeleteAction(IAnalyzerContext context, IQsiDataDeleteActionNode action)
        {
            var tableAnalyzer = context.Engine.GetAnalyzer <QsiTableAnalyzer>();

            using var tableContext = new TableCompileContext(context);

            var table     = (await tableAnalyzer.BuildTableStructure(tableContext, action.Target)).References[0];
            var tempTable = CreateTemporaryTable(table.Identifier);

            var commonTableNode = ReassembleCommonTableNode(action.Target);
            var dataTable       = await GetDataTableByCommonTableNode(context, commonTableNode);

            var deleteRows = new QsiDataRowCollection(1);

            foreach (var row in dataTable.Rows)
            {
                var targetRow = deleteRows.NewRow();
                targetRow.Items[0] = row.Items[0];
            }

            var dataAction = new QsiDataAction
            {
                Table      = tempTable,
                DeleteRows = deleteRows.ToNullIfEmpty()
            };

            return((new[] { dataAction }).ToResult());
        }
Example #4
0
        protected override QsiIdentifier ResolveDerivedColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiDerivedColumnNode column)
        {
            if (column.IsExpression && column.Alias is null)
            {
                var expr        = column.Expression;
                var parensCount = 0;

                while (expr is IQsiMultipleExpressionNode multipleExpr && multipleExpr.Elements.Length == 1)
                {
                    expr = multipleExpr.Elements[0];
                    parensCount++;
                }

                bool withParens = true;
                var  parent     = table.Parent;

                while (parent is not null)
                {
                    if (parent is IQsiDerivedTableNode)
                    {
                        withParens = false;
                        break;
                    }

                    parent = parent.Parent;
                }

                if (expr is IQsiColumnExpressionNode {
                    Column : IQsiColumnReferenceNode columnReferenceNode
                })
Example #5
0
        public virtual async ValueTask <QsiTableStructure> BuildTableStructure(TableCompileContext context, IQsiTableNode table)
        {
            context.ThrowIfCancellationRequested();

            switch (table)
            {
            case IQsiTableReferenceNode tableReference:
                return(await BuildTableReferenceStructure(context, tableReference));

            case IQsiTableFunctionNode tableFunction:
                return(await BuildTableFunctionStructure(context, tableFunction));

            case IQsiDerivedTableNode derivedTable:
                return(await BuildDerivedTableStructure(context, derivedTable));

            case IQsiInlineDerivedTableNode inlineDerivedTableNode:
                return(await BuildInlineDerivedTableStructure(context, inlineDerivedTableNode));

            case IQsiJoinedTableNode joinedTable:
                return(await BuildJoinedTableStructure(context, joinedTable));

            case IQsiCompositeTableNode compositeTable:
                return(await BuildCompositeTableStructure(context, compositeTable));
            }

            throw new InvalidOperationException();
        }
        protected override ValueTask <QsiTableStructure> BuildDerivedTableStructure(TableCompileContext context, IQsiDerivedTableNode table)
        {
            if (table.Source == null)
            {
                throw new QsiException(QsiError.NoFromClause);
            }

            return(base.BuildDerivedTableStructure(context, table));
        }
Example #7
0
        public override ValueTask <QsiTableStructure> BuildTableStructure(TableCompileContext context, IQsiTableNode table)
        {
            if (table is ImpalaValuesTableNode valuesTableNode)
            {
                return(BuildImpalaValuesTableStructure(context, valuesTableNode));
            }

            return(base.BuildTableStructure(context, table));
        }
Example #8
0
        protected override async ValueTask <IQsiAnalysisResult> OnExecute(IAnalyzerContext context)
        {
            if (!(context.Tree is IQsiTableNode tableNode))
            {
                throw new InvalidOperationException();
            }

            using var scope = new TableCompileContext(context);
            var table = await BuildTableStructure(scope, tableNode);

            return(new QsiTableAnalysisResult(table));
        }
Example #9
0
        protected override IEnumerable <QsiTableColumn> ResolveColumnsInExpression(TableCompileContext context, IQsiExpressionNode expression)
        {
            switch (expression)
            {
            case MySqlAliasedExpressionNode aliasedExpressionNode:
                return(ResolveColumnsInExpression(context, aliasedExpressionNode.Expression.Value));

            case MySqlCollationExpressionNode collationExpressionNode:
                return(ResolveColumnsInExpression(context, collationExpressionNode.Expression.Value));
            }

            return(base.ResolveColumnsInExpression(context, expression));
        }
Example #10
0
        protected override async ValueTask <IQsiAnalysisResult> ExecuteDataUpdateAction(IAnalyzerContext context, IQsiDataUpdateActionNode action)
        {
            var tableAnalyzer = context.Engine.GetAnalyzer <QsiTableAnalyzer>();

            using var tableContext = new TableCompileContext(context);

            var table     = (await tableAnalyzer.BuildTableStructure(tableContext, action.Target)).References[0];
            var tempTable = CreateTemporaryTable(table.Identifier);

            var commonTableNode = ReassembleCommonTableNode(action.Target);
            var dataTable       = await GetDataTableByCommonTableNode(context, commonTableNode);

            var updateBeforeRows = new QsiDataRowCollection(1);
            var updateAfterRows  = new QsiDataRowCollection(1);

            (object[], QsiExpressionNode, bool)[] setValues = action.SetValues
        protected override QsiTableColumn ResolveDeclaredColumn(TableCompileContext context, IQsiDeclaredColumnNode column)
        {
            try
            {
                return(base.ResolveDeclaredColumn(context, column));
            }
            catch (QsiException e) when(e.Error == QsiError.UnknownColumn || e.Error == QsiError.UnknownColumnIn)
            {
                if (OraclePseudoColumn.Contains(column.Name[0].Value))
                {
                    _pseudoTable ??= CreatePseudoTable();
                    return(_pseudoTable.Columns[0]);
                }

                throw;
            }
        }
Example #12
0
        protected override QsiTableColumn ResolveColumnReference(TableCompileContext context, IQsiColumnReferenceNode column)
        {
            try
            {
                return(base.ResolveColumnReference(context, column));
            }
            catch (QsiException e) when(e.Error == QsiError.UnknownColumn || e.Error == QsiError.UnknownColumnIn)
            {
                if (OraclePseudoColumn.Contains(column.Name[0].Value, out var index))
                {
                    _pseudoTable ??= CreatePseudoTable();
                    return(_pseudoTable.Columns[index]);
                }

                throw;
            }
        }
        protected override IEnumerable <QsiTableColumn> ResolveColumnsInExpression(TableCompileContext context, IQsiExpressionNode expression)
        {
            switch (expression)
            {
            case CqlIndexExpressionNode _:
            case CqlMultipleUsingExpressionNode _:
            case CqlUsingExpressionNode _:
                break;

            case CqlIndexerExpressionNode _:
            case CqlRangeExpressionNode _:
            case CqlSetColumnExpressionNode _:
            {
                return(expression.Children
                       .Cast <IQsiExpressionNode>()
                       .SelectMany(n => ResolveColumnsInExpression(context, n)));
            }
            }

            return(base.ResolveColumnsInExpression(context, expression));
        }
Example #14
0
        private ValueTask <QsiTableStructure> BuildImpalaValuesTableStructure(TableCompileContext context, ImpalaValuesTableNode table)
        {
            if (table.Rows.Count == 0)
            {
                throw new QsiException(QsiError.Syntax);
            }

            var structure = new QsiTableStructure
            {
                Type = QsiTableType.Inline
            };

            var columnCount = table.Rows[0].ColumnValues.Count;

            foreach (var value in table.Rows[0].ColumnValues)
            {
                var column = structure.NewColumn();

                if (value is IQsiColumnExpressionNode {
                    Column: IQsiDerivedColumnNode {
                        Alias: { }
                    } derivedColumnNode
                })
Example #15
0
        protected override async ValueTask <QsiTableStructure> BuildViewDefinitionStructure(TableCompileContext context, IQsiViewDefinitionNode viewDefinition)
        {
            var structure = await base.BuildViewDefinitionStructure(context, viewDefinition);

            if (viewDefinition is IDynamicColumnsNode dynamicColumnsNode)
            {
                structure = structure.Clone();
                PatchDynamicColumns(structure, dynamicColumnsNode);
            }

            return(structure);
        }
Example #16
0
 protected virtual QsiIdentifier ResolveDerivedColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiDerivedColumnNode column)
 {
     return(column.Alias?.Name ?? column.InferredName);
 }
        protected override async ValueTask <QsiTableStructure> BuildTableAccessStructure(TableCompileContext context, IQsiTableAccessNode table)
        {
            var structure = await base.BuildTableAccessStructure(context, table);

            if (table is IDynamicTableNode dynamicTableNode)
            {
                structure = structure.Clone();
                PatchDynamicTable(structure, dynamicTableNode);
            }

            return(structure);
        }
        protected override async ValueTask <QsiTableStructure> BuildDerivedTableStructure(TableCompileContext context, IQsiDerivedTableNode table)
        {
            var structure = await base.BuildDerivedTableStructure(context, table);

            if (table is IDynamicTableNode dynamicTableNode)
            {
                PatchDynamicTable(structure, dynamicTableNode);
            }

            return(structure);
        }
Example #19
0
        protected virtual async ValueTask <QsiTableStructure> BuildRecursiveCompositeTableStructure(TableCompileContext context, IQsiDerivedTableNode table, IQsiCompositeTableNode source)
        {
            context.ThrowIfCancellationRequested();

            var declaredTable = new QsiTableStructure
            {
                Type       = QsiTableType.Derived,
                Identifier = new QsiQualifiedIdentifier(table.Alias.Name)
            };

            int sourceOffset = 0;
            var structures   = new List <QsiTableStructure>(source.Sources.Length);

            if (table.Columns.Any(c => c is not IQsiAllColumnNode))
            {
                foreach (var columnNode in table.Columns.Cast <IQsiSequentialColumnNode>())
                {
                    var column = declaredTable.NewColumn();
                    column.Name = columnNode.Alias.Name;
                }
            }
Example #20
0
 protected virtual Task <QsiTableStructure> BuildTableFunctionStructure(TableCompileContext context, IQsiTableFunctionNode table)
 {
     throw TreeHelper.NotSupportedFeature("Table Function");
 }
Example #21
0
 protected virtual QsiIdentifier ResolveCompoundColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiColumnNode column, QsiTableColumn refColumn)
 {
     return(refColumn.Name);
 }
Example #22
0
        protected virtual ValueTask <QsiTableStructure> BuildInlineDerivedTableStructure(TableCompileContext context, IQsiInlineDerivedTableNode table)
        {
            context.ThrowIfCancellationRequested();

            var alias = table.Alias?.Name;

            if (alias == null &&
                table.Parent is IQsiDerivedColumnNode &&
                !context.Options.AllowNoAliasInDerivedTable)
            {
                throw new QsiException(QsiError.NoAlias);
            }

            var declaredTable = new QsiTableStructure
            {
                Type       = QsiTableType.Inline,
                Identifier = alias == null ? null : new QsiQualifiedIdentifier(alias)
            };

            int?columnCount = null;

            switch (table.Columns)
            {
            case null:
            case var cd when cd.All(c => c is IQsiAllColumnNode { Path: null } all) :
                // Skip
                break;

            case var cd when cd.TryCast(out IQsiSequentialColumnNode[] sequentialColumns):
                foreach (var column in sequentialColumns)
                {
                    var c = declaredTable.NewColumn();

                    c.Name = column.Alias.Name;
                }

                columnCount = sequentialColumns.Length;
                break;

            default:
                throw new NotSupportedException("Not supported columns in inline derived table.");
            }

            // Skip trace columns in expression.
            // Because don't know the possibility of declaring a referenceable column in the expression.
            // ISSUE: row.ColumnValues
            foreach (var row in table.Rows ?? Enumerable.Empty <IQsiRowValueExpressionNode>())
            {
                if (!columnCount.HasValue)
                {
                    columnCount = row.ColumnValues.Length;
                }
                else if (columnCount != row.ColumnValues.Length)
                {
                    throw new QsiException(QsiError.DifferentColumnsCount);
                }
            }

            if ((columnCount ?? 0) == 0)
            {
                if (!context.Options.AllowEmptyColumnsInInline)
                {
                    throw new QsiException(QsiError.NoColumnsSpecified, alias);
                }

                columnCount = 0;
            }

            if (declaredTable.Columns.Count != columnCount)
            {
                for (int i = 0; i < columnCount; i++)
                {
                    declaredTable.NewColumn();
                }
            }

            return(new ValueTask <QsiTableStructure>(declaredTable));
        }
Example #23
0
        protected virtual async ValueTask <QsiTableStructure> BuildDerivedTableStructure(TableCompileContext context, IQsiDerivedTableNode table)
        {
            context.ThrowIfCancellationRequested();

            using var scopedContext = new TableCompileContext(context);

            // Directives

            if (table.Directives?.Tables?.Length > 0)
            {
                await BuildDirectives(scopedContext, table.Directives);
            }

            // Table Source

            var alias = table.Alias?.Name;

            if (alias == null &&
                table.Parent is IQsiDerivedColumnNode &&
                !context.Options.AllowNoAliasInDerivedTable)
            {
                throw new QsiException(QsiError.NoAlias);
            }

            if (table.Source is IQsiJoinedTableNode joinedTableNode)
            {
                scopedContext.SourceTable = await BuildJoinedTableStructure(scopedContext, joinedTableNode);
            }
            else if (table.Source != null)
            {
                using var sourceContext   = new TableCompileContext(scopedContext);
                scopedContext.SourceTable = await BuildTableStructure(scopedContext, table.Source);
            }

            var declaredTable = new QsiTableStructure
            {
                Type       = QsiTableType.Derived,
                Identifier = alias == null ? null : new QsiQualifiedIdentifier(alias)
            };

            if (scopedContext.SourceTable != null)
            {
                declaredTable.References.Add(scopedContext.SourceTable);
            }

            var columns = table.Columns;

            if (columns == null || columns.Count == 0)
            {
                if (!context.Options.AllowEmptyColumnsInSelect)
                {
                    throw new QsiException(QsiError.Syntax);
                }
            }
            else if (columns.TryCast(out IQsiSequentialColumnNode[] sequentialColumns))
            {
                // Sequential columns definition

                if (scopedContext.SourceTable == null)
                {
                    throw new QsiException(QsiError.NoTablesUsed);
                }

                var columnType = sequentialColumns[0].ColumnType;
                QsiTableColumn[] allColumns = scopedContext.SourceTable.VisibleColumns.ToArray();
                int columnLength            = allColumns.Length;

                if (sequentialColumns.Length > allColumns.Length)
                {
                    throw new QsiException(QsiError.SpecifiesMoreColumnNames);
                }

                if (columnType == QsiSequentialColumnType.Default)
                {
                    if (sequentialColumns.Length != allColumns.Length)
                    {
                        throw new QsiException(QsiError.DifferentColumnsCount);
                    }

                    columnLength = sequentialColumns.Length;
                }

                for (int i = 0; i < columnLength; i++)
                {
                    var column         = allColumns[i];
                    var declaredColumn = declaredTable.NewColumn();

                    declaredColumn.Name = i < sequentialColumns.Length ? sequentialColumns[i].Alias?.Name : column.Name;
                    declaredColumn.References.Add(column);
                }
            }
            else
            {
                // Compund columns definition

                foreach (var column in columns)
                {
                    IEnumerable <QsiTableColumn> resolvedColumns = ResolveColumns(scopedContext, column);

                    switch (column)
                    {
                    case IQsiDerivedColumnNode derivedColum:
                    {
                        var declaredColumn = declaredTable.NewColumn();

                        declaredColumn.Name         = derivedColum.Alias?.Name;
                        declaredColumn.IsExpression = derivedColum.IsExpression;
                        declaredColumn.References.AddRange(resolvedColumns);
                        break;
                    }

                    case IQsiBindingColumnNode bindingColumn:
                    {
                        var declaredColumn = declaredTable.NewColumn();
                        declaredColumn.Name      = new QsiIdentifier(bindingColumn.Id, false);
                        declaredColumn.IsBinding = true;
                        break;
                    }

                    default:
                    {
                        foreach (var c in resolvedColumns)
                        {
                            var declaredColumn = declaredTable.NewColumn();

                            declaredColumn.Name = c.Name;
                            declaredColumn.References.Add(c);
                        }

                        break;
                    }
                    }
                }
            }

            return(declaredTable);
        }
Example #24
0
        protected virtual async ValueTask <QsiTableStructure> BuildTableReferenceStructure(TableCompileContext context, IQsiTableReferenceNode table)
        {
            context.ThrowIfCancellationRequested();

            var lookup = ResolveTableStructure(context, table.Identifier);

            // view
            if (context.Options.UseViewTracing &&
                !lookup.IsSystem &&
                lookup.Type is QsiTableType.View or QsiTableType.MaterializedView)
            {
                var script = context.Engine.RepositoryProvider.LookupDefinition(lookup.Identifier, lookup.Type) ??
                             throw new QsiException(QsiError.UnableResolveDefinition, lookup.Identifier);

                var viewNode = context.Engine.TreeParser.Parse(script);

                using var viewCompileContext = new TableCompileContext(context);

                if (lookup.Identifier.Level > 1)
                {
                    viewCompileContext.PushIdentifierScope(lookup.Identifier.SubIdentifier(..^ 1));
                }

                QsiTableStructure viewStructure;

                switch (viewNode)
                {
                /* TODO: Remove old view node
                 * [V] Cql
                 * [-] JSql (Deprecated)
                 * [V] MySql
                 * [V] PhoenixSql
                 * [V] SqlServer
                 */
                case IQsiTableNode viewTableNode:
                {
                    var viewTableStructure = await BuildTableStructure(viewCompileContext, viewTableNode);

                    viewTableStructure.Identifier = ResolveQualifiedIdentifier(context, viewTableStructure.Identifier);
                    viewStructure = viewTableStructure;
                    break;
                }

                case IQsiDefinitionNode definitionNode:
                {
                    viewStructure = await BuildDefinitionStructure(viewCompileContext, definitionNode);

                    break;
                }

                default:
                    throw TreeHelper.NotSupportedTree(viewNode);
                }

                if (viewStructure.Columns.Count != lookup.Columns.Count)
                {
                    throw new QsiException(QsiError.DifferentColumnsCount, "View definition");
                }

                lookup.References.Add(viewStructure);

                for (int i = 0; i < viewStructure.Columns.Count; i++)
                {
                    lookup.Columns[i].References.Add(viewStructure.Columns[i]);
                }
            }

            return(lookup);
        }
Example #25
0
        protected virtual ValueTask <QsiTableStructure> BuildInlineDerivedTableStructure(TableCompileContext context, IQsiInlineDerivedTableNode table)
        {
            context.ThrowIfCancellationRequested();

            var alias = table.Alias?.Name;

            if (alias == null &&
                table.Parent is IQsiDerivedColumnNode &&
                !context.Options.AllowNoAliasInDerivedTable)
            {
                throw new QsiException(QsiError.NoAlias);
            }

            var declaredTable = new QsiTableStructure
            {
                Type       = QsiTableType.Inline,
                Identifier = alias == null ? null : new QsiQualifiedIdentifier(alias)
            };

            int?columnCount = null;

            switch (table.Columns)
            {
            case null:
            case var cd when cd.All(c => c is IQsiAllColumnNode {
                    Path: null
                }) :
                // Skip
                break;