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)); }
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); }
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()); }
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 })
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)); }
public override ValueTask <QsiTableStructure> BuildTableStructure(TableCompileContext context, IQsiTableNode table) { if (table is ImpalaValuesTableNode valuesTableNode) { return(BuildImpalaValuesTableStructure(context, valuesTableNode)); } return(base.BuildTableStructure(context, table)); }
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)); }
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)); }
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; } }
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)); }
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 })
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); }
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); }
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 Task <QsiTableStructure> BuildTableFunctionStructure(TableCompileContext context, IQsiTableFunctionNode table) { throw TreeHelper.NotSupportedFeature("Table Function"); }
protected virtual QsiIdentifier ResolveCompoundColumnName(TableCompileContext context, IQsiDerivedTableNode table, IQsiColumnNode column, QsiTableColumn refColumn) { return(refColumn.Name); }
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)); }
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 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); }
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;