public EventsTable(EventGraph events) : base(new DbObjectName(events.DatabaseSchemaName, "mt_events")) { var stringIdType = events.GetStreamIdDBType(); AddPrimaryKey(new TableColumn("seq_id", "bigint")); AddColumn("id", "uuid", "NOT NULL"); AddColumn("stream_id", stringIdType, (events.TenancyStyle != TenancyStyle.Conjoined) ? $"REFERENCES {events.DatabaseSchemaName}.mt_streams ON DELETE CASCADE" : null); AddColumn("version", "integer", "NOT NULL"); AddColumn("data", "jsonb", "NOT NULL"); AddColumn("type", "varchar(100)", "NOT NULL"); AddColumn("timestamp", "timestamptz", "default (now()) NOT NULL"); AddColumn <TenantIdColumn>(); AddColumn(new DotNetTypeColumn { Directive = "NULL" }); if (events.TenancyStyle == TenancyStyle.Conjoined) { Constraints.Add($"FOREIGN KEY(stream_id, {TenantIdColumn.Name}) REFERENCES {events.DatabaseSchemaName}.mt_streams(id, {TenantIdColumn.Name})"); Constraints.Add($"CONSTRAINT pk_mt_events_stream_and_version UNIQUE(stream_id, {TenantIdColumn.Name}, version)"); } else { Constraints.Add("CONSTRAINT pk_mt_events_stream_and_version UNIQUE(stream_id, version)"); } Constraints.Add("CONSTRAINT pk_mt_events_id_unique UNIQUE(id)"); }
public override void Write(DdlRules rules, StringWriter writer) { var streamIdType = _events.GetStreamIdDBType(); var databaseSchema = _events.DatabaseSchemaName; var tenancyStyle = _events.TenancyStyle; var streamsWhere = "id = stream"; if (tenancyStyle == TenancyStyle.Conjoined) { streamsWhere += " AND tenant_id = tenantid"; } writer.WriteLine($@" CREATE OR REPLACE FUNCTION {Identifier}(stream {streamIdType}, stream_type varchar, tenantid varchar, event_ids uuid[], event_types varchar[], dotnet_types varchar[], bodies jsonb[]) RETURNS int[] AS $$ DECLARE event_version int; event_type varchar; event_id uuid; body jsonb; index int; seq int; actual_tenant varchar; return_value int[]; BEGIN select version into event_version from {databaseSchema}.mt_streams where {streamsWhere}{(_events.UseAppendEventForUpdateLock ? " for update" : string.Empty)}; if event_version IS NULL then event_version = 0; insert into {databaseSchema}.mt_streams (id, type, version, timestamp, tenant_id) values (stream, stream_type, 0, now(), tenantid); else if tenantid IS NOT NULL then select tenant_id into actual_tenant from {databaseSchema}.mt_streams where {streamsWhere}; if actual_tenant != tenantid then RAISE EXCEPTION 'Marten: The tenantid does not match the existing stream'; end if; end if; end if; index := 1; return_value := ARRAY[event_version + array_length(event_ids, 1)]; foreach event_id in ARRAY event_ids loop seq := nextval('{databaseSchema}.mt_events_sequence'); return_value := array_append(return_value, seq); event_version := event_version + 1; event_type = event_types[index]; body = bodies[index]; insert into {databaseSchema}.mt_events (seq_id, id, stream_id, version, data, type, tenant_id, {DocumentMapping.DotNetTypeColumn}) values (seq, event_id, stream, event_version, body, event_type, tenantid, dotnet_types[index]); index := index + 1; end loop; update {databaseSchema}.mt_streams set version = event_version, timestamp = now() where {streamsWhere}; return return_value; END $$ LANGUAGE plpgsql; "); }