Exemplo n.º 1
0
        public virtual void CopyAttributes(SQLiteColumnAttribute attribute)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException(nameof(attribute));
            }

            IsReadOnly          = attribute.IsReadOnly;
            IsNullable          = attribute.IsNullable;
            IsPrimaryKey        = attribute.IsPrimaryKey;
            InsertOnly          = attribute.InsertOnly;
            UpdateOnly          = attribute.UpdateOnly;
            AutoIncrements      = attribute.AutoIncrements;
            AutomaticType       = attribute.AutomaticType;
            HasDefaultValue     = attribute.HasDefaultValue;
            Collation           = attribute.Collation;
            BindOptions         = attribute.BindOptions;
            PrimaryKeyDirection = attribute.PrimaryKeyDirection;
            IsUnique            = attribute.IsUnique;
            CheckExpression     = attribute.CheckExpression;
            if (HasDefaultValue)
            {
                if (!Table.Database.TryChangeType(attribute.DefaultValue, ClrType, out object value))
                {
                    string type = attribute.DefaultValue != null ? "'" + attribute.DefaultValue.GetType().FullName + "'" : "<null>";
                    throw new SqlNadoException("0023: Cannot convert attribute DefaultValue `" + attribute.DefaultValue + "` of type " + type + " for column '" + Name + "' of table '" + Table.Name + "'.");
                }

                DefaultValue            = value;
                IsDefaultValueIntrinsic = attribute.IsDefaultValueIntrinsic;
            }
        }
Exemplo n.º 2
0
        protected virtual SQLiteColumnAttribute AddAnnotationAttributes(PropertyInfo property, SQLiteColumnAttribute attribute)
        {
            if (property == null)
            {
                throw new ArgumentNullException(nameof(property));
            }

            // NOTE: we don't add RequiredAttribute, ColumnAttribute here because that would require us to add a package
            // but check the test project, it has an example in the TestDataAnnotations method.
            return(attribute);
        }
Exemplo n.º 3
0
        protected virtual void AddIndices(SQLiteObjectTable table, IDictionary <string, IReadOnlyList <Tuple <SQLiteColumnAttribute, SQLiteIndexAttribute> > > indices)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (indices == null)
            {
                throw new ArgumentNullException(nameof(indices));
            }

            foreach (var index in indices)
            {
                var list = index.Value;
                for (int i = 0; i < list.Count; i++)
                {
                    SQLiteColumnAttribute col = list[i].Item1;
                    SQLiteIndexAttribute  idx = list[i].Item2;
                    if (idx.Order == SQLiteIndexAttribute.DefaultOrder)
                    {
                        idx.Order = i;
                    }
                }

                var    columns    = new List <SQLiteIndexedColumn>();
                bool   unique     = false;
                string schemaName = null;
                foreach (var kv in list.OrderBy(l => l.Item2.Order))
                {
                    var col = CreateIndexedColumn(kv.Item1.Name);
                    if (col == null)
                    {
                        throw new InvalidOperationException();
                    }

                    col.CollationName = kv.Item2.CollationName;
                    col.Direction     = kv.Item2.Direction;

                    // if at least one defines unique, it's unique
                    if (kv.Item2.IsUnique)
                    {
                        unique = true;
                    }

                    // first schema defined is used
                    if (!string.IsNullOrWhiteSpace(kv.Item2.SchemaName))
                    {
                        schemaName = kv.Item2.SchemaName;
                    }
                    columns.Add(col);
                }

                var oidx = CreateObjectIndex(table, index.Key, columns);
                if (oidx == null)
                {
                    throw new InvalidOperationException();
                }

                oidx.IsUnique   = unique;
                oidx.SchemaName = schemaName;
                table.AddIndex(oidx);
            }
        }
