private (NpgsqlProviderAdapter.NpgsqlDbType?[] npgsqlTypes, string?[] dbTypes, DbDataType[] columnTypes) BuildTypes(
            NpgsqlProviderAdapter adapter,
            PostgreSQLSqlBuilder sqlBuilder,
            ColumnDescriptor[]    columns)
        {
            var npgsqlTypes = new NpgsqlProviderAdapter.NpgsqlDbType?[columns.Length];
            var dbTypes     = new string?[columns.Length];
            var columnTypes = new DbDataType[columns.Length];

            for (var i = 0; i < columns.Length; i++)
            {
                dbTypes[i]     = columns[i].DbType;
                columnTypes[i] = columns[i].GetDbDataType(true);
                var npgsqlType = _provider.GetNativeType(columns[i].DbType, true);
                if (npgsqlType == null)
                {
                    var sb = new System.Text.StringBuilder();
                    sqlBuilder.BuildTypeName(sb, new SqlQuery.SqlDataType(columnTypes[i]));
                    npgsqlType = _provider.GetNativeType(sb.ToString(), true);
                }

                npgsqlTypes[i] = npgsqlType;

                if (npgsqlType == null && dbTypes[i] == null)
                {
                    throw new LinqToDBException($"Cannot guess PostgreSQL type for column {columns[i].ColumnName}. Specify type explicitly in column mapping.");
                }
            }

            return(npgsqlTypes, dbTypes, columnTypes);
        }
Exemple #2
0
        public Action <MappingSchema, NpgsqlBinaryImporter, ColumnDescriptor[], TEntity> CreateBinaryImportRowWriter <TEntity>(
            PostgreSQLDataProvider provider,
            BasicSqlBuilder sqlBuilder,
            ColumnDescriptor[] columns,
            MappingSchema mappingSchema)
        {
            var generator = new ExpressionGenerator(_typeMapper);

            var pMapping  = Expression.Parameter(typeof(MappingSchema));
            var pWriterIn = Expression.Parameter(typeof(NpgsqlBinaryImporter));
            var pColumns  = Expression.Parameter(typeof(ColumnDescriptor[]));
            var pEntity   = Expression.Parameter(typeof(TEntity));

            var pWriter = generator.AddVariable(Expression.Parameter(_npgsqlBinaryImporterType));

            generator.Assign(pWriter, Expression.Convert(ExpressionHelper.Property(pWriterIn, nameof(TypeWrapper.instance_)), _npgsqlBinaryImporterType));

            generator.AddExpression(generator.MapAction((NpgsqlBinaryImporter importer) => importer.StartRow(), pWriter));

            for (var i = 0; i < columns.Length; i++)
            {
                var npgsqlType = provider.GetNativeType(columns[i].DbType, true);
                if (npgsqlType == null)
                {
                    var columnType = columns[i].DataType != DataType.Undefined ? new SqlDataType(columns[i]) : null;

                    if (columnType == null || columnType.Type.DataType == DataType.Undefined)
                    {
                        columnType = mappingSchema.GetDataType(columns[i].StorageType);
                    }

                    var sb = new StringBuilder();
                    sqlBuilder.BuildTypeName(sb, columnType);
                    npgsqlType = provider.GetNativeType(sb.ToString(), true);
                }

                if (npgsqlType == null)
                {
                    throw new LinqToDBException($"Cannot guess PostgreSQL type for column {columns[i].ColumnName}. Specify type explicitly in column mapping.");
                }

                // don't use WriteNull because Write already handle both null and DBNull values properly
                // also use object as type parameter, as it is not important for npgsql now
                generator.AddExpression(
                    Expression.Call(
                        pWriter,
                        "Write",
                        new[] { typeof(object) },
                        //columns[idx].GetValue(mappingSchema, entity)
                        Expression.Call(Expression.ArrayIndex(pColumns, Expression.Constant(i)), "GetValue", Array <Type> .Empty, pMapping, pEntity),
                        Expression.Convert(Expression.Constant(npgsqlType.Value), _dbTypeType)));
            }

            var ex = Expression.Lambda <Action <MappingSchema, NpgsqlBinaryImporter, ColumnDescriptor[], TEntity> >(
                generator.Build(),
                pMapping, pWriterIn, pColumns, pEntity);

            return(ex.Compile());
        }
