public PostgreSqlQueryExecutor(PostgreSqlQueryConfiguration configuration, Akka.Serialization.Serialization serialization, ITimestampProvider timestampProvider)
            : base(configuration, serialization, timestampProvider)
        {
            _configuration = configuration;
            var storedAs = configuration.StoredAs.ToString().ToUpperInvariant();

            CreateEventsJournalSql = $@"
                CREATE TABLE IF NOT EXISTS {Configuration.FullJournalTableName} (
                    {Configuration.OrderingColumnName} BIGSERIAL NOT NULL PRIMARY KEY,
                    {Configuration.PersistenceIdColumnName} VARCHAR(255) NOT NULL,
                    {Configuration.SequenceNrColumnName} BIGINT NOT NULL,
                    {Configuration.IsDeletedColumnName} BOOLEAN NOT NULL,
                    {Configuration.TimestampColumnName} BIGINT NOT NULL,
                    {Configuration.ManifestColumnName} VARCHAR(500) NOT NULL,
                    {Configuration.PayloadColumnName} {storedAs} NOT NULL,
                    {Configuration.TagsColumnName} VARCHAR(100) NULL,
                    {Configuration.SerializerIdColumnName} INTEGER NULL,
                    CONSTRAINT {Configuration.JournalEventsTableName}_uq UNIQUE ({Configuration.PersistenceIdColumnName}, {Configuration.SequenceNrColumnName})
                );
                ";

            CreateMetaTableSql = $@"
                CREATE TABLE IF NOT EXISTS {Configuration.FullMetaTableName} (
                    {Configuration.PersistenceIdColumnName} VARCHAR(255) NOT NULL,
                    {Configuration.SequenceNrColumnName} BIGINT NOT NULL,
                    CONSTRAINT {Configuration.MetaTableName}_pk PRIMARY KEY ({Configuration.PersistenceIdColumnName}, {Configuration.SequenceNrColumnName})
                );";

            switch (_configuration.StoredAs)
            {
            case StoredAsType.ByteA:
                _serialize = e =>
                {
                    var serializer = Serialization.FindSerializerFor(e.Payload);
                    return(new SerializationResult(NpgsqlDbType.Bytea, serializer.ToBinary(e.Payload), serializer));
                };
                _deserialize = (type, serialized, manifest, serializerId) =>
                {
                    if (serializerId.HasValue)
                    {
                        return(Serialization.Deserialize((byte[])serialized, serializerId.Value, manifest));
                    }
                    else
                    {
                        // Support old writes that did not set the serializer id
                        var deserializer = Serialization.FindSerializerForType(type, Configuration.DefaultSerializer);
                        return(deserializer.FromBinary((byte[])serialized, type));
                    }
                };
                break;

            case StoredAsType.JsonB:
                _serialize   = e => new SerializationResult(NpgsqlDbType.Jsonb, JsonConvert.SerializeObject(e.Payload, _configuration.JsonSerializerSettings), null);
                _deserialize = (type, serialized, manifest, serializerId) => JsonConvert.DeserializeObject((string)serialized, type, _configuration.JsonSerializerSettings);
                break;

            case StoredAsType.Json:
                _serialize   = e => new SerializationResult(NpgsqlDbType.Json, JsonConvert.SerializeObject(e.Payload, _configuration.JsonSerializerSettings), null);
                _deserialize = (type, serialized, manifest, serializerId) => JsonConvert.DeserializeObject((string)serialized, type, _configuration.JsonSerializerSettings);
                break;

            default:
                throw new NotSupportedException($"{_configuration.StoredAs} is not supported Db type for a payload");
            }
        }
        public PostgreSqlQueryExecutor(PostgreSqlQueryConfiguration configuration, Akka.Serialization.Serialization serialization, ITimestampProvider timestampProvider)
            : base(configuration, serialization, timestampProvider)
        {
            var storedAs = configuration.StoredAs.ToString().ToUpperInvariant();

            CreateEventsJournalSql = $@"
                CREATE TABLE IF NOT EXISTS {Configuration.FullJournalTableName} (
                    {Configuration.OrderingColumnName} {(configuration.UseBigIntPrimaryKey ? "BIGINT GENERATED ALWAYS AS IDENTITY" : "BIGSERIAL")} NOT NULL PRIMARY KEY,
                    {Configuration.PersistenceIdColumnName} VARCHAR(255) NOT NULL,
                    {Configuration.SequenceNrColumnName} BIGINT NOT NULL,
                    {Configuration.IsDeletedColumnName} BOOLEAN NOT NULL,
                    {Configuration.TimestampColumnName} BIGINT NOT NULL,
                    {Configuration.ManifestColumnName} VARCHAR(500) NOT NULL,
                    {Configuration.PayloadColumnName} {storedAs} NOT NULL,
                    {Configuration.TagsColumnName} VARCHAR(100) NULL,
                    {Configuration.SerializerIdColumnName} INTEGER NULL,
                    CONSTRAINT {Configuration.JournalEventsTableName}_uq UNIQUE ({Configuration.PersistenceIdColumnName}, {Configuration.SequenceNrColumnName})
                );";

            CreateMetaTableSql = $@"
                CREATE TABLE IF NOT EXISTS {Configuration.FullMetaTableName} (
                    {Configuration.PersistenceIdColumnName} VARCHAR(255) NOT NULL,
                    {Configuration.SequenceNrColumnName} BIGINT NOT NULL,
                    CONSTRAINT {Configuration.MetaTableName}_pk PRIMARY KEY ({Configuration.PersistenceIdColumnName}, {Configuration.SequenceNrColumnName})
                );";

            HighestSequenceNrSql = $@"
                SELECT MAX(u.SeqNr) as SequenceNr 
                FROM (
                    SELECT MAX(e.{Configuration.SequenceNrColumnName}) as SeqNr FROM {Configuration.FullJournalTableName} e WHERE e.{Configuration.PersistenceIdColumnName} = @PersistenceId
                    UNION
                    SELECT MAX(m.{Configuration.SequenceNrColumnName}) as SeqNr FROM {Configuration.FullMetaTableName} m WHERE m.{Configuration.PersistenceIdColumnName} = @PersistenceId) as u";

            // As per https://github.com/akkadotnet/Akka.Persistence.PostgreSql/pull/72, apparently PostgreSQL does not like
            // it when you chain two deletes in a single command, so we have to split it into two.
            // The performance penalty should be minimal, depending on the network speed
            DeleteBatchSql = $@"
                DELETE FROM {Configuration.FullJournalTableName}
                WHERE {Configuration.PersistenceIdColumnName} = @PersistenceId AND {Configuration.SequenceNrColumnName} <= @ToSequenceNr;";

            DeleteBatchSqlMetadata = $@"DELETE FROM {Configuration.FullMetaTableName}
                WHERE {Configuration.PersistenceIdColumnName} = @PersistenceId AND {Configuration.SequenceNrColumnName} <= @ToSequenceNr;";

            switch (configuration.StoredAs)
            {
            case StoredAsType.ByteA:
                _serialize = e =>
                {
                    var payloadType = e.Payload.GetType();
                    var serializer  = Serialization.FindSerializerForType(payloadType, Configuration.DefaultSerializer);

                    // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811
                    var binary = Akka.Serialization.Serialization.WithTransport(Serialization.System, () => serializer.ToBinary(e.Payload));

                    return(new SerializationResult(NpgsqlDbType.Bytea, binary, serializer));
                };
                _deserialize = (type, payload, manifest, serializerId) =>
                {
                    if (serializerId.HasValue)
                    {
                        // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811
                        return(Serialization.Deserialize((byte[])payload, serializerId.Value, manifest));
                    }
                    else
                    {
                        // Support old writes that did not set the serializer id
                        var deserializer = Serialization.FindSerializerForType(type, Configuration.DefaultSerializer);

                        // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811
                        return(Akka.Serialization.Serialization.WithTransport(Serialization.System, () => deserializer.FromBinary((byte[])payload, type)));
                    }
                };
                break;

            case StoredAsType.JsonB:
                _serialize   = e => new SerializationResult(NpgsqlDbType.Jsonb, JsonConvert.SerializeObject(e.Payload, configuration.JsonSerializerSettings), null);
                _deserialize = (type, serialized, manifest, serializerId) => JsonConvert.DeserializeObject((string)serialized, type, configuration.JsonSerializerSettings);
                break;

            case StoredAsType.Json:
                _serialize   = e => new SerializationResult(NpgsqlDbType.Json, JsonConvert.SerializeObject(e.Payload, configuration.JsonSerializerSettings), null);
                _deserialize = (type, serialized, manifest, serializerId) => JsonConvert.DeserializeObject((string)serialized, type, configuration.JsonSerializerSettings);
                break;

            default:
                throw new NotSupportedException($"{configuration.StoredAs} is not supported Db type for a payload");
            }
        }