Skip to content

Commit

Permalink
Merge pull request #8 from ptixed/postgre
Browse files Browse the repository at this point in the history
Postgre
  • Loading branch information
ptixed authored Jul 4, 2024
2 parents 93d662b + f0ba82d commit 64b0e90
Show file tree
Hide file tree
Showing 39 changed files with 1,867 additions and 1,053 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ jobs:
id: publish_nuget
uses: alirezanet/[email protected]
with:
PROJECT_FILE_PATH: Ptixed.Sql/Ptixed.Sql.csproj
PROJECT_FILE_PATH: Ptixed.Sql.SqlServer/Ptixed.Sql.SqlServer.csproj
PACKAGE_NAME: Ptixed.Sql

VERSION_FILE_PATH: Ptixed.Sql/Ptixed.Sql.csproj
VERSION_FILE_PATH: Ptixed.Sql.SqlServer/Ptixed.Sql.SqlServer.csproj
VERSION_REGEX: ^\s*<Version>(.*)<\/Version>\s*$
# VERSION_STATIC: 1.0.0

TAG_COMMIT: true
TAG_FORMAT: v*
Expand Down
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

/.vs/
.vs/
*.user

/packages/
bin/
obj/

*.user
appsettings.json
12 changes: 12 additions & 0 deletions Ptixed.Sql.Postgres/Database.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Npgsql;
using Ptixed.Sql.Impl;

namespace Ptixed.Sql.Postgres
{
public class Database : Database<NpgsqlConnection, NpgsqlCommand, NpgsqlParameter>, IDatabase
{
public Database(ConnectionConfig config) : base(config)
{
}
}
}
96 changes: 96 additions & 0 deletions Ptixed.Sql.Postgres/DatabaseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Ptixed.Sql.Meta;
using Ptixed.Sql.Postgres;

namespace Ptixed.Sql.Postgres
{
public static class DatabaseExtensions
{
public static List<T> ToList<T>(this IDatabase db, FormattableString query, params Type[] types)
=> db.Query<T>(new Query(query), types).ToList();

public static List<T> ToList<T>(this IDatabase db, FormattableString query)
=> ToList<T>(db, query, new[] { typeof(T) });
public static List<T1> ToList<T1, T2>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2) });
public static List<T1> ToList<T1, T2, T3>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2), typeof(T3) });
public static List<T1> ToList<T1, T2, T3, T4>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) });
public static List<T1> ToList<T1, T2, T3, T4, T5>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) });
public static List<T1> ToList<T1, T2, T3, T4, T5, T6>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) });
public static List<T1> ToList<T1, T2, T3, T4, T5, T6, T7>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) });
public static List<T1> ToList<T1, T2, T3, T4, T5, T6, T7, T8>(this IDatabase db, FormattableString query)
=> ToList<T1>(db, query, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) });

public static T Single<T>(this IDatabase db, FormattableString query)
=> db.Query<T>(new Query(query)).Single();

public static T SingleOrDefault<T>(this IDatabase db, FormattableString query)
=> db.Query<T>(new Query(query)).SingleOrDefault();

public static T FirstOrDefault<T>(this IDatabase db, FormattableString query)
=> db.Query<T>(new Query(query)).FirstOrDefault();

public static int NonQuery(this IDatabase db, FormattableString query)
=> db.NonQuery(new Query(query));

public static List<T> GetByIds<T>(this IDatabase db, params object[] ids)
{
if (ids.Length == 0)
return new List<T>();
return db.Query<T>(QueryHelper.GetById<T>(ids)).ToList();
}

public static T GetById<T>(this IDatabase db, object id)
{
return GetByIds<T>(db, id).SingleOrDefault();
}

public static List<T> Insert<T>(this IDatabase db, params T[] entities)
{
if (entities.Length == 0)
return new List<T>();
var result = db.Query<T>(QueryHelper.Insert(entities)).ToList();

var table = Table.Get(typeof(T));

if (table.AutoIncrementColumn != null)
foreach (var (inserted, i) in result.Select((x, i) => (x, i)))
table[entities[i], table.AutoIncrementColumn.LogicalColumn] = table[inserted, table.AutoIncrementColumn.LogicalColumn];

return entities.ToList();
}

public static T Insert<T>(this IDatabase db, T entity)
{
return Insert(db, new [] { entity })[0];
}

public static int Update(this IDatabase db, params object[] entities)
{
if (entities.Length == 0)
return 0;
return db.NonQuery(QueryHelper.Update(entities));
}

public static int Delete(this IDatabase db, params object[] entities)
{
if (entities.Length == 0)
return 0;
return db.NonQuery(QueryHelper.Delete(entities));
}

public static int Delete<T>(this IDatabase db, params object[] ids)
{
if (ids.Length == 0)
return 0;
return db.NonQuery(QueryHelper.Delete<T>(ids));
}
}
}
8 changes: 8 additions & 0 deletions Ptixed.Sql.Postgres/IDatabase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Npgsql;

namespace Ptixed.Sql.Postgres
{
public interface IDatabase : IDatabase<NpgsqlParameter>
{
}
}
22 changes: 22 additions & 0 deletions Ptixed.Sql.Postgres/Ptixed.Sql.Postgres.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<SignAssembly>False</SignAssembly>
<Title>Ptixed.Sql.Postgres</Title>
<Version>0.1.0</Version>
<Description>Library for interacting with Microsoft SQL databases</Description>
<Authors>ptixed</Authors>
<RepositoryUrl>https://github.com/ptixed/Ptixed.Sql</RepositoryUrl>
<PackageTags>ptixed sql tsql database db</PackageTags>
<AssemblyVersion>0.1.0</AssemblyVersion>
<FileVersion>0.1.0</FileVersion>
<Company />
<PackageIconUrl>https://raw.githubusercontent.com/ptixed/Ptixed.Sql/master/logo-nuget.png</PackageIconUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Npgsql" Version="8.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ptixed.Sql\Ptixed.Sql.csproj" />
</ItemGroup>
</Project>
17 changes: 17 additions & 0 deletions Ptixed.Sql.Postgres/Query.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Npgsql;
using System;
using System.Runtime.CompilerServices;

