Permalink
Browse files

Add support for InsertIntoSelect

  • Loading branch information...
mythz committed Nov 28, 2018
1 parent 423e859 commit 282d55c73b955c3a2bbc6e9ed395b23bd99ffbb2
BIN +512 Bytes (100%) lib/net45/ServiceStack.Common.dll
Binary file not shown.
@@ -91,6 +91,24 @@ public static void InsertUsingDefaults<T>(this IDbConnection dbConn, params T[]
dbConn.Exec(dbCmd => dbCmd.InsertUsingDefaults(objs));
}

/// <summary>
/// Insert results from SELECT SqlExpression, use selectIdentity to retrieve the last insert AutoIncrement id (if any). E.g:
/// <para>var id = db.InsertIntoSelect&lt;Contact&gt;(db.From&lt;Person&gt;().Select(x => new { x.Id, Surname == x.LastName }))</para>
/// </summary>
public static long InsertIntoSelect<T>(this IDbConnection dbConn, ISqlExpression query)
{
return dbConn.Exec(dbCmd => dbCmd.InsertIntoSelect<T>(query, commandFilter: null));
}

/// <summary>
/// Insert results from SELECT SqlExpression, use selectIdentity to retrieve the last insert AutoIncrement id (if any). E.g:
/// <para>var id = db.InsertIntoSelect&lt;Contact&gt;(db.From&lt;Person&gt;().Select(x => new { x.Id, Surname == x.LastName }))</para>
/// </summary>
public static long InsertIntoSelect<T>(this IDbConnection dbConn, ISqlExpression query, Action<IDbCommand> commandFilter)
{
return dbConn.Exec(dbCmd => dbCmd.InsertIntoSelect<T>(query, commandFilter: commandFilter));
}

/// <summary>
/// Insert a collection of POCOs in a transaction. E.g:
/// <para>db.InsertAll(new[] { new Person { Id = 9, FirstName = "Biggie", LastName = "Smalls", Age = 24 } })</para>
@@ -689,6 +689,30 @@ internal static void Insert<T>(this IDbCommand dbCmd, Action<IDbCommand> command
dbCmd.InsertAll(objs: objs, commandFilter: commandFilter);
}

internal static long InsertIntoSelect<T>(this IDbCommand dbCmd, ISqlExpression query, Action<IDbCommand> commandFilter)
{
var dialectProvider = dbCmd.GetDialectProvider();

var sql = query.ToSelectStatement();
var selectFields = query.GetUntypedSqlExpression()
.SelectExpression
.Substring("SELECT ".Length)
.ParseCommands();

var fieldsOrAliases = selectFields
.Map(x => x.Name.LastRightPart("AS").Trim().StripQuotes());

dialectProvider.PrepareParameterizedInsertStatement<T>(dbCmd, insertFields: fieldsOrAliases);

dbCmd.SetParameters(query.Params);

dbCmd.CommandText = dbCmd.CommandText.LeftPart(")") + ")\n" + sql;

commandFilter?.Invoke(dbCmd); //dbCmd.OnConflictInsert() needs to be applied before last insert id

return dbCmd.ExecNonQuery();
}

internal static void InsertAll<T>(this IDbCommand dbCmd, IEnumerable<T> objs, Action<IDbCommand> commandFilter)
{
IDbTransaction dbTrans = null;
@@ -56,4 +56,8 @@
<Reference Include="..\..\lib\netstandard2.0\ServiceStack.Common.dll" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.1" />
</ItemGroup>

</Project>
@@ -375,6 +375,54 @@ public void Can_insert_record_with_Computed_column()
fieldDef.IsComputed = true;
}
}

[Test]
public void Can_InsertIntoSelect_using_Custom_Select()
{
using (var db = OpenDbConnection())
{
OrmLiteConfig.BeforeExecFilter = cmd => cmd.GetDebugString().Print();
db.DropAndCreateTable<UserAuth>();
db.DropAndCreateTable<SubUserAuth>();

var userAuth = new UserAuth {
Id = 1,
UserName = "UserName",
Email = "a@b.com",
PrimaryEmail = "c@d.com",
FirstName = "FirstName",
LastName = "LastName",
DisplayName = "DisplayName",
Salt = "Salt",
PasswordHash = "PasswordHash",
CreatedDate = DateTime.Now,
ModifiedDate = DateTime.UtcNow,
};
db.Insert(userAuth);

var q = db.From<UserAuth>()
.Where(x => x.UserName == "UserName")
.Select(x => new {
x.UserName,
x.Email,
GivenName = x.FirstName,
Surname = x.LastName,
FullName = x.FirstName + " " + x.LastName
});

var id = db.InsertIntoSelect<SubUserAuth>(q);
Assert.That(id, Is.EqualTo(1));

var result = db.Select<SubUserAuth>()[0];

Assert.That(result.Id, Is.GreaterThan(0));
Assert.That(result.UserName, Is.EqualTo(userAuth.UserName));
Assert.That(result.Email, Is.EqualTo(userAuth.Email));
Assert.That(result.GivenName, Is.EqualTo(userAuth.FirstName));
Assert.That(result.Surname, Is.EqualTo(userAuth.LastName));
Assert.That(result.FullName, Is.EqualTo(userAuth.FirstName + " " + userAuth.LastName));
}
}
}

public class Market
@@ -458,4 +506,15 @@ public class UserAuthRole
public virtual string RefIdStr { get; set; }
public virtual Dictionary<string, string> Meta { get; set; }
}

public class SubUserAuth
{
[AutoIncrement]
public virtual int Id { get; set; }
public virtual string UserName { get; set; }
public string Email { get; set; }
public string GivenName { get; set; }
public string Surname { get; set; }
public string FullName { get; set; }
}
}

0 comments on commit 282d55c

Please sign in to comment.