Exemple #3
0
        private Action <MappingSchema, object, ColumnDescriptor[], TEntity> BuildRowWriter <TEntity>(
            Type writerType,
            ColumnDescriptor[] columns,
            MappingSchema mappingSchema)
        {
            var pMapping = Expression.Parameter(typeof(MappingSchema));
            var pWriter  = Expression.Parameter(typeof(object));
            var pColumns = Expression.Parameter(typeof(ColumnDescriptor[]));
            var pEntity  = Expression.Parameter(typeof(TEntity));

            var writerVar = Expression.Variable(writerType);
            var exprs     = new List <Expression>();

            exprs.Add(Expression.Assign(writerVar, Expression.Convert(pWriter, writerType)));
            exprs.Add(Expression.Call(writerVar, "StartRow", Array <Type> .Empty));

            var builder = (BasicSqlBuilder)_dataProvider.CreateSqlBuilder();

            for (var i = 0; i < columns.Length; i++)
            {
                var npgsqlType = _dataProvider.GetNativeType(columns[i].DbType);
                if (npgsqlType == null)
                {
                    var columnType = columns[i].DataType != DataType.Undefined ? new SqlDataType(columns[i].DataType) : null;

                    if (columnType == null || columnType.DataType == DataType.Undefined)
                    {
                        columnType = mappingSchema.GetDataType(columns[i].StorageType);
                    }

                    var sb = new StringBuilder();
                    builder.BuildTypeName(sb, columnType);
                    npgsqlType = _dataProvider.GetNativeType(sb.ToString());
                }

                if (npgsqlType == null)
                {
                    throw new LinqToDBException($"Cannot guess PostgreSQL type for column {columns[i].ColumnName}. Specify type explicitly in column mapping.");
                }

                // don't use WriteNull because Write already handle both null and DBNull values properly
                exprs.Add(Expression.Call(
                              writerVar,
                              "Write",
                              new[] { typeof(object) },
                              Expression.Call(
                                  Expression.ArrayIndex(pColumns, Expression.Constant(i)),
                                  MemberHelper.MethodOf((ColumnDescriptor cd) => cd.GetValue(default, default)),
Exemple #4
0
        private BulkCopyRowsCopied ProviderSpecificCopyImpl <T>(DataConnection dataConnection, ITable <T> table, BulkCopyOptions options, IEnumerable <T> source)
        {
            var connection = _provider.TryGetProviderConnection(dataConnection.Connection, dataConnection.MappingSchema);

            if (connection == null)
            {
                return(MultipleRowsCopy(table, options, source));
            }

            var sqlBuilder = (BasicSqlBuilder)_provider.CreateSqlBuilder(dataConnection.MappingSchema);
            var ed         = dataConnection.MappingSchema.GetEntityDescriptor(typeof(T));
            var tableName  = GetTableName(sqlBuilder, options, table);
            var columns    = ed.Columns.Where(c => !c.SkipOnInsert || options.KeepIdentity == true && c.IsIdentity).ToArray();

            var npgsqlTypes = new NpgsqlProviderAdapter.NpgsqlDbType[columns.Length];

            for (var i = 0; i < columns.Length; i++)
            {
                var npgsqlType = _provider.GetNativeType(columns[i].DbType, true);
                if (npgsqlType == null)
                {
                    var columnType = columns[i].DataType != DataType.Undefined ? new SqlQuery.SqlDataType(columns[i]) : null;

                    if (columnType == null || columnType.Type.DataType == DataType.Undefined)
                    {
                        columnType = columns[i].MappingSchema.GetDataType(columns[i].StorageType);
                    }

                    var sb = new System.Text.StringBuilder();
                    sqlBuilder.BuildTypeName(sb, columnType);
                    npgsqlType = _provider.GetNativeType(sb.ToString(), true);
                }

                if (npgsqlType == null)
                {
                    throw new LinqToDBException($"Cannot guess PostgreSQL type for column {columns[i].ColumnName}. Specify type explicitly in column mapping.");
                }

                npgsqlTypes[i] = npgsqlType.Value;
            }

            var fields      = string.Join(", ", columns.Select(column => sqlBuilder.ConvertInline(column.ColumnName, ConvertType.NameToQueryField)));
            var copyCommand = $"COPY {tableName} ({fields}) FROM STDIN (FORMAT BINARY)";

            // batch size numbers not based on any strong grounds as I didn't found any recommendations for it
            var batchSize = Math.Max(10, options.MaxBatchSize ?? 10000);

            var useComplete = _provider.Adapter.BinaryImporterHasComplete;
            var writer      = _provider.Adapter.BeginBinaryImport(connection, copyCommand);

            return(ProviderSpecificCopySyncImpl(dataConnection, options, source, connection, tableName, columns, npgsqlTypes, copyCommand, batchSize, useComplete, writer));
        }