Example #1
0
        public static (IEnumerable <StringBasedMappedProperty> property, IEnumerable <MappedTable> tables) BuildMap(
            BuildMapState state,
            MethodCallExpression caseExpression,
            MapType nextMap,
            string toPrefix = null)
        {
            var(isElse, elseResult) = IsElse(caseExpression);
            if (!isElse)
            {
                throw new InvalidOperationException("The method only handles sql case statements");
            }

            var(@else, tables) = ComplexMapBuilder.BuildMap(state, elseResult);
            var el = @else.ToArray();

            if (el.Length != 1)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression.Arguments[0]);
            }

            var(cases, tables2) = GetDslCases(state, caseExpression.Object);
            return(CompileCases(
                       state,
                       cases,
                       el[0],
                       tables.Concat(tables2),
                       caseExpression.Type,
                       toPrefix));
        }
Example #2
0
        static (IEnumerable <(StringBasedMappedProperty when, StringBasedMappedProperty then)> cases, StringBasedMappedProperty @else, IEnumerable <MappedTable> tables) GetCasesX(
            BuildMapState state,
            Expression expr)
        {
            var caseExpression = expr as ConditionalExpression;

            if (caseExpression == null)
            {
                var(elseP, elseTables) = ComplexMapBuilder.BuildMap(
                    state,
                    ReflectionUtils.RemoveConvert(expr));

                var elseProperties = elseP.ToArray();
                if (elseProperties.Length != 1)
                {
                    throw new SqlBuilderException(state.MappingPurpose, caseExpression);
                }

                return(CodingConstants.Empty.Case, elseProperties[0], elseTables);
            }

            var(ifP, ifTables) = ComplexMapBuilder.BuildMap(
                state,
                ReflectionUtils.RemoveConvert(caseExpression.Test));

            var ifProperties = ifP.ToArray();

            if (ifProperties.Length != 1)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression);
            }

            var(thenP, thenTables) = ComplexMapBuilder.BuildMap(
                state,
                ReflectionUtils.RemoveConvert(caseExpression.IfTrue));

            var thenProperties = thenP.ToArray();

            if (thenProperties.Length != 1)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression);
            }

            var(otherCases, @else, otherTables) = GetCasesX(
                state,
                ReflectionUtils.RemoveConvert(caseExpression.IfFalse));

            return(
                otherCases.Prepend((ifProperties[0], thenProperties[0])),
                @else,
                ifTables.Concat(thenTables).Concat(otherTables)
                );
        }
Example #3
0
        static (IEnumerable <(StringBasedMappedProperty when, StringBasedMappedProperty then)> cases, IEnumerable <MappedTable> tables) GetDslCases(
            BuildMapState state,
            Expression caseExpression)
        {
            if (caseExpression == null)
            {
                return(CodingConstants.Empty.Case, CodingConstants.Empty.MappedTable);
            }

            var thenObject = caseExpression as MethodCallExpression;

            if (thenObject == null)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression);
            }

            var(isThen, thenResult) = IsThen(thenObject);
            if (!isThen)
            {
                throw new SqlBuilderException(state.MappingPurpose, thenObject);
            }

            var whenObject = thenObject.Object as MethodCallExpression;

            if (whenObject == null)
            {
                throw new SqlBuilderException(state.MappingPurpose, thenObject.Object);
            }

            var(isWhen, whenCondition) = IsWhen(whenObject);
            if (!isWhen)
            {
                throw new SqlBuilderException(state.MappingPurpose, whenObject);
            }

            var(whenProperties, whenTables) = ComplexMapBuilder.BuildMap(state, whenCondition);
            var(thenProperties, thenTables) = ComplexMapBuilder.BuildMap(state, thenResult);

            var whenP = whenProperties.ToArray();
            var thenP = thenProperties.ToArray();

            if (whenP.Length != 1 || thenP.Length != 1)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression);
            }

            var(cases, tables) = GetDslCases(state, whenObject.Object);
            return(
                cases.Append((whenP[0], thenP[0])),
                tables.Concat(whenTables).Concat(thenTables)
                );
        }
