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);
        }
示例#2
0
        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));
        }
示例#3
0
        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();
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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 = "*"
            });
        }
示例#7
0
        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));
        }
示例#10
0
        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
            });
        }
示例#12
0
        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));
        }
示例#13
0
        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);
                }
            }
        }
示例#14
0
        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 = "*"
            });
        }
示例#15
0
        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);
                }
            }
        }
示例#16
0
        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);
        }
示例#17
0
        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));
        }
示例#18
0
        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);
        }
        public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType,
                                                                   IDocumentMapping aggregateMapping, MethodSlot slot)
        {
            if (slot.Method is ConstructorInfo)
            {
                return(new AggregateConstructorFrame(slot));
            }

            return(new CreateAggregateFrame(slot));
        }
示例#20
0
        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));
        }
示例#21
0
        // 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);
        }
示例#22
0
文件: Delete.cs 项目: Xamarui/marten
 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);
     }
 }
示例#23
0
        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);
        }
示例#24
0
        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));
        }
示例#25
0
文件: Delete.cs 项目: nieve/marten
 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);
             }
         }
     }
 }
示例#28
0
        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));
        }
示例#29
0
        // 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);
        }
示例#30
0
 /// <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]);
 }
示例#31
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());
        }
示例#32
0
        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);
            }
        }
示例#33
0
        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);
            }
        }
        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);
            }


        }
示例#36
0
        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);
            }
        }
示例#37
0
        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();
        }
示例#38
0
        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;
        }
示例#39
0
        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();
        }
示例#40
0
        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));
        }
示例#41
0
        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();
        }
示例#42
0
        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});");
        }
示例#43
0
        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();
        }
示例#44
0
        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();
        }
示例#45
0
        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();
        }
示例#46
0
        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>();
                });
        }
示例#47
0
        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();
        }
示例#48
0
 public static IDocumentStorage Build(IDocumentSchema schema, IDocumentMapping mapping)
 {
     return Build(schema, new[] {mapping}).Single();
 }
示例#49
0
        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);
        }
示例#50
0
        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);
        }
示例#51
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 _factory.GetStringList(sql, documentMapping.Table.Schema, documentMapping.Table.Name).ToArray();
        }
示例#52
0
 public DocumentQuery(IDocumentMapping mapping, QueryModel query, ISerializer serializer)
 {
     _mapping = mapping;
     _query = query;
     _parser = new MartenExpressionParser(this, serializer);
 }
示例#53
0
        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);
        }
示例#54
0
 public IWhereFragment Parse(IDocumentMapping mapping, ISerializer serializer, MethodCallExpression expression)
 {
     var value = expression.Arguments.Single().Value();
     return ContainmentWhereFragment.SimpleArrayContains(serializer, expression.Object, value);
 }
示例#55
0
        // 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'");
        }
示例#57
0
 public CompoundWhereFragment(MartenExpressionParser parser, IDocumentMapping mapping, string separator, IEnumerable<WhereClause> wheres)
 {
     _separator = separator;
     _children = wheres.Select(x => parser.ParseWhereFragment(mapping, x.Predicate)).ToArray();
 }
示例#58
0
 public WhereClauseVisitor(MartenExpressionParser parent, IDocumentMapping mapping)
 {
     _parent = parent;
     _mapping = mapping;
     _register.Push(x => _top = x);
 }
示例#59
0
        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

");
        }
示例#60
0
        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();
        }