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); }
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()); }
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)),
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)); }