Exemplo n.º 4
0
        protected virtual SQLiteColumnAttribute GetColumnAttribute(PropertyInfo property)
        {
            if (property == null)
            {
                throw new ArgumentNullException(nameof(property));
            }

            // discard enumerated types unless att is defined to not ignore
            var att = property.GetCustomAttribute <SQLiteColumnAttribute>();

            if (property.PropertyType != typeof(string))
            {
                var et = Conversions.GetEnumeratedType(property.PropertyType);
                if (et != null)
                {
                    if (et != typeof(byte))
                    {
                        if (att == null || !att._ignore.HasValue || att._ignore.Value)
                        {
                            return(null);
                        }
                    }
                }
            }

            if (att != null && att.Ignore)
            {
                return(null);
            }

            if (att == null)
            {
                att = new SQLiteColumnAttribute();
            }

            if (att.ClrType == null)
            {
                att.ClrType = property.PropertyType;
            }

            if (string.IsNullOrWhiteSpace(att.Name))
            {
                att.Name = property.Name;
            }

            if (string.IsNullOrWhiteSpace(att.Collation))
            {
                att.Collation = Database.DefaultColumnCollation;
            }

            if (string.IsNullOrWhiteSpace(att.DataType))
            {
                if (typeof(ISQLiteBlobObject).IsAssignableFrom(att.ClrType))
                {
                    att.DataType = SQLiteColumnType.BLOB.ToString();
                }
                else
                {
                    if (att.HasDefaultValue && att.IsDefaultValueIntrinsic && att.DefaultValue is string df)
                    {
                        // https://www.sqlite.org/lang_createtable.html
                        if (IsComputedDefaultValue(df))
                        {
                            att.DataType = SQLiteColumnType.TEXT.ToString();
                            // we need to force this column type options
                            att.BindOptions = att.BindOptions ?? Database.CreateBindOptions();
                            att.BindOptions.DateTimeFormat = SQLiteDateTimeFormat.SQLiteIso8601;
                        }
                    }
                }

                if (string.IsNullOrWhiteSpace(att.DataType))
                {
                    att.DataType = GetDefaultDataType(att.ClrType);
                }
            }

            if (!att._isNullable.HasValue)
            {
                att.IsNullable = att.ClrType.IsNullable() || !att.ClrType.IsValueType;
            }

            if (!att._isReadOnly.HasValue)
            {
                att.IsReadOnly = !property.CanWrite;
            }

            if (att.GetValueExpression == null)
            {
                // equivalent of
                // att.GetValueFunc = (o) => property.GetValue(o);

                var        instanceParameter = Expression.Parameter(typeof(object));
                var        instance          = Expression.Convert(instanceParameter, property.DeclaringType);
                Expression getValue          = Expression.Property(instance, property);
                if (att.ClrType != typeof(object))
                {
                    getValue = Expression.Convert(getValue, typeof(object));
                }
                var lambda = Expression.Lambda <Func <object, object> >(getValue, instanceParameter);
                att.GetValueExpression = lambda;
            }

            if (!att.IsReadOnly && att.SetValueExpression == null && property.SetMethod != null)
            {
                // equivalent of
                // att.SetValueAction = (options, o, v) => {
                //      if (options.TryChangeType(v, typeof(property), options.FormatProvider, out object newv))
                //      {
                //          property.SetValue(o, newv);
                //      }
                //  }

                var optionsParameter  = Expression.Parameter(typeof(SQLiteLoadOptions), "options");
                var instanceParameter = Expression.Parameter(typeof(object), "instance");
                var valueParameter    = Expression.Parameter(typeof(object), "value");
                var instance          = Expression.Convert(instanceParameter, property.DeclaringType);

                var expressions = new List <Expression>();
                var variables   = new List <ParameterExpression>();

                Expression setValue;
                if (att.ClrType != typeof(object))
                {
                    var convertedValue = Expression.Variable(typeof(object), "cvalue");
                    variables.Add(convertedValue);

                    var tryConvert = Expression.Call(
                        optionsParameter,
                        typeof(SQLiteLoadOptions).GetMethod(nameof(SQLiteLoadOptions.TryChangeType), new Type[] { typeof(object), typeof(Type), typeof(object).MakeByRefType() }),
                        valueParameter,
                        Expression.Constant(att.ClrType, typeof(Type)),
                        convertedValue);

                    var ifTrue  = Expression.Call(instance, property.SetMethod, Expression.Convert(convertedValue, att.ClrType));
                    var ifFalse = Expression.Empty();
                    setValue = Expression.Condition(Expression.Equal(tryConvert, Expression.Constant(true)), ifTrue, ifFalse);
                }
                else
                {
                    setValue = Expression.Call(instance, property.SetMethod, valueParameter);
                }

                expressions.Add(setValue);
                var body   = Expression.Block(variables, expressions);
                var lambda = Expression.Lambda <Action <SQLiteLoadOptions, object, object> >(body, optionsParameter, instanceParameter, valueParameter);
                att.SetValueExpression = lambda;
            }

            return(att);
        }