Permalink
Browse files

Allow insertFields to change field order within INSERT Statements

  • Loading branch information...
mythz committed Nov 28, 2018
1 parent 18ab1f2 commit 066010020f0b6225c44cbd1f96e5a61ea488f493
@@ -117,17 +117,15 @@ public override string ToSelectStatement(Type tableType, string sqlFilter, param

public override string ToInsertRowStatement(IDbCommand cmd, object objWithProperties, ICollection<string> insertFields = null)
{
if (insertFields == null)
insertFields = new List<string>();

var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var sbReturningColumns = StringBuilderCacheAlt.Allocate();

var tableType = objWithProperties.GetType();
var modelDef = GetModel(tableType);

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (fieldDef.ReturnOnInsert || (fieldDef.IsPrimaryKey && fieldDef.AutoIncrement && HasInsertReturnValues(modelDef)))
{
@@ -138,8 +136,6 @@ public override string ToInsertRowStatement(IDbCommand cmd, object objWithProper

if (fieldDef.IsComputed)
continue;
if (insertFields.Count > 0 && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;

if ((fieldDef.AutoIncrement || !string.IsNullOrEmpty(fieldDef.Sequence)
|| fieldDef.Name == OrmLiteConfig.IdField)
@@ -201,7 +197,8 @@ public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICol
cmd.Parameters.Clear();
cmd.CommandTimeout = OrmLiteConfig.CommandTimeout;

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (fieldDef.ReturnOnInsert || (fieldDef.IsPrimaryKey && fieldDef.AutoIncrement && HasInsertReturnValues(modelDef)))
{
@@ -213,10 +210,6 @@ public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICol
if (fieldDef.ShouldSkipInsert() && !fieldDef.AutoIncrement && string.IsNullOrEmpty(fieldDef.Sequence))
continue;

//insertFields contains Property "Name" of fields to insert ( that's how expressions work )
if (insertFields != null && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;

if (sbColumnNames.Length > 0)
sbColumnNames.Append(",");
if (sbColumnValues.Length > 0)
@@ -279,22 +279,18 @@ public override string ToSelectStatement(Type tableType, string sqlFilter, param

public override void PrepareParameterizedInsertStatement<T>(IDbCommand dbCommand, ICollection<string> insertFields = null)
{
if (insertFields == null)
insertFields = new List<string>();

var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var modelDef = GetModel(typeof(T));

dbCommand.Parameters.Clear();
dbCommand.CommandTimeout = OrmLiteConfig.CommandTimeout;
foreach (var fieldDef in modelDef.FieldDefinitions)

var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (fieldDef.IsComputed || fieldDef.IsRowVersion) continue;

//insertFields contains Property "Name" of fields to insert (that's how expressions work)
if (insertFields.Count > 0 && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase)) continue;

if (sbColumnNames.Length > 0) sbColumnNames.Append(",");
if (sbColumnValues.Length > 0) sbColumnValues.Append(",");

@@ -368,21 +364,17 @@ public override void SetParameterValues<T>(IDbCommand dbCmd, object obj)
//TODO: Change to parameterized query to match all other ToInsertRowStatement() impls
public override string ToInsertRowStatement(IDbCommand dbCommand, object objWithProperties, ICollection<string> insertFields = null)
{
if (insertFields == null)
insertFields = new List<string>();

var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();

var tableType = objWithProperties.GetType();
var modelDef = GetModel(tableType);

foreach (var fieldDef in modelDef.FieldDefinitions)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (fieldDef.IsComputed)
continue;
if (insertFields.Count > 0 && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;

if ((fieldDef.AutoIncrement || !string.IsNullOrEmpty(fieldDef.Sequence))
&& dbCommand != null)
@@ -256,21 +256,16 @@ public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICol

cmd.Parameters.Clear();

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
//insertFields contains Property "Name" of fields to insert
var includeField = insertFields == null || insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase);

if (ShouldReturnOnInsert(modelDef, fieldDef) && (!fieldDef.AutoId || !includeField))
if (ShouldReturnOnInsert(modelDef, fieldDef))
{
sbReturningColumns.Append(sbReturningColumns.Length == 0 ? " RETURNING " : ",");
sbReturningColumns.Append(GetQuotedColumnName(fieldDef.FieldName));
}

if (ShouldSkipInsert(fieldDef) && (!fieldDef.AutoId || !includeField))
continue;

if (!includeField)
if (ShouldSkipInsert(fieldDef))
continue;

if (sbColumnNames.Length > 0)
@@ -292,10 +287,20 @@ public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICol
}
}

foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
{
if (fieldDefs.Contains(fieldDef))
continue;

sbReturningColumns.Append(sbReturningColumns.Length == 0 ? " RETURNING " : ",");
sbReturningColumns.Append(GetQuotedColumnName(fieldDef.FieldName));
}

var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
cmd.CommandText = $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) " +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
+ strReturning;
cmd.CommandText = sbColumnNames.Length > 0
? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) " +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)}){strReturning}"
: $"INSERT INTO {GetQuotedTableName(modelDef)} DEFAULT VALUES{strReturning}";
}

//Convert xmin into an integer so it can be used in comparisons
@@ -255,16 +255,14 @@ public override string GetColumnDefinition(FieldDefinition fieldDef)

public override string ToInsertRowStatement(IDbCommand cmd, object objWithProperties, ICollection<string> insertFields = null)
{
if (insertFields == null)
insertFields = new List<string>();

var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var sbReturningColumns = StringBuilderCacheAlt.Allocate();
var tableType = objWithProperties.GetType();
var modelDef = GetModel(tableType);

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (ShouldReturnOnInsert(modelDef, fieldDef))
{
@@ -276,9 +274,6 @@ public override string ToInsertRowStatement(IDbCommand cmd, object objWithProper
if (ShouldSkipInsert(fieldDef))
continue;

if (insertFields.Count > 0 && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;

if (sbColumnNames.Length > 0)
sbColumnNames.Append(",");
if (sbColumnValues.Length > 0)
@@ -299,11 +294,23 @@ public override string ToInsertRowStatement(IDbCommand cmd, object objWithProper
}
}

foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
{
if (fieldDefs.Contains(fieldDef))
continue;

if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}

var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
var sql = $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) " +
strReturning +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})";
var sql = sbColumnNames.Length > 0
? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) " +
strReturning +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
: $"INSERT INTO {GetQuotedTableName(modelDef)} {strReturning} DEFAULT VALUES";

return sql;
}
@@ -341,23 +348,17 @@ public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICol

cmd.Parameters.Clear();

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
//insertFields contains Property "Name" of fields to insert
var includeField = insertFields == null || insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase);

if (ShouldReturnOnInsert(modelDef, fieldDef) && (!fieldDef.AutoId || !includeField))
if (ShouldReturnOnInsert(modelDef, fieldDef))
{
if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}

if (ShouldSkipInsert(fieldDef) && (!fieldDef.AutoId || !includeField))
continue;

//insertFields contains Property "Name" of fields to insert ( that's how expressions work )
if (insertFields != null && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
if (ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
continue;

if (sbColumnNames.Length > 0)
@@ -386,11 +387,22 @@ public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICol
}
}

foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
{
if (fieldDefs.Contains(fieldDef))
continue;

if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}

var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
cmd.CommandText = $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) " +
strReturning +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})";
cmd.CommandText = sbColumnNames.Length > 0
? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) {strReturning}" +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
: $"INSERT INTO {GetQuotedTableName(modelDef)}{strReturning} DEFAULT VALUES";
}

