public override int CommandCount(SqlStatement statement) { switch (statement) { case SqlTruncateTableStatement truncate: return(truncate.ResetIdentity && truncate.Table !.IdentityFields.Count > 0 ? 2 : 1); case SqlCreateTableStatement createTable: _identityField = createTable.Table !.IdentityFields.FirstOrDefault(); if (_identityField != null) { return(3); } break; } return(base.CommandCount(statement)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SelectQuery.Select.IsDistinct; if (isSubQuery) { sequence = new SubQueryContext(sequence); } if (!(sequence.Statement is SqlInsertStatement insertStatement)) { insertStatement = new SqlInsertStatement(sequence.SelectQuery); sequence.Statement = insertStatement; } var insertType = InsertContext.InsertType.Insert; switch (methodCall.Method.Name) { case "Insert": insertType = InsertContext.InsertType.Insert; break; case "InsertWithIdentity": insertType = InsertContext.InsertType.InsertWithIdentity; break; case "InsertWithOutput": insertType = InsertContext.InsertType.InsertOutput; break; case "InsertWithOutputInto": insertType = InsertContext.InsertType.InsertOutputInto; break; } var indexedParameters = methodCall.Method.GetParameters().Select((p, i) => Tuple.Create(p, i)).ToDictionary(t => t.Item1.Name, t => t.Item2); Expression GetArgumentByName(string name) { return(methodCall.Arguments[indexedParameters[name]]); } LambdaExpression GetOutputExpression(Type outputType) { if (!indexedParameters.TryGetValue("outputExpression", out var index)) { var param = Expression.Parameter(outputType); return(Expression.Lambda(param, param)); } return((LambdaExpression)methodCall.Arguments[index].Unwrap()); } IBuildContext? outputContext = null; LambdaExpression?outputExpression = null; if (methodCall.Arguments.Count > 0) { var argument = methodCall.Arguments[0]; if (typeof(IValueInsertable <>).IsSameOrParentOf(argument.Type) || typeof(ISelectInsertable <,>).IsSameOrParentOf(argument.Type)) { // static int Insert<T> (this IValueInsertable<T> source) // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source) sequence.SelectQuery.Select.Columns.Clear(); if (insertStatement.Insert.Items.Count == 0) { insertStatement.Insert.Items.AddRange(insertStatement.Insert.DefaultItems); } AddInsertColumns(sequence.SelectQuery, insertStatement.Insert.Items); } else if (methodCall.Arguments.Count > 1 && typeof(IQueryable <>).IsSameOrParentOf(argument.Type) && typeof(ITable <>).IsSameOrParentOf(methodCall.Arguments[1].Type)) { // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter) var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery())); var setter = (LambdaExpression)GetArgumentByName("setter").Unwrap(); UpdateBuilder.BuildSetter( builder, buildInfo, setter, into, insertStatement.Insert.Items, sequence); sequence.SelectQuery.Select.Columns.Clear(); if (insertStatement.Insert.Items.Count == 0) { insertStatement.Insert.Items.AddRange(insertStatement.Insert.DefaultItems); } AddInsertColumns(sequence.SelectQuery, insertStatement.Insert.Items); insertStatement.Insert.Into = ((TableBuilder.TableContext)into).SqlTable; } else if (typeof(ITable <>).IsSameOrParentOf(argument.Type)) { // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter) // static TTarget InsertWithOutput<TTarget>(this ITable<TTarget> target, Expression<Func<TTarget>> setter) // static TTarget InsertWithOutput<TTarget>(this ITable<TTarget> target, Expression<Func<TTarget>> setter, Expression<Func<TTarget,TOutput>> outputExpression) var argIndex = 1; var arg = methodCall.Arguments[argIndex].Unwrap(); LambdaExpression?setter = null; switch (arg) { case LambdaExpression lambda: { setter = lambda; UpdateBuilder.BuildSetter( builder, buildInfo, setter, sequence, insertStatement.Insert.Items, sequence); break; } default: { var objType = arg.Type; var ed = builder.MappingSchema.GetEntityDescriptor(objType); var into = sequence; var ctx = new TableBuilder.TableContext(builder, buildInfo, objType); var table = new SqlTable(objType); foreach (var c in ed.Columns.Where(c => !c.SkipOnInsert)) { var field = table[c.ColumnName]; if (field == null) { continue; } var pe = Expression.MakeMemberAccess(arg, c.MemberInfo); var column = into.ConvertToSql(pe, 1, ConvertFlags.Field); var parameter = builder.BuildParameterFromArgumentProperty(methodCall, argIndex, field.ColumnDescriptor); insertStatement.Insert.Items.Add(new SqlSetExpression(column[0].Sql, parameter.SqlParameter)); } var insertedTable = SqlTable.Inserted(methodCall.Method.GetGenericArguments()[0]); break; } } insertStatement.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SelectQuery.From.Tables.Clear(); } if (insertType == InsertContext.InsertType.InsertOutput || insertType == InsertContext.InsertType.InsertOutputInto) { outputExpression = GetOutputExpression(methodCall.Method.GetGenericArguments().Last()); insertStatement.Output = new SqlOutputClause(); var insertedTable = SqlTable.Inserted(outputExpression.Parameters[0].Type); outputContext = new TableBuilder.TableContext(builder, new SelectQuery(), insertedTable); insertStatement.Output.InsertedTable = insertedTable; if (insertType == InsertContext.InsertType.InsertOutputInto) { var outputTable = GetArgumentByName("outputTable"); var destination = builder.BuildSequence(new BuildInfo(buildInfo, outputTable, new SelectQuery())); UpdateBuilder.BuildSetter( builder, buildInfo, outputExpression, destination, insertStatement.Output.OutputItems, outputContext); insertStatement.Output.OutputTable = ((TableBuilder.TableContext)destination).SqlTable; } } } var insert = insertStatement.Insert; var q = insert.Into !.IdentityFields .Except(insert.Items.Select(e => e.Column).OfType <SqlField>()); foreach (var field in q) { var expr = builder.DataContext.CreateSqlProvider().GetIdentityExpression(insert.Into); if (expr != null) { insert.Items.Insert(0, new SqlSetExpression(field, expr)); if (methodCall.Arguments.Count == 3) { sequence.SelectQuery.Select.Columns.Insert(0, new SqlColumn(sequence.SelectQuery, insert.Items[0].Expression !)); } } } insertStatement.Insert.WithIdentity = insertType == InsertContext.InsertType.InsertWithIdentity; sequence.Statement = insertStatement; if (insertType == InsertContext.InsertType.InsertOutput) { return(new InsertWithOutputContext(buildInfo.Parent, sequence, outputContext !, outputExpression !)); } return(new InsertContext(buildInfo.Parent, sequence, insertType, outputExpression)); }
protected override void BuildDropTableStatement(SqlDropTableStatement dropTable) { var identityField = dropTable.Table !.IdentityFields.FirstOrDefault(); if (identityField == null && dropTable.IfExists == false) { base.BuildDropTableStatement(dropTable); return; } // implementation use following approach: http://www.firebirdfaq.org/faq69/ StringBuilder .AppendLine("EXECUTE BLOCK AS BEGIN"); Indent++; if (identityField != null) { BuildDropWithSchemaCheck("TRIGGER", "rdb$triggers", "rdb$trigger_name", "TIDENTITY_" + dropTable.Table.PhysicalName); BuildDropWithSchemaCheck("GENERATOR", "rdb$generators", "rdb$generator_name", "GIDENTITY_" + dropTable.Table.PhysicalName); } BuildDropWithSchemaCheck("TABLE", "rdb$relations", "rdb$relation_name", dropTable.Table.PhysicalName !); Indent--; StringBuilder .AppendLine("END"); void BuildDropWithSchemaCheck(string objectName, string schemaTable, string nameColumn, string identifier) { if (dropTable.IfExists) { AppendIndent().AppendFormat("IF (EXISTS(SELECT 1 FROM {0} WHERE {1} = ", schemaTable, nameColumn); var identifierValue = identifier; // if identifier is not quoted, it must be converted to upper case to match record in rdb$relation_name if (FirebirdConfiguration.IdentifierQuoteMode == FirebirdIdentifierQuoteMode.None || FirebirdConfiguration.IdentifierQuoteMode == FirebirdIdentifierQuoteMode.Auto && IsValidIdentifier(identifierValue)) { identifierValue = identifierValue.ToUpper(); } BuildValue(null, identifierValue); StringBuilder .AppendLine(")) THEN"); Indent++; } AppendIndent().Append("EXECUTE STATEMENT "); var dropCommand = new StringBuilder(); dropCommand .Append("DROP ") .Append(objectName) .Append(" "); Convert(dropCommand, identifier, ConvertType.NameToQueryTable); BuildValue(null, dropCommand.ToString()); StringBuilder.AppendLine(";"); if (dropTable.IfExists) { Indent--; } } }