示例#1
0
        private Sql.ExpressionAttribute GetDbFunctionFromMethodCall(Type type, MethodInfo methodInfo)
        {
            if (_dependencies == null || _model == null)
            {
                return(null);
            }

            methodInfo = (MethodInfo)type.GetMemberEx(methodInfo) ?? methodInfo;

            var found = _calculatedExtensions.GetOrAdd(methodInfo, mi =>
            {
                EFCoreExpressionAttribute result = null;

                if (!methodInfo.IsGenericMethodDefinition && !mi.GetCustomAttributes <Sql.ExpressionAttribute>().Any())
                {
                    var value = Expression.Constant(DefaultValue.GetValue(type), type);

                    var objExpr         = new SqlTransparentExpression(value, _mappingSource?.FindMapping(type));
                    var parameterInfos  = methodInfo.GetParameters();
                    var parametersArray = parameterInfos
                                          .Select(p =>
                                                  (SqlExpression) new SqlTransparentExpression(
                                                      Expression.Constant(DefaultValue.GetValue(p.ParameterType), p.ParameterType),
                                                      _mappingSource?.FindMapping(p.ParameterType))).ToArray();

                    var newExpression = _dependencies.MethodCallTranslatorProvider.Translate(_model, objExpr, methodInfo, parametersArray);
                    if (newExpression != null)
                    {
                        if (!methodInfo.IsStatic)
                        {
                            parametersArray = new SqlExpression[] { objExpr }
                        }
                        .Concat(parametersArray).ToArray();

                        result = ConvertToExpressionAttribute(methodInfo, newExpression, parametersArray);
                    }
示例#2
0
 private string GetVariableType(ColumnModification columnModification)
 {
     return(_typeMappingSource.FindMapping(columnModification.Property).StoreType);
 }
示例#3
0
        public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments, IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            var traversal = GetTraversalExpression(instance, arguments);

            if (traversal == null)
            {
                return(null);
            }

            if (typeof(JToken).IsAssignableFrom(method.DeclaringType) &&
                method.Name == "get_Item" &&
                arguments.Count == 1)
            {
                var indexExpression = _sqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0]);

                if (method.DeclaringType == typeof(JArray) ||
                    indexExpression.Type == typeof(int))
                {
                    // Try translating indexing inside json column.
                    return(_jsonPocoTranslator.TranslateMemberAccess(
                               traversal,
                               _sqlExpressionFactory.JsonArrayIndex(indexExpression),
                               method.ReturnType));
                }

                return(traversal.Append(
                           ApplyPathLocationTypeMapping(arguments[0]),
                           method.DeclaringType,
                           _typeMappingSource.FindMapping(method.DeclaringType)));
            }

            // Support for .Value<T>() and .Value<U, T>():
            if (instance == null &&
                method.Name == nameof(global::Newtonsoft.Json.Linq.Extensions.Value) &&
                method.DeclaringType == typeof(global::Newtonsoft.Json.Linq.Extensions) &&
                method.IsGenericMethod &&
                method.GetParameters().Length == 1 &&
                arguments.Count == 1)
            {
                return(ConvertFromJsonExtract(
                           traversal.Clone(
                               method.ReturnType == typeof(string),
                               method.ReturnType,
                               _typeMappingSource.FindMapping(method.ReturnType)
                               ),
                           method.ReturnType));
            }

            // Support for Count()
            if (instance == null &&
                method.Name == nameof(Enumerable.Count) &&
                method.DeclaringType == typeof(Enumerable) &&
                method.IsGenericMethod &&
                method.GetParameters().Length == 1 &&
                arguments.Count == 1)
            {
                return(_jsonPocoTranslator.TranslateArrayLength(traversal));
            }

            // Predicate-less Any - translate to a simple length check.
            if (method.IsClosedFormOf(_enumerableAnyWithoutPredicate) &&
                arguments.Count == 1 &&
                arguments[0].Type.TryGetElementType(out _) &&
                arguments[0].TypeMapping is MySqlJsonTypeMapping)
            {
                return(_sqlExpressionFactory.GreaterThan(
                           _jsonPocoTranslator.TranslateArrayLength(arguments[0]),
                           _sqlExpressionFactory.Constant(0)));
            }

            return(null);
        }
示例#4
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual TypeScaffoldingInfo FindMapping(
            string storeType,
            bool keyOrIndex,
            bool rowVersion)
        {
            // This is because certain providers can have no type specified as a default type e.g. SQLite
            Check.NotNull(storeType, nameof(storeType));

            var mapping = _typeMappingSource.FindMapping(storeType);

            if (mapping == null)
            {
                return(null);
            }

            var  canInfer          = false;
            bool?scaffoldUnicode   = null;
            int? scaffoldMaxLength = null;

            if (mapping.ClrType == typeof(byte[]))
            {
                // Check for inference
                var byteArrayMapping = _typeMappingSource.FindMapping(
                    typeof(byte[]),
                    keyOrIndex,
                    rowVersion: rowVersion,
                    size: mapping.Size);

                if (byteArrayMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
                {
                    canInfer = true;

                    // Check for size
                    var sizedMapping = _typeMappingSource.FindMapping(
                        typeof(byte[]),
                        keyOrIndex,
                        rowVersion: rowVersion);

                    scaffoldMaxLength = sizedMapping.Size != byteArrayMapping.Size ? byteArrayMapping.Size : null;
                }
            }
            else if (mapping.ClrType == typeof(string))
            {
                // Check for inference
                var stringMapping = _typeMappingSource.FindMapping(
                    typeof(string),
                    keyOrIndex,
                    unicode: mapping.IsUnicode,
                    size: mapping.Size);

                if (stringMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
                {
                    canInfer = true;

                    // Check for unicode
                    var unicodeMapping = _typeMappingSource.FindMapping(
                        typeof(string),
                        keyOrIndex,
                        unicode: true,
                        size: mapping.Size);

                    scaffoldUnicode = unicodeMapping.IsUnicode != stringMapping.IsUnicode ? (bool?)stringMapping.IsUnicode : null;

                    // Check for size
                    var sizedMapping = _typeMappingSource.FindMapping(
                        typeof(string),
                        keyOrIndex,
                        unicode: mapping.IsUnicode);

                    scaffoldMaxLength = sizedMapping.Size != stringMapping.Size ? stringMapping.Size : null;
                }
            }
            else
            {
                var defaultMapping = _typeMappingSource.GetMapping(mapping.ClrType);

                if (defaultMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
                {
                    canInfer = true;
                }
            }

            return(new TypeScaffoldingInfo(
                       mapping.ClrType,
                       canInfer,
                       scaffoldUnicode,
                       scaffoldMaxLength));
        }
示例#5
0
 public static RelationalTypeMapping GetMapping(
     IRelationalTypeMappingSource typeMappingSource,
     IProperty property)
 => typeMappingSource.FindMapping(property);
示例#6
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual SqlExpression?Translate(
            SqlExpression?instance,
            MemberInfo member,
            Type returnType,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            Check.NotNull(member, nameof(member));
            Check.NotNull(returnType, nameof(returnType));
            Check.NotNull(logger, nameof(logger));

            if (typeof(Polygon).IsAssignableFrom(member.DeclaringType))
            {
                Check.DebugAssert(instance !.TypeMapping != null, "Instance must have typeMapping assigned.");
                var storeType   = instance.TypeMapping.StoreType;
                var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase);

                if (isGeography)
                {
                    if (Equals(_exteriorRing, member))
                    {
                        return(_sqlExpressionFactory.Function(
                                   instance,
                                   "RingN",
                                   new[] { _sqlExpressionFactory.Constant(1) },
                                   nullable: true,
                                   instancePropagatesNullability: true,
                                   argumentsPropagateNullability: new[] { false },
                                   returnType,
                                   _typeMappingSource.FindMapping(returnType, storeType)));
                    }

                    if (Equals(_numInteriorRings, member))
                    {
                        return(_sqlExpressionFactory.Subtract(
                                   _sqlExpressionFactory.Function(
                                       instance,
                                       "NumRings",
                                       Array.Empty <SqlExpression>(),
                                       nullable: true,
                                       instancePropagatesNullability: true,
                                       argumentsPropagateNullability: Array.Empty <bool>(),
                                       returnType),
                                   _sqlExpressionFactory.Constant(1)));
                    }
                }

                if (_geometryMemberToFunctionName.TryGetValue(member, out var functionName))
                {
                    var resultTypeMapping = typeof(Geometry).IsAssignableFrom(returnType)
                        ? _typeMappingSource.FindMapping(returnType, storeType)
                        : _typeMappingSource.FindMapping(returnType);

                    return(_sqlExpressionFactory.Function(
                               instance,
                               functionName,
                               Array.Empty <SqlExpression>(),
                               nullable: true,
                               instancePropagatesNullability: true,
                               argumentsPropagateNullability: Array.Empty <bool>(),
                               returnType,
                               resultTypeMapping));
                }
            }

            return(null);
        }
示例#7
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual TypeScaffoldingInfo?FindMapping(
            string storeType,
            bool keyOrIndex,
            bool rowVersion)
        {
            // This is because certain providers can have no type specified as a default type e.g. SQLite
            Check.NotNull(storeType, nameof(storeType));

            var mapping = _typeMappingSource.FindMapping(storeType);

            if (mapping == null)
            {
                return(null);
            }

            var  canInfer            = false;
            bool?scaffoldUnicode     = null;
            bool?scaffoldFixedLength = null;
            int? scaffoldMaxLength   = null;
            int? scaffoldPrecision   = null;
            int? scaffoldScale       = null;

            var unwrappedClrType = mapping.ClrType.UnwrapNullableType();

            // Check for inference
            var defaultTypeMapping = _typeMappingSource.FindMapping(
                unwrappedClrType,
                null,
                keyOrIndex,
                unicode: mapping.IsUnicode,
                size: mapping.Size,
                rowVersion: rowVersion,
                fixedLength: mapping.IsFixedLength,
                precision: mapping.Precision,
                scale: mapping.Scale);

            if (defaultTypeMapping != null &&
                string.Equals(defaultTypeMapping.StoreType, storeType, StringComparison.Ordinal))
            {
                canInfer = true;

                // Check for Unicode
                var unicodeMapping = _typeMappingSource.FindMapping(
                    unwrappedClrType,
                    null,
                    keyOrIndex,
                    unicode: null,
                    size: mapping.Size,
                    rowVersion: rowVersion,
                    fixedLength: mapping.IsFixedLength,
                    precision: mapping.Precision,
                    scale: mapping.Scale) !;

                scaffoldUnicode = unicodeMapping.IsUnicode != defaultTypeMapping.IsUnicode ? (bool?)defaultTypeMapping.IsUnicode : null;

                // Check for fixed-length
                var fixedLengthMapping = _typeMappingSource.FindMapping(
                    unwrappedClrType,
                    null,
                    keyOrIndex,
                    unicode: mapping.IsUnicode,
                    size: mapping.Size,
                    fixedLength: null,
                    precision: mapping.Precision,
                    scale: mapping.Scale) !;

                scaffoldFixedLength = fixedLengthMapping.IsFixedLength != defaultTypeMapping.IsFixedLength
                    ? (bool?)defaultTypeMapping.IsFixedLength
                    : null;

                // Check for size (= max-length)
                var sizedMapping = _typeMappingSource.FindMapping(
                    unwrappedClrType,
                    null,
                    keyOrIndex,
                    unicode: mapping.IsUnicode,
                    size: null,
                    rowVersion: rowVersion,
                    fixedLength: false, // Fixed length with no size is not valid
                    precision: mapping.Precision,
                    scale: mapping.Scale) !;

                scaffoldMaxLength = sizedMapping.Size != defaultTypeMapping.Size ? defaultTypeMapping.Size : null;

                // Check for precision
                var precisionMapping = _typeMappingSource.FindMapping(
                    unwrappedClrType,
                    null,
                    keyOrIndex,
                    unicode: mapping.IsUnicode,
                    size: mapping.Size,
                    rowVersion: rowVersion,
                    fixedLength: mapping.IsFixedLength,
                    precision: null,
                    scale: mapping.Scale) !;

                scaffoldPrecision = precisionMapping.Precision != defaultTypeMapping.Precision ? defaultTypeMapping.Precision : null;

                // Check for scale
                var scaleMapping = _typeMappingSource.FindMapping(
                    unwrappedClrType,
                    null,
                    keyOrIndex,
                    unicode: mapping.IsUnicode,
                    size: mapping.Size,
                    rowVersion: rowVersion,
                    fixedLength: mapping.IsFixedLength,
                    precision: mapping.Precision,
                    scale: null) !;

                scaffoldScale = scaleMapping.Scale != defaultTypeMapping.Scale ? defaultTypeMapping.Scale : null;
            }

            return(new TypeScaffoldingInfo(
                       mapping.ClrType,
                       canInfer,
                       scaffoldUnicode,
                       scaffoldMaxLength,
                       scaffoldFixedLength,
                       scaffoldPrecision,
                       scaffoldScale));
        }
 public SqlExpressionFactory(IRelationalTypeMappingSource typeMappingSource)
 {
     _typeMappingSource = typeMappingSource;
     _boolTypeMapping   = typeMappingSource.FindMapping(typeof(bool));
 }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType)
        {
            Check.NotNull(member, nameof(member));
            Check.NotNull(returnType, nameof(returnType));

            if (typeof(Geometry).IsAssignableFrom(member.DeclaringType))
            {
                Check.DebugAssert(instance.TypeMapping != null, "Instance must have typeMapping assigned.");
                var storeType   = instance.TypeMapping.StoreType;
                var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase);

                if (_memberToFunctionName.TryGetValue(member, out var functionName) ||
                    (!isGeography && _geometryMemberToFunctionName.TryGetValue(member, out functionName)))
                {
                    var resultTypeMapping = typeof(Geometry).IsAssignableFrom(returnType)
                        ? _typeMappingSource.FindMapping(returnType, storeType)
                        : _typeMappingSource.FindMapping(returnType);

                    return(_sqlExpressionFactory.Function(
                               instance,
                               functionName,
                               Array.Empty <SqlExpression>(),
                               nullable: true,
                               instancePropagatesNullability: true,
                               argumentsPropagateNullability: Array.Empty <bool>(),
                               returnType,
                               resultTypeMapping));
                }

                if (Equals(member, _ogcGeometryType))
                {
                    var whenClauses = new List <CaseWhenClause>
                    {
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("Point"), _sqlExpressionFactory.Constant(OgcGeometryType.Point)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("LineString"), _sqlExpressionFactory.Constant(OgcGeometryType.LineString)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("Polygon"), _sqlExpressionFactory.Constant(OgcGeometryType.Polygon)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("MultiPoint"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPoint)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("MultiLineString"),
                            _sqlExpressionFactory.Constant(OgcGeometryType.MultiLineString)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("MultiPolygon"),
                            _sqlExpressionFactory.Constant(OgcGeometryType.MultiPolygon)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("GeometryCollection"),
                            _sqlExpressionFactory.Constant(OgcGeometryType.GeometryCollection)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("CircularString"),
                            _sqlExpressionFactory.Constant(OgcGeometryType.CircularString)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("CompoundCurve"),
                            _sqlExpressionFactory.Constant(OgcGeometryType.CompoundCurve)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.Constant("CurvePolygon"),
                            _sqlExpressionFactory.Constant(OgcGeometryType.CurvePolygon))
                    };

                    if (isGeography)
                    {
                        whenClauses.Add(
                            new CaseWhenClause(
                                _sqlExpressionFactory.Constant("FullGlobe"), _sqlExpressionFactory.Constant((OgcGeometryType)126)));
                    }

                    return(_sqlExpressionFactory.Case(
                               _sqlExpressionFactory.Function(
                                   instance,
                                   "STGeometryType",
                                   Array.Empty <SqlExpression>(),
                                   nullable: true,
                                   instancePropagatesNullability: true,
                                   argumentsPropagateNullability: Array.Empty <bool>(),
                                   typeof(string)),
                               whenClauses.ToArray()));
                }

                if (Equals(member, _srid))
                {
                    return(_sqlExpressionFactory.Function(
                               instance,
                               "STSrid",
                               nullable: true,
                               instancePropagatesNullability: true,
                               returnType));
                }
            }

            return(null);
        }
 public virtual RelationalTypeMapping FindMapping([NotNull] string storeTypeName)
 => _typeMappingSource.FindMapping(storeTypeName);
 public MySqlSqlExpressionFactory(SqlExpressionFactoryDependencies dependencies)
     : base(dependencies)
 {
     _typeMappingSource = dependencies.TypeMappingSource;
     _boolTypeMapping   = _typeMappingSource.FindMapping(typeof(bool));
 }