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"); } }