Example #4
0
        public QueryElementBasedMappedProperty Convert(BuildMapState state)
        {
            var mappingContext = MappingContext
                                 .Select(x => state.WrappedSqlStatement.Tables[x])
                                 .ToArray();

            return(new QueryElementBasedMappedProperty(
                       FromParams.Convert(state),
                       To,
                       MappedPropertyType,
                       mappingContext,
                       PropertySegmentConstructors));
        }
Example #5
0
 public static (IEnumerable <StringBasedMappedProperty> property, IEnumerable <MappedTable> tables) BuildMap(
     BuildMapState state,
     ConditionalExpression caseExpression,
     string toPrefix = null)
 {
     var(cases, @else, tables) = GetCasesX(state, caseExpression);
     return(CompileCases(
                state,
                cases,
                @else,
                tables.Concat(tables),
                caseExpression.Type,
                toPrefix));
 }
Example #6
0
 static (IEnumerable <StringBasedMappedProperty> properties, IEnumerable <MappedTable> tables, bool isConstant) BuildMapWithErrorHandling(
     BuildMapState state,
     Expression expr,
     MapType nextMap,
     string toPrefix = null)
 {
     try
     {
         return(BuildMap(state, expr, nextMap, toPrefix));
     }
     catch (Exception e)
     {
         throw new SqlBuilderException(state.MappingPurpose, expr, e);
     }
 }
Example #7
0
        /// <summary>
        /// Compile the query into something which can be executed multiple times
        /// </summary>
        public static ICompiledQuery <TArgs, TMapped> Compile <TArgs, TResult, TMapped>(
            ISqlSyntax sqlSyntax,
            SqlExecutor <TArgs, TResult> query,
            LambdaExpression mapper,
            bool requiresPropertyUnwrap,
            ILogger logger)
        {
            var(wrappedBuilder, parameters) = query.ToSqlStatement();
            var wrappedStatement = new SqlStatement(wrappedBuilder);

            var argsParam = mapper.Parameters.Count > 1 ? mapper.Parameters[1] : null;
            var state     = new BuildMapState(query.PrimaryTableMember.memberName, parameters, mapper.Parameters[0], argsParam, wrappedStatement, query.SqlSyntax, true, MappingPurpose.Mapping);

            var(properties, tables) = MapBuilder.BuildMapFromRoot(state, mapper.Body);

            properties = properties.Enumerate();
            var statement = new MappedSelectStatement(properties, tables, wrappedStatement.Tables.First().PrimaryKey);
            var builder   = new MappedSqlStatementBuilder(state, properties, statement, wrappedBuilder, sqlSyntax);

            return(builder.Compile <TArgs, TMapped>(statement, parameters.Parameters, sqlSyntax, QueryParseType.ORM, requiresPropertyUnwrap));
        }
Example #8
0
        public static (IEnumerable <StringBasedMappedProperty> property, IEnumerable <MappedTable> tables) BuildMap(
            BuildMapState state,
            MethodCallExpression caseExpression,
            MapType nextMap,
            string toPrefix = null)
        {
            var(isElse, elseResult) = IsElse(caseExpression);
            if (!isElse)
            {
                throw new InvalidOperationException("The method only handles sql case statements");
            }

            var(@else, tables) = ComplexMapBuilder.BuildMap(state, elseResult);
            var el = @else.ToArray();

            if (el.Length != 1)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression.Arguments[0]);
            }

            var(subject, cases, tables2) = GetCases(state, caseExpression.Object, MapType.Other, toPrefix);

            var prop = new StringBasedMappedProperty(
                new SimpleCaseSqlExpression <StringBasedElement>(
                    subject.FromParams,
                    cases.Select(c => (c.when.FromParams, c.then.FromParams)),
                    el[0].FromParams),
                toPrefix,
                caseExpression.Type,
                state.MappingContext.propertyName,
                cases
                .SelectMany(x => new [] { x.when, x.then })
                .Concat(@else)
                .SelectMany(c => c.PropertySegmentConstructors)
                .ToArray());

            return(
                prop.ToEnumerable(),
                tables.Concat(tables2));
        }