public override void PrepareInsertRowStatement<T>(IDbCommand dbCmd, Dictionary<string, object> args)
@@ -83,6 +83,39 @@ public object GetPrimaryKey(object instance)
private readonly object fieldDefLock = new object();
private Dictionary<string, FieldDefinition> fieldDefinitionMap;
private Func<string, string> fieldNameSanitizer;

public FieldDefinition[] AutoIdFields { get; private set; }

public List<FieldDefinition> GetAutoIdFieldDefinitions()
{
var to = new List<FieldDefinition>();
foreach (var fieldDef in FieldDefinitionsArray)
{
if (fieldDef.AutoId)
{
to.Add(fieldDef);
}
}
return to;
}


public FieldDefinition[] GetOrderedFieldDefinitions(ICollection<string> fieldNames)
{
if (fieldNames == null)
throw new ArgumentNullException(nameof(fieldNames));

var fieldDefs = new FieldDefinition[fieldNames.Count];

var i = 0;
foreach (var fieldName in fieldNames)
{
var fieldDef = GetFieldDefinition(fieldName);
fieldDefs[i++] = fieldDef ?? throw new ArgumentException($"Field '{fieldName}' not found in '{ModelName}'");
}

return fieldDefs;
}

public Dictionary<string, FieldDefinition> GetFieldDefinitionMap(Func<string, string> sanitizeFieldName)
{
@@ -168,6 +201,8 @@ public void AfterInit()
allItems.AddRange(IgnoredFieldDefinitions);
AllFieldDefinitionsArray = allItems.ToArray();

AutoIdFields = GetAutoIdFieldDefinitions().ToArray();

OrmLiteConfig.OnModelDefinitionInit?.Invoke(this);
}

@@ -551,23 +551,25 @@ public virtual SelectItem[] GetColumnNames(ModelDefinition modelDef, string tabl
protected virtual bool ShouldSkipInsert(FieldDefinition fieldDef) =>
fieldDef.ShouldSkipInsert();

public virtual string ToInsertRowStatement(IDbCommand cmd, object objWithProperties, ICollection<string> insertFields = null)
public virtual FieldDefinition[] GetInsertFieldDefinitions(ModelDefinition modelDef, ICollection<string> insertFields)
{
if (insertFields == null)
insertFields = new List<string>();
return insertFields != null
? modelDef.GetOrderedFieldDefinitions(insertFields)
: modelDef.FieldDefinitionsArray;
}

public virtual string ToInsertRowStatement(IDbCommand cmd, object objWithProperties, ICollection<string> insertFields = null)
{
var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var modelDef = objWithProperties.GetType().GetModelDefinition();

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (ShouldSkipInsert(fieldDef))
continue;

if (insertFields.Count > 0 && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;

if (sbColumnNames.Length > 0)
sbColumnNames.Append(",");
if (sbColumnValues.Length > 0)
@@ -625,15 +627,12 @@ public virtual void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, IColl

cmd.Parameters.Clear();

foreach (var fieldDef in modelDef.FieldDefinitionsArray)
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (fieldDef.ShouldSkipInsert())
continue;

//insertFields contains Property "Name" of fields to insert ( that's how expressions work )
if (insertFields != null && !insertFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;

if (sbColumnNames.Length > 0)
sbColumnNames.Append(",");
if (sbColumnValues.Length > 0)

0 comments on commit 0660100

Please sign in to comment.