namespace Ptixed.Sql.Postgres
{
public class Query : Query<NpgsqlParameter>
{
public static Query Unsafe(string query) => new Query(FormattableStringFactory.Create(query));

public Query() { }
public Query(FormattableString query) : base(query) { }

protected override string FormatTableName(string name) => $"\"{name}\"";
protected override string FormatColumnName(string name) => $"\"{name}\"";
}
}
123 changes: 123 additions & 0 deletions Ptixed.Sql.Postgres/QueryHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Ptixed.Sql.Impl;
using Ptixed.Sql.Meta;

namespace Ptixed.Sql.Postgres
{
public static class QueryHelper
{
public static Query GetPrimaryKeyCondition(Table table, object key)
{
var query = new Query();
query.Append($"(");
query.Append($" AND ", table.PrimaryKey.FromValueToQuery(key).Select(column => new Query($"{column} = {column.Value}")));
query.Append($")");
return query;
}

public static Query GetById<T>(params object[] ids)
{
if (ids == null || ids.Length == 0)
return null;

var table = Table.Get(typeof(T));

var query = new Query();
query.Append($"SELECT * FROM {table} WHERE ");
query.Append($" OR ", ids.Select(id => GetPrimaryKeyCondition(table, id)));
return query;
}

public static Query Insert<T>(params T[] entities)
{
if (entities == null || entities.Length == 0)
return null;

var table = Table.Get(typeof(T));
var columns = table.PhysicalColumns.Except(new[] { table.AutoIncrementColumn }).ToList<PhysicalColumn>();

var query = new Query();
query.Append($"INSERT INTO {table} (");
query.Append($", ", columns.Select(x => new Query($"{x}")));
query.Append($") VALUES ");
query.Append($", ", entities.Select(entity =>
{
var values = table.ToQuery(columns, entity)
.Select(column => new Query($"{column.Value}"))
.ToList();

var q = new Query();
q.Append($"(");
q.Append($", ", values);
q.Append($")");
return q;
}));
query.Append($" RETURNING ");
query.Append($", ", table.PhysicalColumns.Select(column => new Query($"{column}")));
return query;
}

public static Query Update(params object[] entities)
{
if (entities == null || entities.Length == 0)
return null;

var query = new Query();
for (var i = 0; i < entities.Length; ++i)
{
var entity = entities[i];
var table = Table.Get(entity.GetType());
var columns = table.PhysicalColumns.Where(x => !x.IsPrimaryKey).ToList<PhysicalColumn>();

var values = table.ToQuery(columns, entity)
.Select(column => new Query($"{column} = {column.Value}"))
.ToList();

query.Append($"UPDATE {table} SET ");
query.Append($", ", values);
query.Append($" WHERE ");
query.Append(GetPrimaryKeyCondition(table, table[entity, table.PrimaryKey]));

if (i < entities.Length - 1)
query.Append($";");
}
return query;
}

public static Query Delete(params object[] entities)
{
if (entities == null || entities.Length == 0)
return null;

var query = new Query();
for (var i = 0; i < entities.Length; ++i)
{
var entity = entities[i];
var table = Table.Get(entity.GetType());
var id = table[entity, table.PrimaryKey];

query.Append($"DELETE FROM {table} WHERE ");
query.Append(GetPrimaryKeyCondition(table, id));

if (i < entities.Length - 1)
query.Append($";");
}
return query;
}

public static Query Delete<T>(params object[] ids)
{
if (ids == null || ids.Length == 0)
return null;

var table = Table.Get(typeof(T));

var query = new Query();
query.Append($"DELETE FROM {table} WHERE ");
query.Append($" OR ", ids.Select(id => GetPrimaryKeyCondition(table, id)));
return query;
}
}
}
45 changes: 45 additions & 0 deletions Ptixed.Sql.SqlServer/Database.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Ptixed.Sql.Impl;
using Ptixed.Sql.Meta;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;

namespace Ptixed.Sql.SqlServer
{
public class Database : Database<SqlConnection, SqlCommand, SqlParameter>, IDatabase
{
public Database(ConnectionConfig config) : base(config)
{
}

public void BulkInsert<T>(IEnumerable<T> entities)
{
var table = Table.Get(typeof(T));
var columns = table.PhysicalColumns.Except(new[] { table.AutoIncrementColumn }).ToList<PhysicalColumn>();

var payload = new DataTable();

foreach (var column in columns)
payload.Columns.Add(column.Name);

foreach (var entity in entities)
{
var row = payload.NewRow();
var values = table.ToQuery(columns, entity);
foreach (var (name, value) in values)
row[name] = value;
payload.Rows.Add(row);
}

using (var bcp = new SqlBulkCopy(Connection.Value))
{
foreach (var column in columns)
bcp.ColumnMappings.Add(column.Name, column.Name);

bcp.DestinationTableName = table.Name;
bcp.WriteToServer(payload);
}
}
}
}
Loading

0 comments on commit 64b0e90

Please sign in to comment.