protected override void DeparseDerivedTableNode(ScriptWriter writer, IQsiDerivedTableNode node, QsiScript script)
        {
            base.DeparseDerivedTableNode(writer, node, script);

            if (node is not MySqlDerivedTableNode mysqlNode)
            {
                return;
            }

            if (!mysqlNode.ProcedureAnalyse.IsEmpty)
            {
                var procedureAnalyse = mysqlNode.ProcedureAnalyse.Value;

                writer.WriteSpace();
                writer.Write("PROCEDURE ANALYSE (");
                writer.Write(procedureAnalyse.MaxElements);

                if (procedureAnalyse.MaxMemory.HasValue)
                {
                    writer.Write(", ");
                    writer.Write(procedureAnalyse.MaxMemory.Value);
                }

                writer.Write(')');
            }

            if (mysqlNode.Lockings?.Count > 0)
            {
                writer.WriteSpace();
                writer.WriteJoin(" ", mysqlNode.Lockings, DeparseLockingNode);
            }
        }
Beispiel #2
0
 protected bool IsAliasedDerivedTableNode(IQsiDerivedTableNode node)
 {
     return
         (node.Source is IQsiDerivedTableNode &&
          node.Alias is not null &&
          node.Directives is null &&
          node.Where is null &&
          node.Grouping is null &&
          node.Order is null &&
          node.Limit is null &&
          node.Columns is not null &&
          IsWildcard(node.Columns));
 }
 protected bool IsAliasedTableAccessNode(IQsiDerivedTableNode node)
 {
     return
         (node.Source is IQsiTableAccessNode &&
          node.Alias != null &&
          node.Directives == null &&
          node.Where == null &&
          node.Grouping == null &&
          node.Order == null &&
          node.Limit == null &&
          node.Columns != null &&
          IsWildcard(node.Columns));
 }
Beispiel #4
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;
                }
            }
Beispiel #5
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);
        }
Beispiel #6
0
 protected virtual QsiIdentifier ResolveDerivedColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiDerivedColumnNode column)
 {
     return(column.Alias?.Name ?? column.InferredName);
 }
Beispiel #7
0
 protected virtual QsiIdentifier ResolveCompoundColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiColumnNode column, QsiTableColumn refColumn)
 {
     return(refColumn.Name);
 }
        protected override ValueTask <QsiTableStructure> BuildDerivedTableStructure(TableCompileContext context, IQsiDerivedTableNode table)
        {
            if (table.Source == null)
            {
                throw new QsiException(QsiError.NoFromClause);
            }

            return(base.BuildDerivedTableStructure(context, table));
        }
        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);
        }
Beispiel #10
0
        protected override void DeparseDerivedTableNode(ScriptWriter writer, IQsiDerivedTableNode node, QsiScript script)
        {
            if (node is CqlDerivedTableNode cqlNode)
            {
                writer.Write("SELECT ");

                if (cqlNode.IsJson)
                {
                    writer.Write("JSON ");
                }

                if (cqlNode.IsDistinct)
                {
                    writer.Write("DISTINCT ");
                }

                if (node.Columns != null)
                {
                    DeparseTreeNode(writer, node.Columns, script);
                }

                writer.WriteSpace();
                writer.Write("FROM ");

                DeparseTreeNode(writer, node.Source, script);

                if (node.Where != null)
                {
                    writer.WriteSpace();
                    DeparseTreeNode(writer, node.Where, script);
                }

                if (node.Grouping != null)
                {
                    writer.WriteSpace();
                    DeparseTreeNode(writer, node.Grouping, script);
                }

                if (node.Order != null)
                {
                    writer.WriteSpace();
                    DeparseTreeNode(writer, node.Order, script);
                }

                if (!cqlNode.PerPartitionLimit.IsEmpty)
                {
                    writer.WriteSpace();
                    writer.Write("PER PARTITION LIMIT ");
                    DeparseTreeNode(writer, cqlNode.PerPartitionLimit.Value, script);
                }

                if (node.Limit != null)
                {
                    writer.WriteSpace();
                    DeparseTreeNode(writer, node.Limit, script);
                }

                if (cqlNode.AllowFiltering)
                {
                    writer.WriteSpace();
                    writer.Write("ALLOW FILTERING");
                }

                return;
            }

            base.DeparseDerivedTableNode(writer, node, script);
        }
Beispiel #11
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
                })