2016-08-06 16:19:35 +02:00
|
|
|
|
//
|
|
|
|
|
// Copyright (c) 2013-2016 Carsten Sonne Larsen <cs@innolan.dk>
|
|
|
|
|
//
|
2016-05-22 23:40:47 +02:00
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
2016-08-06 16:19:35 +02:00
|
|
|
|
//
|
2016-05-22 23:40:47 +02:00
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
2016-08-06 16:19:35 +02:00
|
|
|
|
//
|
2016-05-22 23:40:47 +02:00
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
// THE SOFTWARE.
|
2016-08-06 16:19:35 +02:00
|
|
|
|
|
2016-05-22 23:40:47 +02:00
|
|
|
|
using System;
|
2016-08-13 21:42:25 +02:00
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2016-05-22 23:40:47 +02:00
|
|
|
|
using System.Text;
|
|
|
|
|
using Npgsql;
|
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* Npqsql Connection String Parameters:
|
|
|
|
|
* Ref: http://www.npgsql.org/doc/connection-string-parameters.html
|
|
|
|
|
*
|
|
|
|
|
* Note that by default, Npgsql will verify that your server’s certificate is valid.
|
|
|
|
|
* If you’re using a self-signed certificate this will fail. You can instruct Npgsql
|
|
|
|
|
* to ignore this by specifying Trust Server Certificate=true in the connection string.
|
|
|
|
|
* To precisely control how the server’s certificate is validated, you can register
|
|
|
|
|
* UserCertificateValidationCallback on NpgsqlConnection (this works just like on
|
|
|
|
|
* .NET’s SSLStream).
|
|
|
|
|
*
|
|
|
|
|
* You can also have Npgsql provide client certificates to the server by registering
|
|
|
|
|
* the ProvideClientCertificatesCallback on NpgsqlConnection (this works just like on
|
|
|
|
|
* .NET’s SSLStream).
|
|
|
|
|
*
|
|
|
|
|
* Ref: http://www.npgsql.org/doc/security.html
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2016-05-22 23:40:47 +02:00
|
|
|
|
namespace Ntp.Data.Provider
|
|
|
|
|
{
|
|
|
|
|
public sealed class PostgreSqlFactory : SqlDatabaseFactory
|
|
|
|
|
{
|
|
|
|
|
internal PostgreSqlFactory()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private const string CreateDatabaseSql1 =
|
|
|
|
|
"SELECT COUNT(*) FROM pg_database WHERE datname = lower('{0}');";
|
|
|
|
|
|
|
|
|
|
private const string CreateDatabaseSql2 =
|
|
|
|
|
"CREATE DATABASE {0};";
|
|
|
|
|
|
|
|
|
|
private const string CheckTableSql =
|
|
|
|
|
"SELECT * " +
|
|
|
|
|
"FROM information_schema.tables " +
|
|
|
|
|
"WHERE table_catalog = lower('{0}') " +
|
|
|
|
|
"AND table_name = lower('{1}');";
|
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
public override IDbCommand CreateCommand()
|
|
|
|
|
{
|
|
|
|
|
return new NpgsqlCommand();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override IDbConnection CreateConnection()
|
|
|
|
|
{
|
|
|
|
|
return new NpgsqlConnection(BuildConnectionString());
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-13 21:42:25 +02:00
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
|
2016-05-22 23:40:47 +02:00
|
|
|
|
public override void CreateDatabase()
|
|
|
|
|
{
|
2016-08-18 19:18:52 +02:00
|
|
|
|
var connection = CreateGenericConnection();
|
2016-05-22 23:40:47 +02:00
|
|
|
|
connection.Open();
|
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
var command = Instance.CreateCommand();
|
2016-05-22 23:40:47 +02:00
|
|
|
|
command.Connection = connection;
|
2016-08-13 21:42:25 +02:00
|
|
|
|
command.CommandText = string.Format(CreateDatabaseSql1, Config.Name);
|
2016-05-22 23:40:47 +02:00
|
|
|
|
command.Prepare();
|
|
|
|
|
int count = Convert.ToInt32(command.ExecuteScalar());
|
|
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
|
{
|
2016-08-13 21:42:25 +02:00
|
|
|
|
command.CommandText = string.Format(CreateDatabaseSql2, Config.Name);
|
2016-05-22 23:40:47 +02:00
|
|
|
|
command.Prepare();
|
|
|
|
|
command.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connection.Close();
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
public override IDbConnection CreateGenericConnection()
|
2016-05-22 23:40:47 +02:00
|
|
|
|
{
|
2016-08-18 19:18:52 +02:00
|
|
|
|
return new NpgsqlConnection(BuildConnectionString(false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override IDbDataParameter CreateParameter(string name, object value)
|
|
|
|
|
{
|
|
|
|
|
return new NpgsqlParameter(name, value);
|
2016-05-22 23:40:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-04 22:35:06 +02:00
|
|
|
|
public override string DateAddMinutes(string dateColumn, string minuteColumn)
|
|
|
|
|
{
|
2016-09-08 21:28:21 +02:00
|
|
|
|
return $"{dateColumn} - {minuteColumn} * INTERVAL '1 minute'";
|
2016-09-04 22:35:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-05-22 23:40:47 +02:00
|
|
|
|
public override string PrepareCheckTableSql(string table)
|
|
|
|
|
{
|
2016-08-13 21:42:25 +02:00
|
|
|
|
return PrepareSql(string.Format(CheckTableSql, Config.Name, table));
|
2016-05-22 23:40:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string PrepareCreateTableSql(string sql)
|
|
|
|
|
{
|
2016-08-18 19:18:52 +02:00
|
|
|
|
string sql2 = sql.
|
|
|
|
|
Replace("UNIQUE KEY", "UNIQUE").
|
|
|
|
|
Replace("BIT(1)", "BOOL");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-08-13 21:42:25 +02:00
|
|
|
|
return PrepareSql(string.Format(sql2, "SERIAL", string.Empty));
|
2016-05-22 23:40:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string PrepareInsertSql(string sql)
|
|
|
|
|
{
|
2016-08-13 21:42:25 +02:00
|
|
|
|
return PrepareSql(string.Format(sql, "SELECT LASTVAL();"));
|
2016-05-22 23:40:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
public override string PrepareSql(string sql)
|
2016-05-22 23:40:47 +02:00
|
|
|
|
{
|
2016-08-18 19:18:52 +02:00
|
|
|
|
return sql.Replace('[', '\"').Replace(']', '\"');
|
2016-05-22 23:40:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
private static string BuildConnectionString(bool includeName = true)
|
2016-05-22 23:40:47 +02:00
|
|
|
|
{
|
2016-08-18 19:18:52 +02:00
|
|
|
|
if (Config.ConnectionString != null)
|
|
|
|
|
return Config.ConnectionString;
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
|
|
|
|
var b = new StringBuilder();
|
2016-08-18 19:18:52 +02:00
|
|
|
|
b.Append($"Server={Config.Host};");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
|
|
|
|
if (Config.Port != null)
|
2016-08-18 19:18:52 +02:00
|
|
|
|
b.Append($"Port={Config.Port};");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
b.Append(includeName ? $"Database={Config.Name};" : @"Database=postgres;");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
b.Append($"User Id={Config.User};");
|
|
|
|
|
b.Append($"Password={Config.Pass};");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
if (Config.ConnectionTimeout.HasValue)
|
|
|
|
|
b.Append($"Timeout={Config.ConnectionTimeout.Value};");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-09-04 22:35:06 +02:00
|
|
|
|
b.Append(Config.EnableSsl ? @"SslMode=Require;" : @"SslMode=Disable;");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
if (Config.Protocol.HasValue)
|
|
|
|
|
b.Append($"Protocol={Config.Protocol.Value};");
|
2016-05-22 23:40:47 +02:00
|
|
|
|
|
2016-08-18 19:18:52 +02:00
|
|
|
|
return b.ToString();
|
2016-05-22 23:40:47 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-20 13:54:56 +02:00
|
|
|
|
}
|