Exemple #1
0
        public override (string, QxType, QxNullity) CompileNative(QxCompilationContext ctx)
        {
            if (string.IsNullOrWhiteSpace(Property))
            {
                // Developer mistake
                throw new InvalidOperationException($"Bug: Invoking {nameof(CompileNative)} on a {nameof(QueryexColumnAccess)} that does not have a property.");
            }

            var propName = Property;

            // (A) Calculate Nullity (the entire path foreign keys + the final property must be all NOT NULL)
            bool pathNotNull = true;
            var  join        = ctx.Joins;

            foreach (var step in Path)
            {
                var navPropDesc = join.EntityDescriptor.NavigationProperty(step);
                pathNotNull = pathNotNull && navPropDesc.ForeignKey.IsNotNull;
                join        = join[step];
            }

            var propDesc = join.EntityDescriptor.Property(propName);

            if (propDesc == null)
            {
                throw new QueryException($"Property '{propName}' does not exist on type {join.EntityDescriptor.Name}.");
            }

            QxNullity nullity = pathNotNull && propDesc.IsNotNull ? QxNullity.NotNull : QxNullity.Nullable;

            // (B) Calculate the type
            QxType type;
            var    propType = Nullable.GetUnderlyingType(propDesc.Type) ?? propDesc.Type;

            switch (propType.Name)
            {
            case nameof(Char):
            case nameof(String):
                type = QxType.String;
                break;

            case nameof(Byte):
            case nameof(SByte):
            case nameof(Int16):
            case nameof(UInt16):
            case nameof(Int32):
            case nameof(UInt32):
            case nameof(Int64):
            case nameof(UInt64):
            case nameof(Single):
            case nameof(Double):
            case nameof(Decimal):
                type = QxType.Numeric;
                break;

            case nameof(Boolean):
                type = QxType.Bit;
                break;

            case nameof(DateTime):
                type = propDesc.IncludesTime ? QxType.DateTime : QxType.Date;
                break;

            case nameof(DateTimeOffset):
                type = QxType.DateTimeOffset;
                break;

            case nameof(HierarchyId):
                type = QxType.HierarchyId;
                break;

            case nameof(Geography):
                type = QxType.Geography;
                break;

            default:
                if (propDesc is NavigationPropertyDescriptor || propDesc is CollectionPropertyDescriptor)
                {
                    throw new QueryException($"A column access cannot terminate with a navigation property like {propDesc.Name}.");
                }
                else
                {
                    // Developer mistake
                    throw new InvalidOperationException($"[Bug] Could not map type {propType.Name} to a {nameof(QxType)}");     // Future proofing
                }
            }

            // (C) Calculate the SQL
            var sql = $"[{join.Symbol}].[{propName}]";

            // Return the result
            return(sql, type, nullity);
        }
 public override bool TryCompile(QxType targetType, QxCompilationContext ctx, out string resultSql, out QxNullity resultNullity)
 {
     // This here is merely an optimization
     if (Operator == "+")
     {
         if ((targetType == QxType.String && // String concatenation
              Left.TryCompile(QxType.String, ctx, out string leftSql, out QxNullity leftNullity) &&
              Right.TryCompile(QxType.String, ctx, out string rightSql, out QxNullity rightNullity)) ||
             (targetType == QxType.Numeric && // Numeric
              Left.TryCompile(QxType.Numeric, ctx, out leftSql, out leftNullity) &&
              Right.TryCompile(QxType.Numeric, ctx, out rightSql, out rightNullity)))
         {
             resultNullity = leftNullity | rightNullity;
             resultSql     = $"({leftSql} + {rightSql})";
             return(true);
         }
         else
         {
             // No other types are possible for +
             resultNullity = default;
             resultSql     = null;
             return(false);
         }
     }
Exemple #3
0
        public override bool TryCompile(QxType targetType, QxCompilationContext ctx, out string resultSql, out QxNullity resultNullity)
        {
            switch (targetType)
            {
            case QxType.Date:
                if (DateTime.TryParse(Value, out DateTime d))
                {
                    d = d.Date;     // Remove the time component
                    string varDef  = $"N'{d:yyyy-MM-dd}'";
                    string varName = ctx.Variables.AddVariable("DATE", varDef);
                    resultSql     = $"@{varName}";
                    resultNullity = QxNullity.NotNull;
                    return(true);
                }
                else
                {
                    resultSql     = null;
                    resultNullity = default;
                    return(false);
                }

            case QxType.DateTime:
                if (DateTime.TryParse(Value, out DateTime dt))
                {
                    string varDef  = $"N'{dt:yyyy-MM-ddTHH:mm:ss.ff}'";
                    string varName = ctx.Variables.AddVariable("DATETIME2(2)", varDef);
                    resultSql     = $"@{varName}";
                    resultNullity = QxNullity.NotNull;
                    return(true);
                }
                else
                {
                    resultSql     = null;
                    resultNullity = default;
                    return(false);
                }

            case QxType.DateTimeOffset:
                if (DateTimeOffset.TryParse(Value, out DateTimeOffset dto))
                {
                    string varDef  = $"N'{dto:o}'";
                    string varName = ctx.Variables.AddVariable("DATETIMEOFFSET(7)", varDef);
                    resultSql     = $"@{varName}";
                    resultNullity = QxNullity.NotNull;
                    return(true);
                }
                else
                {
                    resultSql     = null;
                    resultNullity = default;
                    return(false);
                }
            }

            return(base.TryCompile(targetType, ctx, out resultSql, out resultNullity));
        }
Exemple #4
0
        public override bool TryCompile(QxType targetType, QxCompilationContext ctx, out string resultSql, out QxNullity resultNullity)
        {
            string nameLower = Name?.ToLower();

            switch (nameLower)
            {
            case "min":
            case "max":
            {
                var(arg1, conditionSql) = AggregationParameters(ctx);

                if (arg1.TryCompile(targetType, ctx, out string expSql, out resultNullity))
                {
                    resultSql = AggregationCompile(expSql, conditionSql);
                    return(true);
                }