public UpsertFunction(IDocumentMapping mapping) { FunctionName = mapping.UpsertName; TableName = mapping.TableName; var idType = mapping.IdMember.GetMemberType(); PgIdType = TypeMappings.GetPgType(idType); Id_NpgsqlDbType = TypeMappings.ToDbType(idType); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = PgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new UpsertArgument { Arg = "doc", PostgresType = "JSONB", DbType = NpgsqlDbType.Jsonb, Column = "data", BulkInsertPattern = "writer.Write(serializer.ToJson(x), NpgsqlDbType.Jsonb);", BatchUpdatePattern = "*" }); }
public UpsertFunction(DocumentMapping mapping) { if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _functionName = mapping.UpsertFunction; _tableName = mapping.Table; _primaryKeyConstraintName = "pk_" + mapping.Table.Name; var idType = mapping.IdMember.GetMemberType(); var pgIdType = TypeMappings.GetPgType(idType); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Select(x => x.UpsertArgument)); Arguments.Add(new VersionArgument()); Arguments.Add(new DotNetTypeArgument()); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } }
public DocumentTable(DocumentMapping mapping) : base(mapping.Table) { var pgIdType = TypeMappings.GetPgType(mapping.IdMember.GetMemberType()); AddPrimaryKey(new TableColumn("id", pgIdType)); AddColumn("data", "jsonb", "NOT NULL"); AddColumn <LastModifiedColumn>(); AddColumn <VersionColumn>(); AddColumn <DotNetTypeColumn>(); foreach (var field in mapping.DuplicatedFields) { AddColumn(new DuplicatedFieldColumn(field)); } if (mapping.IsHierarchy()) { AddColumn(new DocumentTypeColumn(mapping)); } if (mapping.DeleteStyle == DeleteStyle.SoftDelete) { AddColumn <DeletedColumn>(); AddColumn <DeletedAtColumn>(); } Indexes.AddRange(mapping.Indexes); ForeignKeys.AddRange(mapping.ForeignKeys); }
public void execute_get_pg_type_custom_mappings_resolve_or_default_to_jsonb() { NpgsqlConnection.GlobalTypeMapper.MapComposite <MappedTarget>("varchar"); TypeMappings.GetPgType(typeof(MappedTarget), EnumStorage.AsString).ShouldBe("varchar"); TypeMappings.GetPgType(typeof(UnmappedTarget), EnumStorage.AsString).ShouldBe("jsonb"); }
public TableDefinition StorageTable() { var pgIdType = TypeMappings.GetPgType(_mapping.IdMember.GetMemberType()); var table = new TableDefinition(_mapping.Table, new TableColumn("id", pgIdType)); table.Columns.Add(new TableColumn("data", "jsonb") { Directive = "NOT NULL" }); table.Columns.Add(new TableColumn(DocumentMapping.LastModifiedColumn, "timestamp with time zone") { Directive = "DEFAULT transaction_timestamp()" }); table.Columns.Add(new TableColumn(DocumentMapping.VersionColumn, "uuid") { Directive = "NOT NULL" }); table.Columns.Add(new TableColumn(DocumentMapping.DotNetTypeColumn, "varchar")); _mapping.DuplicatedFields.Select(x => x.ToColumn()).Each(x => table.Columns.Add(x)); if (_mapping.IsHierarchy()) { table.Columns.Add(new TableColumn(DocumentMapping.DocumentTypeColumn, "varchar")); } return(table); }
public UpsertFunction(DocumentMapping mapping, DbObjectName identifier = null, bool disableConcurrency = false) : base(identifier ?? mapping.UpsertFunction) { _disableConcurrency = disableConcurrency; if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _tableName = mapping.Table; var table = new DocumentTable(mapping); if (table.PrimaryKeys.Count > 1) { _primaryKeyConstraintName = mapping.Table.Name + "_pkey"; } else { _primaryKeyConstraintName = "pk_" + mapping.Table.Name; } var idType = mapping.IdMember.GetMemberType(); var pgIdType = TypeMappings.GetPgType(idType); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Select(x => x.UpsertArgument)); Arguments.Add(new VersionArgument()); Arguments.Add(new DotNetTypeArgument()); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } if (mapping.UseOptimisticConcurrency) { Arguments.Add(new CurrentVersionArgument()); } if (mapping.TenancyStyle == TenancyStyle.Conjoined) { Arguments.Add(new TenantIdArgument()); _tenantWhereClause = $"{_tableName.QualifiedName}.{TenantIdColumn.Name} = {TenantIdArgument.ArgName}"; _andTenantWhereClause = $" and {_tenantWhereClause}"; } }
public StreamTableColumn(string name, Expression <Func <StreamAction, object> > memberExpression) : base(name, "varchar") { _memberExpression = memberExpression; _member = FindMembers.Determine(memberExpression).Single(); var memberType = _member.GetMemberType(); Type = TypeMappings.GetPgType(memberType, EnumStorage.AsInteger); NpgsqlDbType = TypeMappings.ToDbType(memberType); }
public DictionaryField(string dataLocator, Casing casing, EnumStorage enumStorage, MemberInfo[] members) : base(dataLocator, "JSONB", casing, members) { TypedLocator = $"CAST({RawLocator} as {PgType})"; _intermediateLocator = RawLocator.Replace("->>", "->"); var valueType = FieldType.GenericTypeArguments[1]; _isStringValue = valueType == typeof(string); _valuePgType = TypeMappings.GetPgType(valueType, enumStorage); }
protected Field(EnumStorage enumStorage, MemberInfo[] members) { Members = members; MemberName = members.Select(x => x.Name).Join(""); FieldType = members.Last().GetMemberType(); PgType = TypeMappings.GetPgType(FieldType, enumStorage); }
protected Field(MemberInfo[] members) { Members = members; MemberName = members.Select(x => x.Name).Join(""); MemberType = members.Last().GetMemberType(); PgType = TypeMappings.GetPgType(MemberType); }
public DuplicatedField(EnumStorage enumStorage, IField innerField, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) { InnerField = innerField; MemberName = InnerField.Members.Select(x => x.Name).Join(""); NotNull = notNull; ColumnName = MemberName.ToTableAlias(); this.useTimestampWithoutTimeZoneForDateTime = useTimestampWithoutTimeZoneForDateTime; PgType = TypeMappings.GetPgType(FieldType, enumStorage); if (FieldType.IsEnum) { if (enumStorage == EnumStorage.AsString) { DbType = NpgsqlDbType.Varchar; PgType = "varchar"; _parseObject = expression => { var raw = expression.Value(); if (raw == null) { return(null); } return(Enum.GetName(FieldType, raw)); }; } else { DbType = NpgsqlDbType.Integer; PgType = "integer"; } } else if (FieldType.IsDateTime()) { PgType = this.useTimestampWithoutTimeZoneForDateTime ? "timestamp without time zone" : "timestamp with time zone"; DbType = this.useTimestampWithoutTimeZoneForDateTime ? NpgsqlDbType.Timestamp : NpgsqlDbType.TimestampTz; } else if (FieldType == typeof(DateTimeOffset) || FieldType == typeof(DateTimeOffset?)) { PgType = "timestamp with time zone"; DbType = NpgsqlDbType.TimestampTz; } else { DbType = TypeMappings.ToDbType(FieldType); } }
protected IField resolveField(MemberInfo[] members) { foreach (var source in _options.FieldSources) { if (source.TryResolve(_dataLocator, _options, _serializer, _documentType, members, out var field)) { return(field); } } var fieldType = members.Last().GetMemberType(); if (fieldType == typeof(string)) { return(new StringField(_dataLocator, _serializer.Casing, members)); } if (fieldType.IsEnum) { return(_serializer.EnumStorage == EnumStorage.AsInteger ? (IField) new EnumAsIntegerField(_dataLocator, _serializer.Casing, members) : new EnumAsStringField(_dataLocator, _serializer.Casing, members)); } if (fieldType == typeof(DateTime) || fieldType == typeof(DateTime?)) { return(new DateTimeField(_dataLocator, _options.DatabaseSchemaName, _serializer.Casing, members)); } if (fieldType == typeof(DateTimeOffset) || fieldType == typeof(DateTimeOffset?)) { return(new DateTimeOffsetField(_dataLocator, _options.DatabaseSchemaName, _serializer.Casing, members)); } var pgType = TypeMappings.GetPgType(fieldType, _serializer.EnumStorage); if (pgType.IsNotEmpty()) { if (fieldType.IsArray || fieldType.Closes(typeof(IList <>))) { return(new ArrayField(_dataLocator, pgType, _serializer.Casing, members)); } return(new SimpleCastField(_dataLocator, pgType, _serializer.Casing, members)); } throw new NotSupportedException($"Marten does not support Linq expressions for this member. Was {_documentType.FullName}.{members.Select(x => x.Name).Join(".")}"); }
protected Field(EnumStorage enumStorage, MemberInfo[] members, bool notNull = false) { Members = members; MemberName = members.Select(x => x.Name).Join(""); MemberType = members.Last().GetMemberType(); PgType = TypeMappings.GetPgType(MemberType, enumStorage); _enumStorage = enumStorage; NotNull = notNull; }
public void add_type_by_dotnet_type_and_name() { var table = new Table("mytable"); table.AddColumn <int>("number"); var column = table.Columns.Single(); column .Type.ShouldBe(TypeMappings.GetPgType(typeof(int), EnumStorage.AsInteger)); table.Columns.ShouldContain(column); }
public DocumentTable(DocumentMapping mapping) : base(mapping.Table) { // validate to ensure document has an Identity field or property mapping.Validate(); var pgIdType = TypeMappings.GetPgType(mapping.IdMember.GetMemberType()); var pgTextType = TypeMappings.GetPgType(string.Empty.GetType()); var idColumn = new TableColumn("id", pgIdType); if (mapping.TenancyStyle == TenancyStyle.Conjoined) { AddPrimaryKeys(new List <TableColumn> { idColumn, new TenantIdColumn() }); Indexes.Add(new IndexDefinition(mapping, TenantIdColumn.Name)); } else { AddPrimaryKey(idColumn); } AddColumn("data", "jsonb", "NOT NULL"); AddColumn <LastModifiedColumn>(); AddColumn <VersionColumn>(); AddColumn <DotNetTypeColumn>(); foreach (var field in mapping.DuplicatedFields) { AddColumn(new DuplicatedFieldColumn(field)); } if (mapping.IsHierarchy()) { AddColumn(new DocumentTypeColumn(mapping)); } if (mapping.DeleteStyle == DeleteStyle.SoftDelete) { AddColumn <DeletedColumn>(); Indexes.Add(new IndexDefinition(mapping, DocumentMapping.DeletedColumn)); AddColumn <DeletedAtColumn>(); } Indexes.AddRange(mapping.Indexes); ForeignKeys.AddRange(mapping.ForeignKeys); }
private IField createFieldByFieldType(MemberInfo[] members, Type fieldType) { if (fieldType == typeof(string)) { return(new StringField(_dataLocator, _serializer.Casing, members)); } if (fieldType.Closes(typeof(IDictionary <,>))) { return(new DictionaryField(_dataLocator, _serializer.Casing, _serializer.EnumStorage, members)); } if (fieldType.IsEnum) { return(_serializer.EnumStorage == EnumStorage.AsInteger ? (IField) new EnumAsIntegerField(_dataLocator, _serializer.Casing, members) : new EnumAsStringField(_dataLocator, _serializer.Casing, members)); } if (fieldType == typeof(DateTime)) { return(new DateTimeField(_dataLocator, _options.DatabaseSchemaName, _serializer.Casing, members)); } if (fieldType == typeof(DateTimeOffset)) { return(new DateTimeOffsetField(_dataLocator, _options.DatabaseSchemaName, _serializer.Casing, members)); } var pgType = TypeMappings.GetPgType(fieldType, _serializer.EnumStorage); if (fieldType.Closes(typeof(IDictionary <,>))) { return(new SimpleCastField(_dataLocator, "JSONB", _serializer.Casing, members)); } if (isEnumerable(fieldType)) { return(new ArrayField(_dataLocator, pgType, _serializer, members)); } if (pgType.IsNotEmpty()) { return(new SimpleCastField(_dataLocator, pgType, _serializer.Casing, members)); } throw new NotSupportedException( $"Marten does not support Linq expressions for this member. Was {_documentType.FullName}.{members.Select(x => x.Name).Join(".")}"); }
public TableDefinition StorageTable() { var pgIdType = TypeMappings.GetPgType(_mapping.IdMember.GetMemberType()); var table = new TableDefinition(_mapping.Table, new TableColumn("id", pgIdType)); table.Columns.Add(new TableColumn("data", "jsonb") { Directive = "NOT NULL" }); table.Columns.Add(new TableColumn(DocumentMapping.LastModifiedColumn, "timestamp with time zone") { Directive = "DEFAULT transaction_timestamp()" }); table.Columns.Add(new TableColumn(DocumentMapping.VersionColumn, "uuid") { Directive = "NOT NULL default(md5(random()::text || clock_timestamp()::text)::uuid)" }); table.Columns.Add(new TableColumn(DocumentMapping.DotNetTypeColumn, "varchar")); _mapping.DuplicatedFields.Select(x => x.ToColumn()).Each(x => table.Columns.Add(x)); if (_mapping.IsHierarchy()) { table.Columns.Add(new TableColumn(DocumentMapping.DocumentTypeColumn, "varchar") { Directive = $"DEFAULT '{_mapping.AliasFor(_mapping.DocumentType)}'" }); } if (_mapping.DeleteStyle == DeleteStyle.SoftDelete) { table.Columns.Add(new TableColumn(DocumentMapping.DeletedColumn, "boolean") { Directive = "DEFAULT FALSE" }); table.Columns.Add(new TableColumn(DocumentMapping.DeletedAtColumn, "timestamp with time zone") { Directive = "NULL" }); } return(table); }
public ArrayField(string dataLocator, string pgType, Casing casing, MemberInfo[] members) : base(dataLocator, pgType, casing, members) { var rawLocator = RawLocator; RawLocator = $"CAST({rawLocator} as jsonb)"; if (PgType == "jsonb[]") { PgType = "jsonb"; } TypedLocator = $"CAST({rawLocator} as {PgType})"; var collectionType = members.Last().GetMemberType(); var elementType = collectionType.DetermineElementType(); var innerPgType = TypeMappings.GetPgType(elementType, EnumStorage.AsInteger); LocatorForIncludedDocumentId = $"unnest(CAST(ARRAY(SELECT jsonb_array_elements_text(CAST({rawLocator} as jsonb))) as {innerPgType}[]))"; }
public virtual TableDefinition ToTable(IDocumentSchema schema) // take in schema so that you // can do foreign keys { var pgIdType = TypeMappings.GetPgType(IdMember.GetMemberType()); var table = new TableDefinition(TableName, new TableColumn("id", pgIdType)); table.Columns.Add(new TableColumn("data", "jsonb") { Directive = "NOT NULL" }); _fields.Values.OfType <DuplicatedField>().Select(x => x.ToColumn(schema)).Each(x => table.Columns.Add(x)); if (IsHierarchy()) { table.Columns.Add(new TableColumn(DocumentTypeColumn, "varchar")); } return(table); }
public ArrayField(string dataLocator, string pgType, ISerializer serializer, MemberInfo[] members) : base(dataLocator, pgType, serializer.Casing, members) { var rawLocator = RawLocator; RawLocator = $"CAST({rawLocator} as jsonb)"; var collectionType = members.Last().GetMemberType(); ElementType = collectionType.DetermineElementType(); var innerPgType = TypeMappings.GetPgType(ElementType, EnumStorage.AsInteger); if (TypeMappings.HasTypeMapping(ElementType)) { PgType = innerPgType + "[]"; } if (PgType == "jsonb[]") { PgType = "jsonb"; } TypedLocator = $"CAST({rawLocator} as {PgType})"; LocatorForIncludedDocumentId = $"unnest(CAST(ARRAY(SELECT jsonb_array_elements_text(CAST({rawLocator} as jsonb))) as {innerPgType}[]))"; if (PgType.EqualsIgnoreCase("JSONB")) { LocatorForFlattenedElements = $"unnest(CAST(ARRAY(SELECT jsonb_array_elements(CAST({rawLocator} as jsonb))) as jsonb[]))"; } else { LocatorForFlattenedElements = LocatorForIncludedDocumentId; } }
public override ISqlFragment CreateComparison(string op, ConstantExpression value, Expression memberExpression) { var key = memberExpression.As <MethodCallExpression>().Arguments[0].As <ConstantExpression>().Value; var locator = $"{RawLocator.Replace("->>", "->")} ->> '{key}'"; if (value.Value == null) { return(op == "=" ? (ISqlFragment) new IsNullFilter(this) : new IsNotNullFilter(this)); } else { if (_valueIsObject) { var pgType = TypeMappings.GetPgType(value.Value.GetType(), _enumStorage); locator = $"CAST({locator} as {pgType})"; } } var def = new CommandParameter(value); return(new ComparisonFilter(new WhereFragment(locator), def, op)); }
public static string ToLocator(ISerializer serializer) { return($"CAST(data as {TypeMappings.GetPgType(typeof(T), serializer.EnumStorage)})"); }
public void execute_get_pg_type_default_mappings_resolve() { TypeMappings.GetPgType(typeof(long), EnumStorage.AsString).ShouldBe("bigint"); TypeMappings.GetPgType(typeof(DateTime), EnumStorage.AsString).ShouldBe("timestamp without time zone"); }
public UpsertFunction(DocumentMapping mapping, DbObjectName identifier = null, bool disableConcurrency = false) : base(identifier ?? mapping.UpsertFunction) { _mapping = mapping; _disableConcurrency = disableConcurrency; if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _tableName = mapping.TableName; // TODO -- it'd be nice to not need this here. var table = new DocumentTable(mapping); if (table.PrimaryKeys.Count > 1) { _primaryKeyConstraintName = mapping.TableName.Name + "_pkey"; } else { _primaryKeyConstraintName = "pk_" + mapping.TableName.Name; } var idType = mapping.IdMember.GetMemberType(); var pgIdType = TypeMappings.GetPgType(idType, mapping.EnumStorage); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Where(x => !x.OnlyForSearching).Select(x => x.UpsertArgument)); // TODO -- see the columns below if (mapping.Metadata.Version.Enabled) { Arguments.Add(new VersionArgument()); } if (mapping.Metadata.DotNetType.Enabled) { Arguments.Add(new DotNetTypeArgument()); } AddIfActive(mapping.Metadata.CorrelationId); AddIfActive(mapping.Metadata.CausationId); AddIfActive(mapping.Metadata.LastModifiedBy); AddIfActive(mapping.Metadata.Headers); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } if (mapping.UseOptimisticConcurrency) { Arguments.Add(new CurrentVersionArgument()); } if (mapping.TenancyStyle == TenancyStyle.Conjoined) { Arguments.Add(new TenantIdArgument()); _tenantWhereClause = $"{_tableName.QualifiedName}.{TenantIdColumn.Name} = {TenantIdArgument.ArgName}"; _andTenantWhereClause = $" and {_tenantWhereClause}"; } }
public IdColumn(DocumentMapping mapping) : base("id", TypeMappings.GetPgType(mapping.IdMember.GetMemberType(), mapping.EnumStorage)) { }