public bool VisitExprDerivedTableValues(ExprDerivedTableValues expr, TCtx arg) { var res = this.Visit(expr, "DerivedTableValues", arg, out var argOut) && this.Accept("Values", expr.Values, argOut) && this.Accept("Alias", expr.Alias, argOut) && this.Accept("Columns", expr.Columns, argOut); this._visitor.EndVisitExpr(expr, arg); return(res); }
protected bool VisitExprDerivedTableValuesCommon(ExprDerivedTableValues derivedTableValues, IExpr?parent) { this.AcceptPar('(', derivedTableValues.Values, ')', derivedTableValues); derivedTableValues.Alias.Accept(this, derivedTableValues); derivedTableValues.Columns.AssertNotEmpty("List of columns in a derived table with values literals cannot be empty"); this.AcceptListComaSeparatedPar('(', derivedTableValues.Columns, ')', derivedTableValues); return(true); }
public static ExprList FromDerivedTableValuesInsert(ExprDerivedTableValues derivedTableValues, IReadOnlyList <ExprColumnName>?keys, out TempTableBase tempTable, Alias alias = default, string?name = null) { tempTable = FromDerivedTableValues(derivedTableValues, keys, alias, name); var insertData = derivedTableValues.Values.Items.SelectToReadOnlyList(r => new ExprInsertValueRow(r.Items)); var insert = SqQueryBuilder.InsertInto(tempTable, derivedTableValues.Columns).Values(new ExprInsertValues(insertData)); return(new ExprList(new IExprExec[] { new ExprStatement(tempTable.Script.Create()), insert })); }
public static ExprDerivedTableValues WithColumns(this ExprDerivedTableValues original, IReadOnlyList <ExprColumnName> newColumns) => new ExprDerivedTableValues(values: original.Values, alias: original.Alias, columns: newColumns);
public static ExprDerivedTableValues WithAlias(this ExprDerivedTableValues original, ExprTableAlias newAlias) => new ExprDerivedTableValues(values: original.Values, alias: newAlias, columns: original.Columns);
public static ExprDerivedTableValues WithValues(this ExprDerivedTableValues original, ExprTableValueConstructor newValues) => new ExprDerivedTableValues(values: newValues, alias: original.Alias, columns: original.Columns);
public ExprInsert Done() { var checkExistence = this._checkExistenceByColumns != null && this._checkExistenceByColumns.Count > 0; var useDerivedTable = this._targetInsertSelectMapping != null || checkExistence; var mapping = this._dataMapping.AssertFatalNotNull(nameof(this._dataMapping)); int?capacity = this._data.TryToCheckLength(out var c) ? c : (int?)null; if (capacity != null && capacity.Value < 1) { throw new SqExpressException("Input data should not be empty"); } List <ExprValueRow>? recordsS = null; List <ExprInsertValueRow>?recordsI = null; if (useDerivedTable) { recordsS = capacity.HasValue ? new List <ExprValueRow>(capacity.Value) : new List <ExprValueRow>(); } else { recordsI = capacity.HasValue ? new List <ExprInsertValueRow>(capacity.Value) : new List <ExprInsertValueRow>(); } DataMapSetter <TTable, TItem>? dataMapSetter = null; IReadOnlyList <ExprColumnName>?columns = null; foreach (var item in this._data) { dataMapSetter ??= new DataMapSetter <TTable, TItem>(this._target, item); dataMapSetter.NextItem(item, columns?.Count); mapping(dataMapSetter); columns ??= dataMapSetter.Columns; dataMapSetter.EnsureRecordLength(); recordsS?.Add(new ExprValueRow(dataMapSetter.Record.AssertFatalNotNull(nameof(dataMapSetter.Record)))); recordsI?.Add(new ExprInsertValueRow(dataMapSetter.Record.AssertFatalNotNull(nameof(dataMapSetter.Record)))); } if ((recordsS?.Count ?? 0 + recordsI?.Count ?? 0) < 1 || columns == null) { //In case of empty IEnumerable throw new SqExpressException("Input data should not be empty"); } IExprInsertSource insertSource; if (recordsI != null) { insertSource = new ExprInsertValues(recordsI); } else if (recordsS != null && useDerivedTable) { var valuesConstructor = new ExprTableValueConstructor(recordsS); var values = new ExprDerivedTableValues( valuesConstructor, new ExprTableAlias(Alias.Auto.BuildAliasExpression().AssertNotNull("Alias cannot be null")), columns); IReadOnlyList <ColumnValueInsertSelectMap>?additionalMaps = null; if (this._targetInsertSelectMapping != null) { var targetUpdateSetter = new TargetInsertSelectSetter <TTable>(this._target); this._targetInsertSelectMapping.Invoke(targetUpdateSetter); additionalMaps = targetUpdateSetter.Maps; if (additionalMaps.Count < 1) { throw new SqExpressException("Additional insertion cannot be null"); } } var selectValues = new List <IExprSelecting>(columns.Count + (additionalMaps?.Count ?? 0)); foreach (var exprColumnName in values.Columns) { selectValues.Add(exprColumnName); } if (additionalMaps != null) { foreach (var m in additionalMaps) { selectValues.Add(m.Value); } } IExprQuery query; var queryBuilder = SqQueryBuilder.Select(selectValues).From(values); if (checkExistence && this._checkExistenceByColumns != null) { var tbl = this._target.WithAlias(new ExprTableAlias(Alias.Auto.BuildAliasExpression() !)); var existsFilter = !SqQueryBuilder.Exists(SqQueryBuilder .SelectOne() .From(tbl) .Where(this._checkExistenceByColumns .Select(column => column.WithSource(tbl.Alias) == column.WithSource(values.Alias)) .JoinAsAnd())); query = queryBuilder.Where(existsFilter).Done(); } else { query = queryBuilder.Done(); } insertSource = new ExprInsertQuery(query); if (additionalMaps != null) { var extraInsertCols = additionalMaps.SelectToReadOnlyList(m => m.Column); columns = Helpers.Combine(columns, extraInsertCols); } } else { //Actually C# should have detected that this brunch cannot be invoked throw new SqExpressException("Fatal logic error!"); } return(new ExprInsert(this._target.FullName, columns, insertSource)); }
public override bool VisitExprDerivedTableValues(ExprDerivedTableValues derivedTableValues, IExpr?parent) { return(this.VisitExprDerivedTableValuesCommon(derivedTableValues, parent)); }
public static TempTableData FromDerivedTableValues(ExprDerivedTableValues derivedTableValues, IReadOnlyList <ExprColumnName>?keys, Alias alias = default, string?name = null) { var result = new TempTableData(string.IsNullOrEmpty(name) || name == null ? GenerateName() : name, alias); derivedTableValues.Columns.AssertNotEmpty("Columns list cannot be empty"); derivedTableValues.Values.Items.AssertNotEmpty("Rows list cannot be empty"); TableColumn?[] tableColumns = new TableColumn?[derivedTableValues.Columns.Count]; for (var rowIndex = 0; rowIndex < derivedTableValues.Values.Items.Count; rowIndex++) { var lastRow = rowIndex + 1 == derivedTableValues.Values.Items.Count; var row = derivedTableValues.Values.Items[rowIndex]; if (row.Items.Count != derivedTableValues.Columns.Count) { throw new SqExpressException("Number of values in a row does not match number of columns"); } for (var valueIndex = 0; valueIndex < row.Items.Count; valueIndex++) { var value = row.Items[valueIndex]; var previousColumn = tableColumns[valueIndex]; var currentColumnName = derivedTableValues.Columns[valueIndex]; var res = value.Accept(ExprValueTypeAnalyzer <TableColumn?, TempTableBuilderCtx> .Instance, new ExprValueTypeAnalyzerCtx <TableColumn?, TempTableBuilderCtx>( new TempTableBuilderCtx( currentColumnName, previousColumn, CheckIsPk(currentColumnName)), result)); tableColumns[valueIndex] = res; if (lastRow) { if (ReferenceEquals(res, null)) { throw new SqExpressException($"Could not evaluate column type at {valueIndex}"); } } } } result.AddColumns(tableColumns !); return(result); bool CheckIsPk(ExprColumnName columnName) { if (keys == null || keys.Count < 1) { return(false); } for (var index = 0; index < keys.Count; index++) { var key = keys[index]; if (key.LowerInvariantName == columnName.LowerInvariantName) { return(true); } } return(false); } }
public abstract bool VisitExprDerivedTableValues(ExprDerivedTableValues derivedTableValues, IExpr?parent);
public ExprMerge Done() { var records = this._data.TryToCheckLength(out var capacity) ? capacity > 0 ? new List <ExprValueRow>(capacity) : null : new List <ExprValueRow>(); if (records == null) { throw new SqExpressException("Input data should not be empty"); } var dataMapKeys = this._dataMapKeys.AssertNotNull("DataMapKeys should be initialized"); var dataMap = this._dataMap.AssertNotNull("DataMap should be initialized"); DataMapSetter <TTable, TItem>? setter = null; List <ExprColumnName>? keys = null; IReadOnlyList <ExprColumnName>?allTableColumns = null; IReadOnlyList <ExprColumnName>?totalColumns = null; foreach (var item in this._data) { setter ??= new DataMapSetter <TTable, TItem>(this._table, item); setter.NextItem(item, totalColumns?.Count); dataMapKeys(setter); keys ??= new List <ExprColumnName>(setter.Columns); keys.AssertNotEmpty("There should be at least one key"); dataMap(setter); totalColumns = allTableColumns ??= new List <ExprColumnName>(setter.Columns); if (this._extraDataMap != null) { this._extraDataMap.Invoke(setter); if (ReferenceEquals(totalColumns, allTableColumns)) { totalColumns = new List <ExprColumnName>(setter.Columns); } } setter.EnsureRecordLength(); records.Add(new ExprValueRow(setter.Record.AssertFatalNotNull(nameof(setter.Record)))); } if (records.Count < 1) { throw new SqExpressException("Input data should not be empty"); } keys = keys.AssertFatalNotNull(nameof(keys)); allTableColumns = allTableColumns.AssertFatalNotNull(nameof(allTableColumns)); totalColumns = totalColumns.AssertFatalNotNull(nameof(allTableColumns)); var exprValuesTable = new ExprDerivedTableValues(new ExprTableValueConstructor(records), this._sourceTableAlias, totalColumns); if (keys.Count >= allTableColumns.Count) { throw new SqExpressException("The number of keys exceeds the number of columns"); } return(new ExprMerge( this._table, exprValuesTable, this.GetOn(keys), this.BuildWhenMatched(keys, allTableColumns), this.BuildWhenNotMatchedByTarget(keys, allTableColumns), this.BuildWhenNotMatchedBySource())); }
public void Deconstruct(out List <ExprColumnName> keys, out IReadOnlyList <ExprColumnName> allTableColumns, out ExprDerivedTableValues exprValuesTable) { keys = this.Keys; allTableColumns = this.AllTableColumns; exprValuesTable = this.ExprValuesTable; }
public UpdateDataAnalysis(List <ExprColumnName> keys, IReadOnlyList <ExprColumnName> allTableColumns, ExprDerivedTableValues exprValuesTable) { this.Keys = keys; this.AllTableColumns = allTableColumns; this.ExprValuesTable = exprValuesTable; }
public static UpdateDataAnalysis AnalyzeUpdateData <TTable, TItem> ( IEnumerable <TItem> data, TTable targetTable, DataMapping <TTable, TItem> dataMapKeys, DataMapping <TTable, TItem>?dataMap, IndexDataMapping?extraDataMap, ExprTableAlias sourceTableAlias ) { var records = data.TryToCheckLength(out var capacity) ? capacity > 0 ? new List <ExprValueRow>(capacity) : null : new List <ExprValueRow>(); if (records == null) { throw new SqExpressException("Input data should not be empty"); } DataMapSetter <TTable, TItem>? setter = null; List <ExprColumnName>? keys = null; IReadOnlyList <ExprColumnName>?allTableColumns = null; IReadOnlyList <ExprColumnName>?totalColumns = null; foreach (var item in data) { setter ??= new DataMapSetter <TTable, TItem>(targetTable, item); setter.NextItem(item, totalColumns?.Count); dataMapKeys(setter); keys ??= new List <ExprColumnName>(setter.Columns); keys.AssertNotEmpty("There should be at least one key"); dataMap?.Invoke(setter); totalColumns = allTableColumns ??= new List <ExprColumnName>(setter.Columns); if (extraDataMap != null) { extraDataMap.Invoke(setter); if (ReferenceEquals(totalColumns, allTableColumns)) { totalColumns = new List <ExprColumnName>(setter.Columns); } } setter.EnsureRecordLength(); records.Add(new ExprValueRow(setter.Record.AssertFatalNotNull(nameof(setter.Record)))); } if (records.Count < 1) { throw new SqExpressException("Input data should not be empty"); } keys = keys.AssertFatalNotNull(nameof(keys)); allTableColumns = allTableColumns.AssertFatalNotNull(nameof(allTableColumns)); totalColumns = totalColumns.AssertFatalNotNull(nameof(allTableColumns)); var exprValuesTable = new ExprDerivedTableValues(new ExprTableValueConstructor(records), sourceTableAlias, totalColumns); if (keys.Count > allTableColumns.Count) { throw new SqExpressException("The number of keys exceeds the number of columns"); } return(new UpdateDataAnalysis(keys, allTableColumns, exprValuesTable)); }