public void AssembleTypes(GeneratedAssembly assembly, StoreOptions options) { assembly.Generation.Assemblies.Add(GetType().Assembly); assembly.Generation.Assemblies.Add(typeof(T).Assembly); assembly.Generation.Assemblies.AddRange(_applyMethods.ReferencedAssemblies()); assembly.Generation.Assemblies.AddRange(_createMethods.ReferencedAssemblies()); assembly.Generation.Assemblies.AddRange(_shouldDeleteMethods.ReferencedAssemblies()); assembly.Namespaces.Add("System"); assembly.Namespaces.Add("System.Linq"); _isAsync = _createMethods.IsAsync || _applyMethods.IsAsync; _aggregateMapping = options.Storage.FindMapping(typeof(T)); if (_aggregateMapping.IdMember == null) { throw new InvalidDocumentException( $"No identity property or field can be determined for the aggregate '{typeof(T).FullNameInCode()}', but one is required to be used as an aggregate in projections"); } buildLiveAggregationType(assembly); buildInlineAggregationType(assembly); }
private IWhereFragment buildSimpleWhereClause(IDocumentMapping mapping, BinaryExpression binary) { var op = _operators[binary.NodeType]; var value = Value(binary.Right); if (mapping.PropertySearching == PropertySearching.ContainmentOperator && binary.NodeType == ExpressionType.Equal && value != null) { return(new ContainmentWhereFragment(_serializer, binary)); } var jsonLocator = JsonLocator(mapping, binary.Left); if (value == null) { var sql = binary.NodeType == ExpressionType.NotEqual ? $"{jsonLocator} is not null" : $"{jsonLocator} is null"; return(new WhereFragment(sql)); } return(new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value)); }
public IWhereFragment ParseWhereFragment(IDocumentMapping mapping, Expression expression) { if (expression is BinaryExpression) { return(GetWhereFragment(mapping, expression.As <BinaryExpression>())); } if (expression.NodeType == ExpressionType.Call) { return(GetMethodCall(mapping, expression.As <MethodCallExpression>())); } if (expression is MemberExpression && expression.Type == typeof(bool)) { var locator = JsonLocator(mapping, expression.As <MemberExpression>()); return(new WhereFragment("{0} = True".ToFormat(locator), true)); } if (expression.NodeType == ExpressionType.Not) { return(GetNotWhereFragment(mapping, expression.As <UnaryExpression>().Operand)); } if (expression is SubQueryExpression) { return(GetWhereFragment(mapping, expression.As <SubQueryExpression>())); } throw new NotSupportedException(); }
protected override void assembleTypes(GeneratedAssembly assembly, StoreOptions options) { assembly.Rules.ReferenceTypes(GetType()); assembly.ReferenceAssembly(GetType().Assembly); assembly.ReferenceAssembly(typeof(T).Assembly); assembly.Rules.ReferenceTypes(_applyMethods.ReferencedTypes().ToArray()); assembly.Rules.ReferenceTypes(_createMethods.ReferencedTypes().ToArray()); assembly.Rules.ReferenceTypes(_shouldDeleteMethods.ReferencedTypes().ToArray()); // Walk the assembly dependencies for the projection and aggregate types, // and this will catch generic type argument dependencies as well. For GH-2061 assembly.Rules.ReferenceTypes(GetType(), typeof(T)); assembly.UsingNamespaces.Add("System"); assembly.UsingNamespaces.Add("System.Linq"); _isAsync = _createMethods.IsAsync || _applyMethods.IsAsync; _aggregateMapping = options.Storage.FindMapping(typeof(T)); if (_aggregateMapping.IdMember == null) { throw new InvalidDocumentException( $"No identity property or field can be determined for the aggregate '{typeof(T).FullNameInCode()}', but one is required to be used as an aggregate in projections"); } buildLiveAggregationType(assembly); buildInlineAggregationType(assembly); }
private IWhereFragment buildSimpleWhereClause(IDocumentMapping mapping, BinaryExpression binary) { var isValueExpressionOnRight = binary.Right.IsValueExpression(); var jsonLocatorExpression = isValueExpressionOnRight ? binary.Left : binary.Right; var valuExpression = isValueExpressionOnRight ? binary.Right : binary.Left; var op = _operators[binary.NodeType]; var value = valuExpression.Value(); if (mapping.PropertySearching == PropertySearching.ContainmentOperator && binary.NodeType == ExpressionType.Equal && value != null) { return new ContainmentWhereFragment(_serializer, binary); } var jsonLocator = mapping.JsonLocator(jsonLocatorExpression); if (value == null) { var sql = binary.NodeType == ExpressionType.NotEqual ? $"({jsonLocator}) is not null" : $"({jsonLocator}) is null"; return new WhereFragment(sql); } if (jsonLocatorExpression.NodeType == ExpressionType.Modulo) { var moduloByValue = GetModuloByValue(binary); return new WhereFragment("{0} % {1} {2} ?".ToFormat(jsonLocator, moduloByValue, op), value); } return new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value); }
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 = "*" }); }
private IWhereFragment buildSimpleWhereClause(IDocumentMapping mapping, BinaryExpression binary) { var isValueExpressionOnRight = IsValueExpression(binary.Right); var jsonLocatorExpression = isValueExpressionOnRight ? binary.Left : binary.Right; var valuExpression = isValueExpressionOnRight ? binary.Right : binary.Left; var op = _operators[binary.NodeType]; var value = Value(valuExpression); if (mapping.PropertySearching == PropertySearching.ContainmentOperator && binary.NodeType == ExpressionType.Equal && value != null) { return(new ContainmentWhereFragment(_serializer, binary)); } var jsonLocator = JsonLocator(mapping, jsonLocatorExpression); if (value == null) { var sql = binary.NodeType == ExpressionType.NotEqual ? $"({jsonLocator}) is not null" : $"({jsonLocator}) is null"; return(new WhereFragment(sql)); } if (jsonLocatorExpression.NodeType == ExpressionType.Modulo) { var moduloByValue = GetModuloByValue(binary); return(new WhereFragment("{0} % {1} {2} ?".ToFormat(jsonLocator, moduloByValue, op), value)); } return(new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value)); }
public EntityMetadataQueryHandler(object entity, IDocumentStorage storage, IDocumentMapping mapping) { _id = storage.Identity(entity); _storage = storage; _mapping = mapping; var fieldIndex = 0; _fields = new Dictionary <string, int> { { DocumentMapping.VersionColumn, fieldIndex++ }, { DocumentMapping.LastModifiedColumn, fieldIndex++ }, { DocumentMapping.DotNetTypeColumn, fieldIndex++ } }; var queryableDocument = _mapping.ToQueryableDocument(); if (queryableDocument.SelectFields().Contains(DocumentMapping.DocumentTypeColumn)) { _fields.Add(DocumentMapping.DocumentTypeColumn, fieldIndex++); } if (queryableDocument.DeleteStyle == DeleteStyle.SoftDelete) { _fields.Add(DocumentMapping.DeletedColumn, fieldIndex++); _fields.Add(DocumentMapping.DeletedAtColumn, fieldIndex++); } if (_mapping.TenancyStyle == TenancyStyle.Conjoined) { _fields.Add(TenantIdColumn.Name, fieldIndex); } }
public void BuildApplyMethod(GeneratedType generatedType, IDocumentMapping aggregateMapping) { var returnType = IsAsync ? typeof(ValueTask <>).MakeGenericType(AggregateType) : AggregateType; var args = new[] { new Argument(typeof(IEvent), "@event"), new Argument(AggregateType, "aggregate"), new Argument(typeof(IQuerySession), "session") }; if (IsAsync) { args = args.Concat(new[] { new Argument(typeof(CancellationToken), "cancellation") }).ToArray(); } var method = new GeneratedMethod(MethodName, returnType, args); generatedType.AddMethod(method); var eventHandling = AddEventHandling(AggregateType, aggregateMapping, this); method.Frames.Add(eventHandling); method.Frames.Code("return {0};", new Use(AggregateType)); }
public IWhereFragment ParseWhereFragment(IDocumentMapping mapping, Expression expression) { if (expression is BinaryExpression) { return GetWhereFragment(mapping, expression.As<BinaryExpression>()); } if (expression.NodeType == ExpressionType.Call) { return GetMethodCall(mapping, expression.As<MethodCallExpression>()); } if (expression is MemberExpression && expression.Type == typeof (bool)) { var locator = JsonLocator(mapping, expression.As<MemberExpression>()); return new WhereFragment("{0} = True".ToFormat(locator), true); } if (expression.NodeType == ExpressionType.Not) { return GetNotWhereFragment(mapping, expression.As<UnaryExpression>().Operand); } if (expression is SubQueryExpression) { return GetWhereFragment(mapping, expression.As<SubQueryExpression>()); } throw new NotSupportedException(); }
public void BuildCreateMethod(GeneratedType generatedType, IDocumentMapping aggregateMapping) { var returnType = IsAsync ? typeof(ValueTask <>).MakeGenericType(AggregateType) : AggregateType; var args = new[] { new Argument(typeof(IEvent), "@event"), new Argument(typeof(IQuerySession), "session") }; if (IsAsync) { args = args.Concat(new[] { new Argument(typeof(CancellationToken), "cancellation") }).ToArray(); } var method = new GeneratedMethod(MethodName, returnType, args); method.AsyncMode = IsAsync ? AsyncMode.AsyncTask : AsyncMode.None; generatedType.AddMethod(method); var eventHandling = AddEventHandling(AggregateType, aggregateMapping, this); method.Frames.Add(eventHandling); method.Frames.Add(new DefaultAggregateConstruction(AggregateType, generatedType) { IfStyle = IfStyle.None }); }
private void buildSchemaObjectsIfNecessary(IDocumentMapping mapping) { Action <string> executeSql = sql => { try { _factory.RunSql(sql); _logger.SchemaChange(sql); } catch (Exception e) { throw new MartenSchemaException(mapping.DocumentType, sql, e); } }; var sortedMappings = new[] { mapping }.TopologicalSort(x => { var documentMapping = x as DocumentMapping; if (documentMapping == null) { return(Enumerable.Empty <IDocumentMapping>()); } return(documentMapping.ForeignKeys .Select(keyDefinition => keyDefinition.ReferenceDocumentType) .Select(MappingFor)); }); sortedMappings.Each( x => x.SchemaObjects.GenerateSchemaObjectsIfNecessary(StoreOptions.AutoCreateSchemaObjects, this, executeSql)); }
public static void Deserialize(this FramesCollection frames, IDocumentMapping mapping) { var documentType = mapping.DocumentType; var document = new Variable(documentType, DocumentVariableName); if (mapping is DocumentMapping d) { if (!d.IsHierarchy()) { frames.Code($@" {documentType.FullNameInCode()} document; BLOCK:using (var json = reader.GetTextReader(0)) document = _serializer.FromJson<{documentType.FullNameInCode()}>(json); END ").Creates(document); } else { // Hierarchy path is different frames.Code($@" {documentType.FullNameInCode()} document; var typeAlias = reader.GetFieldValue<string>(2); BLOCK:using (var json = reader.GetTextReader(0)) document = ({documentType.FullNameInCode()}) _serializer.FromJson(_mapping.TypeFor(typeAlias), json); END ").Creates(document); } } }
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 static void DeserializeAsync(this FramesCollection frames, IDocumentMapping mapping) { var documentType = mapping.DocumentType; var document = new Variable(documentType, DocumentVariableName); if (mapping is DocumentMapping d) { if (!d.IsHierarchy()) { frames.Code($@" {documentType.FullNameInCode()} document; BLOCK:using (var json = reader.GetTextReader(0)) document = _serializer.FromJson<{documentType.FullNameInCode()}>(json); END ").Creates(document); } else { frames.CodeAsync($@" {documentType.FullNameInCode()} document; var typeAlias = await reader.GetFieldValueAsync<string>(2, {{0}}).ConfigureAwait(false); BLOCK:using (var json = reader.GetTextReader(0)) document = ({documentType.FullNameInCode()}) _serializer.FromJson(_mapping.TypeFor(typeAlias), json); END ", Use.Type <CancellationToken>()).Creates(document); } } }
public void CreateSchema(IDocumentSchema schema, IDocumentMapping mapping) { var className = nameof(StoreOptions); var propName = nameof(StoreOptions.AutoCreateSchemaObjects); string message = $"No document storage exists for type {mapping.DocumentType.FullName} and cannot be created dynamically unless the {className}.{propName} = true. See http://jasperfx.github.io/marten/documentation/documents/ for more information"; throw new InvalidOperationException(message); }
private IEnumerable <TableColumn> findTableColumns(IDocumentMapping documentMapping) { Func <DbDataReader, TableColumn> transform = r => new TableColumn(r.GetString(0), r.GetString(1)); var sql = "select column_name, data_type from information_schema.columns where table_schema = ? and table_name = ? order by ordinal_position"; return(_tenant.Fetch(sql, transform, documentMapping.Table.Schema, documentMapping.Table.Name)); }
public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType, IDocumentMapping aggregateMapping, MethodSlot slot) { if (slot.Method is ConstructorInfo) { return(new AggregateConstructorFrame(slot)); } return(new CreateAggregateFrame(slot)); }
public IWhereFragment Parse(IDocumentMapping mapping, ISerializer serializer, MethodCallExpression expression) { var locator = GetLocator(mapping, expression); var value = expression.Arguments.OfType<ConstantExpression>().FirstOrDefault(); if (value == null) throw new BadLinqExpressionException("Could not extract string value from {0}.".ToFormat(expression), null); var stringOperator = GetOperator(expression); return new WhereFragment("{0} {1} ?".ToFormat(locator, stringOperator), FormatValue(expression.Method, value.Value as string)); }
// TODO -- use the mapping off of DocumentQuery later public string JsonLocator(IDocumentMapping mapping, Expression expression) { var visitor = new FindMembers(); visitor.Visit(expression); var field = mapping.FieldFor(visitor.Members); return(field.SqlLocator); }
public void Configure(MartenExpressionParser parser, IDocumentStorage storage, IDocumentMapping mapping, UpdateBatch batch) { if (Where == null) { batch.Delete(mapping.Table, Id, storage.IdType); } else { batch.DeleteWhere(mapping.Table, Where); } }
public IWhereFragment Parse(IDocumentMapping mapping, ISerializer serializer, MethodCallExpression expression) { var finder = new FindMembers(); finder.Visit(expression); var members = finder.Members; var locator = mapping.FieldFor(members).SqlLocator; var values = expression.Object.Value(); return new WhereFragment($"{locator} = ANY(?)", values); }
private bool shouldRegenerate(IDocumentMapping mapping) { if (!DocumentTables().Contains(mapping.TableName)) { return(true); } var existing = TableSchema(mapping.TableName); var expected = mapping.ToTable(this); return(!expected.Equals(existing)); }
public void Configure(MartenExpressionParser parser, IDocumentStorage storage, IDocumentMapping mapping, UpdateBatch batch) { if (Query == null) { batch.Delete(mapping.QualifiedTableName, Id, storage.IdType); } else { var where = Query.BuildWhereClause(); batch.DeleteWhere(mapping.QualifiedTableName, where); } }
public void CreateSchema(IDocumentSchema schema, IDocumentMapping mapping, Func <bool> shouldRegenerate) { if (shouldRegenerate()) { lock (_lock) { if (shouldRegenerate()) { writeSchemaObjects(schema, mapping); } } } }
public void CreateSchema(IDocumentSchema schema, IDocumentMapping mapping, Func<bool> shouldRegenerate) { if (shouldRegenerate()) { lock (_lock) { if (shouldRegenerate()) { writeSchemaObjects(schema, mapping); } } } }
public TableDefinition TableSchema(IDocumentMapping documentMapping) { var columns = findTableColumns(documentMapping); if (!columns.Any()) { return(null); } var pkName = primaryKeysFor(documentMapping).SingleOrDefault(); return(new TableDefinition(documentMapping.Table, pkName, columns)); }
// TODO -- use the mapping off of DocumentQuery later public string JsonLocator(IDocumentMapping mapping, Expression expression) { var visitor = new FindMembers(); visitor.Visit(expression); //return new JsonLocatorField(visitor.Members.ToArray()).SqlLocator; var field = mapping.FieldFor(visitor.Members); _query.RegisterField(field); return(field.SqlLocator); }
/// <summary> /// Returns a locator for the member being queried upon /// </summary> /// <param name="mapping"></param> /// <param name="expression"></param> /// <returns></returns> protected virtual string GetLocator(IDocumentMapping mapping, MethodCallExpression expression) { if (!expression.Method.IsStatic && expression.Object != null && expression.Object.NodeType != ExpressionType.Constant) { // x.member.Equals(...) return mapping.JsonLocator(expression.Object); } if (expression.Arguments[0].NodeType == ExpressionType.Constant) { // string.Equals("value", x.member) return mapping.JsonLocator(expression.Arguments[1]); } // string.Equals(x.member, "value") return mapping.JsonLocator(expression.Arguments[0]); }
private string[] primaryKeysFor(IDocumentMapping documentMapping) { var sql = @" select a.attname, format_type(a.atttypid, a.atttypmod) as data_type from pg_index i join pg_attribute a on a.attrelid = i.indrelid and a.attnum = ANY(i.indkey) where attrelid = (select pg_class.oid from pg_class join pg_catalog.pg_namespace n ON n.oid = pg_class.relnamespace where n.nspname = ? and relname = ?) and i.indisprimary; "; return(_tenant.GetStringList(sql, documentMapping.Table.Schema, documentMapping.Table.Name).ToArray()); }
public void CreateSchema(IDocumentSchema schema, IDocumentMapping mapping) { var writer= new StringWriter(); SchemaBuilder.WriteSchemaObjects(mapping, schema, writer); var sql = writer.ToString(); try { _runner.Execute(sql); } catch (Exception e) { throw new MartenSchemaException(mapping.DocumentType, sql, e); } }
private static void writeBasicSql(CommandBuilder sql, IDocumentMapping mapping, TransformFunction transform) { var version = CombGuidIdGeneration.NewGuid(); sql.Append("update "); sql.Append(mapping.Table.QualifiedName); sql.Append(" as d set data = "); sql.Append(transform.Identifier.QualifiedName); sql.Append("(data), "); sql.Append(DocumentMapping.LastModifiedColumn); sql.Append(" = (now() at time zone 'utc'), "); sql.Append(DocumentMapping.VersionColumn); sql.Append(" = '"); sql.Append(version); sql.Append("'"); }
private void writeSchemaObjects(IDocumentSchema schema, IDocumentMapping mapping) { var writer = new StringWriter(); SchemaBuilder.WriteSchemaObjects(mapping, schema, writer); var sql = writer.ToString(); try { _factory.RunSql(sql); } catch (Exception e) { throw new MartenSchemaException(mapping.DocumentType, sql, e); } }
public void CreateSchema(IDocumentSchema schema, IDocumentMapping mapping) { var writer = new StringWriter(); SchemaBuilder.WriteSchemaObjects(mapping, schema, writer); var sql = writer.ToString(); try { _runner.Execute(sql); } catch (Exception e) { throw new MartenSchemaException(mapping.DocumentType, sql, e); } }
private IWhereFragment GetMethodCall(IDocumentMapping mapping, MethodCallExpression expression) { // TODO -- generalize this mess if (expression.Method.Name == CONTAINS) { var @object = expression.Object; if (@object.Type == typeof(string)) { var locator = JsonLocator(mapping, @object); var value = Value(expression.Arguments.Single()).As <string>(); return(new WhereFragment("{0} like ?".ToFormat(locator), "%" + value + "%")); } if (@object.Type.IsGenericEnumerable()) { var value = Value(expression.Arguments.Single()); return(ContainmentWhereFragment.SimpleArrayContains(_serializer, @object, value)); } } if (expression.Method.Name == STARTS_WITH) { var @object = expression.Object; if (@object.Type == typeof(string)) { var locator = JsonLocator(mapping, @object); var value = Value(expression.Arguments.Single()).As <string>(); return(new WhereFragment("{0} like ?".ToFormat(locator), value + "%")); } } if (expression.Method.Name == ENDS_WITH) { var @object = expression.Object; if (@object.Type == typeof(string)) { var locator = JsonLocator(mapping, @object); var value = Value(expression.Arguments.Single()).As <string>(); return(new WhereFragment("{0} like ?".ToFormat(locator), "%" + value)); } } throw new NotImplementedException(); }
public IWhereFragment ParseWhereFragment(IDocumentMapping mapping, Expression expression) { if (expression is LambdaExpression) { expression = expression.As<LambdaExpression>().Body; } var visitor = new WhereClauseVisitor(this, mapping); visitor.Visit(expression); var whereFragment = visitor.ToWhereFragment(); if (whereFragment == null) { throw new NotSupportedException("Marten does not (yet) support this Linq query type"); } return whereFragment; }
public static void WriteSchemaObjects(IDocumentMapping mapping, IDocumentSchema schema, StringWriter writer) { var table = mapping.ToTable(schema); table.Write(writer); writer.WriteLine(); writer.WriteLine(); mapping.ToUpsertFunction().WriteFunctionSql(schema?.UpsertType ?? PostgresUpsertType.Legacy, writer); mapping.Indexes.Each(x => { writer.WriteLine(); writer.WriteLine(x.ToDDL()); }); writer.WriteLine(); writer.WriteLine(); }
private void buildSchemaObjectsIfNecessary(IDocumentMapping mapping) { var sortedMappings = new[] { mapping }.TopologicalSort(x => { var documentMapping = x as DocumentMapping; if (documentMapping == null) { return(Enumerable.Empty <IDocumentMapping>()); } return(documentMapping.ForeignKeys .Select(keyDefinition => keyDefinition.ReferenceDocumentType) .Select(MappingFor)); }); sortedMappings.Each( x => x.SchemaObjects.GenerateSchemaObjectsIfNecessary(StoreOptions.AutoCreateSchemaObjects, this, this)); }
private static string GenerateViewCommand(IDocumentMapping mapping) { var selectFields = new List <string>(); var tableFields = new List <string>(); foreach (var prop in mapping.DocumentType.GetProperties()) { var propType = prop.PropertyType; var propName = prop.Name; var jsonProp = prop.GetCustomAttributes(typeof(JsonPropertyAttribute)).FirstOrDefault() as JsonPropertyAttribute; if (!string.IsNullOrEmpty(jsonProp?.PropertyName)) { propName = jsonProp.PropertyName; } if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable <>)) { propType = propType.GetGenericArguments().Single(); } var propColumn = GetPropertyColumnType(propType); if (!string.IsNullOrEmpty(propColumn)) { tableFields.Add($"\"{propName}\" {propColumn}"); selectFields.Add($"x.\"{propName}\" as {ToSnakeCase(propName)}"); } } if (tableFields.Count == 0) { return(null); } var table = mapping.Table.Name; var selectList = string.Join(", ", selectFields); var tableList = string.Join(", ", tableFields); return($@"DROP VIEW IF EXISTS {table}_vw; CREATE VIEW {table}_vw AS SELECT {selectList} FROM {table}, jsonb_to_record(data) AS x({tableList});"); }
private IWhereFragment GetWhereFragment(IDocumentMapping mapping, SubQueryExpression expression) { var queryType = expression.QueryModel.MainFromClause.ItemType; if (TypeMappings.HasTypeMapping(queryType)) { var contains = expression.QueryModel.ResultOperators.OfType<ContainsResultOperator>().FirstOrDefault(); if (contains != null) { return ContainmentWhereFragment.SimpleArrayContains(_serializer, expression.QueryModel.MainFromClause.FromExpression, Value(contains.Item)); } } if (expression.QueryModel.ResultOperators.Any(x => x is AnyResultOperator)) { return new CollectionAnyContainmentWhereFragment(_serializer, expression); } throw new NotImplementedException(); }
private IWhereFragment GetWhereFragment(IDocumentMapping mapping, SubQueryExpression expression) { var queryType = expression.QueryModel.MainFromClause.ItemType; if (TypeMappings.HasTypeMapping(queryType)) { var contains = expression.QueryModel.ResultOperators.OfType <ContainsResultOperator>().FirstOrDefault(); if (contains != null) { return(ContainmentWhereFragment.SimpleArrayContains(_serializer, expression.QueryModel.MainFromClause.FromExpression, Value(contains.Item))); } } if (expression.QueryModel.ResultOperators.Any(x => x is AnyResultOperator)) { return(new CollectionAnyContainmentWhereFragment(_serializer, expression)); } throw new NotImplementedException(); }
public IWhereFragment GetWhereFragment(IDocumentMapping mapping, BinaryExpression binary) { if (_operators.ContainsKey(binary.NodeType)) { return(buildSimpleWhereClause(mapping, binary)); } switch (binary.NodeType) { case ExpressionType.AndAlso: return(new CompoundWhereFragment("and", ParseWhereFragment(mapping, binary.Left), ParseWhereFragment(mapping, binary.Right))); case ExpressionType.OrElse: return(new CompoundWhereFragment("or", ParseWhereFragment(mapping, binary.Left), ParseWhereFragment(mapping, binary.Right))); } throw new NotSupportedException(); }
public static IEnumerable<IDocumentStorage> Build(IDocumentSchema schema, IDocumentMapping[] mappings) { // Generate the actual source code var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); // Tell the generator which other assemblies that it should be referencing // for the compilation generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType<NpgsqlConnection>(); generator.ReferenceAssemblyContainingType<QueryModel>(); generator.ReferenceAssemblyContainingType<DbCommand>(); generator.ReferenceAssemblyContainingType<Component>(); generator.ReferenceAssemblyContainingType<DbDataReader>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); // build the new assembly -- this will blow up if there are any // compilation errors with the list of errors and the actual code var assembly = generator.Generate(code); return assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf<IDocumentStorage>()) .Select(x => { var docType = x.FindInterfaceThatCloses(typeof (IdAssignment<>)).GetGenericArguments().Single(); var mapping = mappings.Single(m => m.DocumentType == docType); var arguments = mapping.ToArguments().Select(arg => arg.GetValue(schema)).ToArray(); var ctor = x.GetConstructors().Single(); return ctor.Invoke(arguments).As<IDocumentStorage>(); }); }
public static string GenerateDocumentStorageCode(IDocumentMapping[] mappings) { var writer = new SourceWriter(); // TODO -- get rid of the magic strings var namespaces = new List<string> { "System", "Marten", "Marten.Schema", "Marten.Services", "Marten.Linq", "Marten.Util", "Npgsql", "Remotion.Linq", typeof (NpgsqlDbType).Namespace, typeof (IEnumerable<>).Namespace, typeof(DbDataReader).Namespace, typeof(CancellationToken).Namespace, typeof(Task).Namespace }; namespaces.AddRange(mappings.Select(x => x.DocumentType.Namespace)); namespaces.Distinct().OrderBy(x => x).Each(x => writer.WriteLine($"using {x};")); writer.BlankLine(); writer.StartNamespace("Marten.GeneratedCode"); mappings.Each(x => { GenerateDocumentStorage(x, writer); writer.BlankLine(); writer.BlankLine(); }); writer.FinishBlock(); return writer.Code(); }
public static IDocumentStorage Build(IDocumentSchema schema, IDocumentMapping mapping) { return Build(schema, new[] {mapping}).Single(); }
public TableDefinition TableSchema(IDocumentMapping documentMapping) { var columns = findTableColumns(documentMapping); if (!columns.Any()) return null; var pkName = primaryKeysFor(documentMapping).SingleOrDefault(); return new TableDefinition(documentMapping.Table, pkName, columns); }
private IEnumerable<TableColumn> findTableColumns(IDocumentMapping documentMapping) { Func<DbDataReader, TableColumn> transform = r => new TableColumn(r.GetString(0), r.GetString(1)); var sql = "select column_name, data_type from information_schema.columns where table_schema = ? and table_name = ? order by ordinal_position"; return _factory.Fetch(sql, transform, documentMapping.Table.Schema, documentMapping.Table.Name); }
private string[] primaryKeysFor(IDocumentMapping documentMapping) { var sql = @" select a.attname, format_type(a.atttypid, a.atttypmod) as data_type from pg_index i join pg_attribute a on a.attrelid = i.indrelid and a.attnum = ANY(i.indkey) where attrelid = (select pg_class.oid from pg_class join pg_catalog.pg_namespace n ON n.oid = pg_class.relnamespace where n.nspname = ? and relname = ?) and i.indisprimary; "; return _factory.GetStringList(sql, documentMapping.Table.Schema, documentMapping.Table.Name).ToArray(); }
public DocumentQuery(IDocumentMapping mapping, QueryModel query, ISerializer serializer) { _mapping = mapping; _query = query; _parser = new MartenExpressionParser(this, serializer); }
private IWhereFragment buildSimpleWhereClause(IDocumentMapping mapping, BinaryExpression binary) { var op = _operators[binary.NodeType]; var value = Value(binary.Right); if (mapping.PropertySearching == PropertySearching.ContainmentOperator && binary.NodeType == ExpressionType.Equal && value != null) { return new ContainmentWhereFragment(_serializer, binary); } var jsonLocator = JsonLocator(mapping, binary.Left); if (value == null) { var sql = binary.NodeType == ExpressionType.NotEqual ? $"{jsonLocator} is not null" : $"{jsonLocator} is null"; return new WhereFragment(sql); } return new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value); }
public IWhereFragment Parse(IDocumentMapping mapping, ISerializer serializer, MethodCallExpression expression) { var value = expression.Arguments.Single().Value(); return ContainmentWhereFragment.SimpleArrayContains(serializer, expression.Object, value); }
// TODO -- use the mapping off of DocumentQuery later public string JsonLocator(IDocumentMapping mapping, Expression expression) { var visitor = new FindMembers(); visitor.Visit(expression); //return new JsonLocatorField(visitor.Members.ToArray()).SqlLocator; var field = mapping.FieldFor(visitor.Members); _query.RegisterField(field); return field.SqlLocator; }
public IWhereFragment Parse(IDocumentMapping mapping, ISerializer serializer, MethodCallExpression expression) { var locator = mapping.FieldFor(new MemberInfo[] {_property}).SqlLocator; return new WhereFragment($"{locator} = 'Blue'"); }
public CompoundWhereFragment(MartenExpressionParser parser, IDocumentMapping mapping, string separator, IEnumerable<WhereClause> wheres) { _separator = separator; _children = wheres.Select(x => parser.ParseWhereFragment(mapping, x.Predicate)).ToArray(); }
public WhereClauseVisitor(MartenExpressionParser parent, IDocumentMapping mapping) { _parent = parent; _mapping = mapping; _register.Push(x => _top = x); }
public static void GenerateDocumentStorage(IDocumentMapping mapping, SourceWriter writer) { var upsertFunction = mapping.ToUpsertFunction(); var id_NpgsqlDbType = TypeMappings.ToDbType(mapping.IdMember.GetMemberType()); var typeName = mapping.DocumentType.GetTypeName(); var storageArguments = mapping.ToArguments().ToArray(); var ctorArgs = storageArguments.Select(x => x.ToCtorArgument()).Join(", "); var ctorLines = storageArguments.Select(x => x.ToCtorLine()).Join("\n"); var fields = storageArguments.Select(x => x.ToFieldDeclaration()).Join("\n"); writer.Write( $@" BLOCK:public class {mapping.DocumentType.Name}Storage : IDocumentStorage, IBulkLoader<{typeName}>, IdAssignment<{typeName}>, IResolver<{typeName}> {fields} BLOCK:public {mapping.DocumentType.Name}Storage({ctorArgs}) {ctorLines} END public Type DocumentType => typeof ({typeName}); BLOCK:public NpgsqlCommand UpsertCommand(object document, string json) return UpsertCommand(({typeName})document, json); END BLOCK:public NpgsqlCommand LoaderCommand(object id) return new NpgsqlCommand(`select {mapping.SelectFields("d")} from {mapping.TableName} as d where id = :id`).With(`id`, id); END BLOCK:public NpgsqlCommand DeleteCommandForId(object id) return new NpgsqlCommand(`delete from {mapping.TableName} where id = :id`).With(`id`, id); END BLOCK:public NpgsqlCommand DeleteCommandForEntity(object entity) return DeleteCommandForId((({typeName})entity).{mapping.IdMember.Name}); END BLOCK:public NpgsqlCommand LoadByArrayCommand<T>(T[] ids) return new NpgsqlCommand(`select {mapping.SelectFields("d")} from {mapping.TableName} as d where id = ANY(:ids)`).With(`ids`, ids); END BLOCK:public void Remove(IIdentityMap map, object entity) var id = Identity(entity); map.Remove<{typeName}>(id); END BLOCK:public void Delete(IIdentityMap map, object id) map.Remove<{typeName}>(id); END BLOCK:public void Store(IIdentityMap map, object id, object entity) map.Store<{typeName}>(id, ({typeName})entity); END BLOCK:public object Assign({typeName} document) {mapping.IdStrategy.AssignmentBodyCode(mapping.IdMember)} return document.{mapping.IdMember.Name}; END BLOCK:public object Retrieve({typeName} document) return document.{mapping.IdMember.Name}; END BLOCK:public {typeName} Build(DbDataReader reader, ISerializer serializer) return serializer.FromJson<{typeName}>(reader.GetString(0)); END public NpgsqlDbType IdType => NpgsqlDbType.{id_NpgsqlDbType}; BLOCK:public object Identity(object document) return (({typeName})document).{mapping.IdMember.Name}; END BLOCK:public {typeName} Resolve(IIdentityMap map, ILoader loader, object id) return map.Get(id, () => loader.LoadDocument<{typeName}>(id)) as {typeName}; END BLOCK:public Task<{typeName}> ResolveAsync(IIdentityMap map, ILoader loader, CancellationToken token, object id) return map.GetAsync(id, (tk => loader.LoadDocumentAsync<{typeName}>(id, tk)), token).ContinueWith(x => x.Result as {typeName}, token); END {mapping.ToResolveMethod(typeName)} {upsertFunction.ToUpdateBatchMethod(typeName)} {upsertFunction.ToBulkInsertMethod(typeName)} END "); }
private IWhereFragment GetNotWhereFragment(IDocumentMapping mapping, Expression expression) { if (expression is MemberExpression && expression.Type == typeof (bool)) { var locator = JsonLocator(mapping, expression.As<MemberExpression>()); return new WhereFragment("({0})::Boolean = False".ToFormat(locator)); } if (expression.Type == typeof (bool) && expression.NodeType == ExpressionType.NotEqual && expression is BinaryExpression) { var binaryExpression = expression.As<BinaryExpression>(); var locator = JsonLocator(mapping, binaryExpression.Left); if (binaryExpression.Right.NodeType == ExpressionType.Constant && binaryExpression.Right.As<ConstantExpression>().Value == null) { return new WhereFragment($"({locator})::Boolean IS NULL"); } } throw new NotSupportedException(); }