protected virtual List <PersistRequest> BuildInsertRequest(PersistRequestBuilderContext context) { var result = new List <PersistRequest>(); foreach (var index in context.AffectedIndexes) { var table = context.Mapping[index.ReflectedType]; var tableRef = SqlDml.TableRef(table); var query = SqlDml.Insert(tableRef); var bindings = new List <PersistParameterBinding>(); foreach (var column in index.Columns) { int fieldIndex = GetFieldIndex(context.Type, column); if (fieldIndex >= 0) { var binding = GetBinding(context, column, table, fieldIndex); query.Values[tableRef[column.Name]] = binding.ParameterReference; bindings.Add(binding); } } result.Add(CreatePersistRequest(query, bindings, context.NodeConfiguration)); } return(result); }
private SqlExpression BuildVersionFilter(PersistRequestBuilderContext context, SqlTableRef filteredTable, List <PersistParameterBinding> currentBindings) { SqlExpression result = null; foreach (var column in context.Type.GetVersionColumns()) { var fieldIndex = GetFieldIndex(context.Type, column); if (!context.Task.AvailableFields[fieldIndex]) { continue; } PersistParameterBinding binding; if (!context.VersionParameterBindings.TryGetValue(column, out binding)) { var typeMapping = driver.GetTypeMapping(column); binding = new PersistParameterBinding(typeMapping, fieldIndex, ParameterTransmissionType.Regular, PersistParameterBindingType.VersionFilter); context.VersionParameterBindings.Add(column, binding); } var filteredColumn = filteredTable[column.Name]; if (filteredColumn.IsNullReference()) { continue; } var filterValue = binding.ParameterReference; // Handle decimal precision issue if (Type.GetTypeCode(column.ValueType) == TypeCode.Decimal) { filterValue = SqlDml.Cast(filterValue, driver.MapValueType(column)); } result &= SqlDml.Variant(binding, filteredColumn == filterValue, SqlDml.IsNull(filteredColumn)); currentBindings.Add(binding); } return(result); }
private PersistParameterBinding GetBinding(PersistRequestBuilderContext context, ColumnInfo column, Table table, int fieldIndex) { if (!context.ParameterBindings.TryGetValue(column, out var binding)) { var typeMapping = driver.GetTypeMapping(column); var bindingType = GetTransmissionType(table.TableColumns[column.Name]); binding = new PersistParameterBinding(typeMapping, fieldIndex, bindingType); context.ParameterBindings.Add(column, binding); } return(binding); }
internal ICollection <PersistRequest> Build(StorageNode node, PersistRequestBuilderTask task) { var context = new PersistRequestBuilderContext(task, node.Mapping, node.Configuration); List <PersistRequest> result; switch (task.Kind) { case PersistRequestKind.Insert: result = BuildInsertRequest(context); break; case PersistRequestKind.Remove: result = BuildRemoveRequest(context); break; case PersistRequestKind.Update: result = BuildUpdateRequest(context); break; default: throw new ArgumentOutOfRangeException("task.Kind"); } // Merging requests for servers which support batching // unless version validation is requested. if (providerInfo.Supports(ProviderFeatures.Batches) && result.Count > 1 && !task.ValidateVersion) { var batch = SqlDml.Batch(); var bindings = new HashSet <PersistParameterBinding>(); foreach (var request in result) { batch.Add(request.Statement); bindings.UnionWith(request.ParameterBindings); } var batchRequest = CreatePersistRequest(batch, bindings, node.Configuration); batchRequest.Prepare(); return(new List <PersistRequest> { batchRequest }.AsReadOnly()); } foreach (var item in result) { item.Prepare(); } return(result.AsReadOnly()); }
protected virtual List <PersistRequest> BuildUpdateRequest(PersistRequestBuilderContext context) { var result = new List <PersistRequest>(); foreach (var index in context.AffectedIndexes) { var table = context.Mapping[index.ReflectedType]; var tableRef = SqlDml.TableRef(table); var query = SqlDml.Update(tableRef); var bindings = new List <PersistParameterBinding>(); foreach (var column in index.Columns) { int fieldIndex = GetFieldIndex(context.Type, column); if (fieldIndex >= 0 && context.Task.ChangedFields[fieldIndex]) { var binding = GetBinding(context, column, table, fieldIndex); query.Values[tableRef[column.Name]] = binding.ParameterReference; bindings.Add(binding); } } // There is nothing to update in this table, skip update // unless this table has version columns // in this case we issue a dummy update that changes // only version column(s). var hasColumnUpdates = query.Values.Count > 0; var requiresVersionValidation = context.Task.ValidateVersion; var isValidRequest = hasColumnUpdates || requiresVersionValidation && AddFakeVersionColumnUpdate(context, query, tableRef); if (!isValidRequest) { continue; } query.Where = BuildKeyFilter(context, tableRef, bindings); if (requiresVersionValidation) { query.Where &= BuildVersionFilter(context, tableRef, bindings); } result.Add(CreatePersistRequest(query, bindings, context.NodeConfiguration)); } return(result); }
private SqlExpression BuildKeyFilter(PersistRequestBuilderContext context, SqlTableRef filteredTable, List <PersistParameterBinding> currentBindings) { SqlExpression result = null; foreach (var column in context.PrimaryIndex.KeyColumns.Keys) { if (!context.ParameterBindings.TryGetValue(column, out var binding)) { var typeMapping = driver.GetTypeMapping(column); var fieldIndex = GetFieldIndex(context.Type, column); binding = new PersistParameterBinding(typeMapping, fieldIndex); context.ParameterBindings.Add(column, binding); } result &= filteredTable[column.Name] == binding.ParameterReference; currentBindings.Add(binding); } return(result); }
private bool AddFakeVersionColumnUpdate(PersistRequestBuilderContext context, SqlUpdate update, SqlTableRef filteredTable) { foreach (var column in context.Type.GetVersionColumns()) { var columnExpression = filteredTable[column.Name]; if (columnExpression.IsNullReference()) { continue; } int index = GetFieldIndex(context.Type, column); if (index < 0 || !context.Task.AvailableFields[index]) { continue; } update.Values.Add(columnExpression, columnExpression); return(true); } return(false); }
protected virtual List <PersistRequest> BuildRemoveRequest(PersistRequestBuilderContext context) { var result = new List <PersistRequest>(); for (int i = context.AffectedIndexes.Count - 1; i >= 0; i--) { var index = context.AffectedIndexes[i]; var tableRef = SqlDml.TableRef(context.Mapping[index.ReflectedType]); var query = SqlDml.Delete(tableRef); var bindings = new List <PersistParameterBinding>(); query.Where = BuildKeyFilter(context, tableRef, bindings); if (context.Task.ValidateVersion) { query.Where &= BuildVersionFilter(context, tableRef, bindings); } result.Add(CreatePersistRequest(query, bindings, context.NodeConfiguration)); } return(result); }