Example #9
0
 static (IEnumerable <StringBasedMappedProperty> property, IEnumerable <MappedTable> tables) CompileCases(
     BuildMapState state,
     IEnumerable <(StringBasedMappedProperty when, StringBasedMappedProperty then)> cases,
Example #10
0
        static (IEnumerable <StringBasedMappedProperty> properties, IEnumerable <MappedTable> tables, bool isConstant) BuildMap(
            BuildMapState state,
            Expression expr,
            MapType nextMap,
            string toPrefix)
        {
            var(isConstant, requiresArgs) = ReflectionUtils.IsConstant(expr, state.ArgsObject);
            if (isConstant)
            {
                var result = requiresArgs ?
                             QueryArgAccessor.Create(state.ArgsObject, expr) :
                             ReflectionUtils.ExecuteExpression(expr);

                var paramName = state.Parameters.AddParam(result, expr.Type);

                return(
                    new StringBasedMappedProperty(
                        null,
                        paramName,
                        toPrefix,
                        expr.Type,
                        state.MappingContext.propertyName,
                        aggregatedToTable: state.MappingContext.propertyName).ToEnumerable(),
                    EmptyMappedTables,
                    true
                    );
            }

            switch (expr.NodeType)
            {
            case ExpressionType.Convert:
                return(BuildMapWithErrorHandling(state, (expr as UnaryExpression).Operand, nextMap, toPrefix));

            case ExpressionType.Parameter:
                return(
                    new []
                {
                    new StringBasedMappedProperty(
                        expr as ParameterExpression,
                        null,
                        toPrefix,
                        expr.Type,
                        state.MappingContext.propertyName)
                },
                    EmptyMappedTables,
                    false
                    );

            case ExpressionType.AndAlso:
            case ExpressionType.OrElse:
            case ExpressionType.Add:
            case ExpressionType.Subtract:
            case ExpressionType.Multiply:
            case ExpressionType.Divide:
            case ExpressionType.Equal:
            case ExpressionType.NotEqual:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
                var asB = expr as BinaryExpression;
                return(BuildMapForBinaryCondition(state, asB.Left, asB.Right, asB.Type, asB.NodeType, toPrefix).AddT(false));

            case ExpressionType.Conditional:
                var asC = expr as ConditionalExpression;
                return(CaseMapBuilder.BuildMap(state, asC, toPrefix).AddT(false));

            case ExpressionType.MemberAccess:
                return(BuildMapForMemberAccess(state, expr as MemberExpression, nextMap, toPrefix));

            case ExpressionType.New:
                return(BuildMapForConstructor(state, expr as NewExpression, nextMap, toPrefix: toPrefix).AddT(false));

            case ExpressionType.MemberInit:
                return(BuildMapForMemberInit(state, expr as MemberInitExpression, nextMap, toPrefix).AddT(false));

            case ExpressionType.ArrayLength:
                return(BuildMapForCount(state, (expr as UnaryExpression).Operand, toPrefix).AddT(false));

            case ExpressionType.NewArrayInit:
            case ExpressionType.NewArrayBounds:
                return(BuildMapForNewArray(state, expr as NewArrayExpression, toPrefix).AddT(false));

            case ExpressionType.ListInit:
                return(BuildMapForNewList(state, expr as ListInitExpression, toPrefix).AddT(false));

            case ExpressionType.Call:
                var exprMethod = expr as MethodCallExpression;

                var isOrderByRowNumber = ReflectionUtils.IsOrderByRowNumber(exprMethod);
                if (isOrderByRowNumber)
                {
                    return(BuildMapForOrderByRowNumber(state, exprMethod, toPrefix).AddT(false));
                }

                var(isIn, inLhs, inRhs) = ReflectionUtils.IsIn(exprMethod);
                if (isIn)
                {
                    return(BuildMapForIn(state, inLhs, inRhs, toPrefix).AddT(false));
                }

                var(isCount, countExpr) = ReflectionUtils.IsCount(expr);
                if (isCount)
                {
                    return(BuildMapForCount(state, countExpr, toPrefix).AddT(false));
                }

                var(isSum, sumExpr, sumMapper) = ReflectionUtils.IsSum(exprMethod);
                if (isSum)
                {
                    return(sumMapper == null
                            ? BuildMapForSum(state, sumExpr, toPrefix).AddT(false)
                            : BuildMapForSum(state, sumExpr, sumMapper, toPrefix).AddT(false));
                }

                var(isAverage, averageExpr, averageMapper) = ReflectionUtils.IsAverage(exprMethod);
                if (isAverage)
                {
                    return(averageMapper == null
                            ? BuildMapForAverage(state, averageExpr, toPrefix).AddT(false)
                            : BuildMapForAverage(state, averageExpr, averageMapper, toPrefix).AddT(false));
                }

                var(isMax, maxExpr, maxMapper) = ReflectionUtils.IsMax(exprMethod);
                if (isMax)
                {
                    return(maxMapper == null
                            ? BuildMapForMax(state, maxExpr, toPrefix).AddT(false)
                            : BuildMapForMax(state, maxExpr, maxMapper, toPrefix).AddT(false));
                }

                var(isMin, minExpr, minMapper) = ReflectionUtils.IsMin(exprMethod);
                if (isMin)
                {
                    return(minMapper == null
                            ? BuildMapForMin(state, minExpr, toPrefix).AddT(false)
                            : BuildMapForMin(state, minExpr, minMapper, toPrefix).AddT(false));
                }

                var oneExpr = ReflectionUtils.IsOne(exprMethod);
                if (oneExpr != null)
                {
                    return(BuildMapForOne(state, oneExpr, nextMap, toPrefix));
                }

                var(isToList, enumerableL) = ReflectionUtils.IsToList(exprMethod);
                if (isToList)
                {
                    // .ToList(...) is invisible as far as nextMap is concerned
                    return(BuildMapWithErrorHandling(state, enumerableL, nextMap, toPrefix));
                }

                var(isToArray, enumerableA) = ReflectionUtils.IsToArray(exprMethod);
                if (isToArray)
                {
                    // .ToArray(...) is invisible as far as nextMap is concerned
                    return(BuildMapWithErrorHandling(state, enumerableA, nextMap, toPrefix));
                }

                var(isSelect, enumerableS, mapper) = ReflectionUtils.IsSelectWithLambdaExpression(exprMethod);
                if (isSelect)
                {
                    return(BuildMapForSelect(state, enumerableS, nextMap, mapper, toPrefix).AddT(false));
                }

                var isCase = CaseMapBuilder.IsCase(exprMethod);
                if (isCase)
                {
                    return(CaseMapBuilder.BuildMap(state, exprMethod, nextMap, toPrefix).AddT(false));
                }

                var isSimpleCase = SimpleCaseMapBuilder.IsCase(exprMethod);
                if (isSimpleCase)
                {
                    return(SimpleCaseMapBuilder.BuildMap(state, exprMethod, nextMap, toPrefix).AddT(false));
                }

                break;

            default:
                break;
            }

            throw BuildMappingError(state.MappingPurpose, expr);
        }
Example #11
0
 static (IEnumerable <StringBasedMappedProperty> properties, IEnumerable <MappedTable> tables) BuildMapForBinaryCondition(BuildMapState state, Expression left, Expression right, Type combinedType, ExpressionType combiner, string toPrefix = null) =>
Example #12
0
        static (IEnumerable <StringBasedMappedProperty> properties, IEnumerable <MappedTable> tables) BuildMapForConstructor(BuildMapState state, NewExpression expr, MapType nextMap, string toPrefix = null)
        {
            // TODO: relax this condition
            // The issue is within ObjectPropertyGraphBuilder, complex properties (or constructor args)
            // are defined by the inner simple properties. e.g. property name = OuterObj.InnerProp will create
            // an outer obj and an inner prop. But if inner prop is not set, then there is no reference to outer
            // obj either.
            // see also supporting tests:
            //      PropertyGraph_ReturnsMultipleComplexArgsWithNoSimpleProps_ReturnsCorrectOPG1
            //      PropertyGraph_ReturnsMultipleComplexArgsWithNoSimpleProps_ReturnsCorrectOPG2
            //      ReturnMultipleFromMap_PreMappedWithComplexProperty
            //      ReturnMultipleFromMap_PreMappedWithSimpleConstructorArg
            //      ReturnMultipleFromMap_PreMappedWithSimplePropertyAndSimpleConstructorArg
            //      SimpleMapReturningEmptyObject

            if (nextMap != MapType.MemberInit && expr.Arguments.Count == 0)
            {
                throw BuildMappingError(state.MappingPurpose, $"You cannot map to an object with has no data from table columns: {expr}.");
            }

            return(expr.Arguments
                   .Select((ex, i) => (type: ex.Type, map: BuildMapWithErrorHandling(state, ex, MapType.Other, toPrefix: CombineStrings(toPrefix, SqlStatementConstants.ConstructorArgs.BuildConstructorArg(i)))))
                   .Select((map, i) => (
                               map.Item2.properties.SelectMany(p => CreateContructorArg(p, map.type, i)),
                               map.map.tables.Select(x => new MappedTable(x.From, CombineStrings(SqlStatementConstants.ConstructorArgs.BuildConstructorArg(i), x.To), x.TableresultsAreAggregated))))
                   .AggregateTuple2());

            IEnumerable <StringBasedMappedProperty> CreateContructorArg(StringBasedMappedProperty arg, Type argType, int argIndex)
            {
                var many = PropertyRepresentsTable(state, arg) ?
                           SplitMapOfComplexProperty(state, arg, argType) :
                           arg.ToEnumerable();

                return(many.Select(q => q.With(
                                       constructorArgs: q.PropertySegmentConstructors.Prepend(expr.Constructor).ToArray())));
            }
        }
Example #13
0
 public static (IEnumerable <StringBasedMappedProperty> properties, IEnumerable <MappedTable> tables) BuildMap(BuildMapState state, Expression expr)
 {
     var(x, y, _) = BuildMapWithErrorHandling(state, expr, MapType.Root);
     return(x, y);
 }
Example #14
0
        public static (IEnumerable <QueryElementBasedMappedProperty> properties, IEnumerable <StrongMappedTable> tables) BuildMapFromRoot(BuildMapState state, Expression expression)
        {
            var(properties, tables) = ComplexMapBuilder.BuildMap(state, expression);

            return(
                properties.Select(p => p.Convert(state)).ToArray(),
                tables.Select(p => p.Convert(state.WrappedSqlStatement)).ToArray());
        }
Example #15
0
        static (StringBasedMappedProperty subject, IEnumerable <(StringBasedMappedProperty when, StringBasedMappedProperty then)> cases, IEnumerable <MappedTable> tables) GetCases(
            BuildMapState state,
            Expression caseExpression,
            MapType nextMap,
            string toPrefix = null)
        {
            var thenObject = caseExpression as MethodCallExpression;

            if (thenObject == null)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression);
            }

            var(isSubject, subject) = IsSubject(thenObject);
            if (isSubject)
            {
                var(subjectProperties, subjectTables) = ComplexMapBuilder.BuildMap(state, subject);
                var subjectP = subjectProperties.ToArray();
                if (subjectP.Length != 1)
                {
                    throw new SqlBuilderException(state.MappingPurpose, caseExpression);
                }

                return(subjectP[0], CodingConstants.Empty.Case, subjectTables);
            }

            var(isThen, thenResult) = IsThen(thenObject);
            if (!isThen)
            {
                throw new SqlBuilderException(state.MappingPurpose, thenObject);
            }

            var whenObject = thenObject.Object as MethodCallExpression;

            if (whenObject == null)
            {
                throw new SqlBuilderException(state.MappingPurpose, thenObject.Object);
            }

            var(isWhen, whenCondition) = IsWhen(whenObject);
            if (!isWhen)
            {
                throw new SqlBuilderException(state.MappingPurpose, whenObject);
            }

            var(whenProperties, whenTables) = ComplexMapBuilder.BuildMap(state, whenCondition);
            var(thenProperties, thenTables) = ComplexMapBuilder.BuildMap(state, thenResult);

            var whenP = whenProperties.ToArray();
            var thenP = thenProperties.ToArray();

            if (whenP.Length != 1 || thenP.Length != 1)
            {
                throw new SqlBuilderException(state.MappingPurpose, caseExpression);
            }

            var(sjt, cases, tables) = GetCases(state, whenObject.Object, MapType.Other, toPrefix);
            return(
                sjt,
                cases.Append((whenP[0], thenP[0])),
                tables.Concat(whenTables).Concat(thenTables)
                );
        }