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); } }
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)); }
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; } }
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); }
protected virtual QsiIdentifier ResolveDerivedColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiDerivedColumnNode column) { return(column.Alias?.Name ?? column.InferredName); }
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); }
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); }
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 })