private void WriteToServer(Feeder feeder) { if (this.tableName.Length == 0) { throw new ArgumentException("The name of the destination table hasn't been specified", "DestinationTableName"); } StringBuilder builder = new StringBuilder(); builder.Append("INSERT INTO `"); builder.Append(this.tableName.Replace("`", "``")); builder.Append("` "); if (mappings.Count == 0) { // the target table has the same number and names of the columns as in the specified input rows builder.Append("VALUES ("); for (int i = 0; i < feeder.FieldCount; i++) { if (i != 0) { builder.Append(", "); } builder.Append("?"); } builder.Append(")"); } else { DataRowCollection targetColumns = null; builder.Append(" ("); for (int i = 0; i < mappings.Count; i++) { NuoDbBulkLoaderColumnMapping mapping = mappings[i]; if (i != 0) { builder.Append(", "); } builder.Append("`"); if (mapping.DestinationColumn == null) { // we are requested to map to a target column that is identified with its ordinal number, so // fetch the schema of the target table to find out what is its name if (targetColumns == null) { // split the destination table into its different parts string[] parts = this.tableName.Split(new char[] { '.' }); DataTable targetSchema = this.connection.GetSchema("Columns", new string[] { null, // catalog parts.Length == 2 ? parts[0] : null, // schema parts.Length == 2 ? parts[1] : parts[0] // table }); targetColumns = targetSchema.Rows; } if (mapping.DestinationOrdinal < 0 || mapping.DestinationOrdinal > targetColumns.Count) { throw new IndexOutOfRangeException(String.Format("The specified ordinal of the target column ({0}) is outside the range of the column count ({1}) of table {2}", new object[] { mapping.DestinationOrdinal, targetColumns.Count, this.tableName })); } string columnName = (string)(targetColumns[mapping.DestinationOrdinal]["COLUMN_NAME"]); builder.Append(columnName.Replace("`", "``")); } else { builder.Append(mapping.DestinationColumn.Replace("`", "``")); } builder.Append("`"); } builder.Append(") VALUES ("); for (int i = 0; i < mappings.Count; i++) { if (i != 0) { builder.Append(", "); } builder.Append("?"); } builder.Append(")"); } string sqlString = builder.ToString(); #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDbBulkLoader::WriteToServer: " + sqlString); #endif if (this.connection.State != ConnectionState.Open) { this.connection.Open(); } using (NuoDbCommand command = new NuoDbCommand(sqlString, this.connection)) { command.Prepare(); int totalSize = 0; // do the check for out-of-range values just once foreach (NuoDbBulkLoaderColumnMapping mapping in mappings) { if (mapping.SourceColumn == null && mapping.SourceOrdinal < 0 || mapping.SourceOrdinal > feeder.FieldCount) { throw new IndexOutOfRangeException(String.Format("The specified ordinal of the source column ({0}) is outside the range of the column count ({1})", new object[] { mapping.SourceOrdinal, feeder.FieldCount })); } } while (true) { EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); dataStream.startMessage(Protocol.ExecuteBatchPreparedStatement); dataStream.encodeInt(command.handle); int batchCount = 0; for (; batchCount < this.batchSize && feeder.MoveNext(); batchCount++) { dataStream.encodeInt(command.Parameters.Count); if (mappings.Count == 0) { for (int i = 0; i < feeder.FieldCount; i++) { dataStream.encodeDotNetObject(feeder[i]); } } else { foreach (NuoDbBulkLoaderColumnMapping mapping in mappings) { if (mapping.SourceColumn == null) { dataStream.encodeDotNetObject(feeder[mapping.SourceOrdinal]); } else { dataStream.encodeDotNetObject(feeder[mapping.SourceColumn]); } } } } // the iterator hasn't found any more data to import, let's break out if (batchCount == 0) { break; } dataStream.encodeInt(-1); dataStream.encodeInt(batchCount); totalSize += batchCount; #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDbBulkLoader::WriteToServer: sending a batch of " + batchCount + " rows"); #endif this.connection.InternalConnection.sendAndReceive(dataStream); bool hasErrors = false; string errorMessage = string.Empty; for (int i = 0; i < batchCount; i++) { int result = dataStream.getInt(); if (result == EXECUTE_FAILED) { if (this.connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION6) { int sqlCode = dataStream.getInt(); string message = dataStream.getString(); errorMessage = AppendError(errorMessage, message, i); } hasErrors = true; } } if (this.connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION3) { long txnId = dataStream.getLong(); int nodeId = dataStream.getInt(); long commitSequence = dataStream.getLong(); this.connection.InternalConnection.setLastTransaction(txnId, nodeId, commitSequence); } if (handlers.Count != 0) { BatchProcessedEventHandler[] tmpArray = new BatchProcessedEventHandler[handlers.Count]; handlers.CopyTo(tmpArray); BatchProcessedEventArgs args = new BatchProcessedEventArgs(); args.BatchSize = batchCount; args.TotalSize = totalSize; args.HasErrors = hasErrors; foreach (BatchProcessedEventHandler h in tmpArray) { h.Invoke(this, args); } } if (hasErrors) { throw new NuoDbSqlException(errorMessage, NuoDbSqlCode.FindError("BATCH_UPDATE_ERROR")); } } } }
private void WriteToServer(Feeder feeder) { if (this.tableName.Length == 0) throw new ArgumentException("The name of the destination table hasn't been specified", "DestinationTableName"); StringBuilder builder = new StringBuilder(); builder.Append("INSERT INTO `"); builder.Append(this.tableName.Replace("`", "``")); builder.Append("` "); if (mappings.Count == 0) { // the target table has the same number and names of the columns as in the specified input rows builder.Append("VALUES ("); for (int i = 0; i < feeder.FieldCount; i++) { if (i != 0) builder.Append(", "); builder.Append("?"); } builder.Append(")"); } else { DataRowCollection targetColumns = null; builder.Append(" ("); for(int i=0;i<mappings.Count;i++) { NuoDbBulkLoaderColumnMapping mapping = mappings[i]; if (i != 0) builder.Append(", "); builder.Append("`"); if (mapping.DestinationColumn == null) { // we are requested to map to a target column that is identified with its ordinal number, so // fetch the schema of the target table to find out what is its name if (targetColumns == null) { // split the destination table into its different parts string[] parts = this.tableName.Split(new char[] { '.' }); DataTable targetSchema = this.connection.GetSchema("Columns", new string[] { null, // catalog parts.Length == 2 ? parts[0] : null, // schema parts.Length == 2 ? parts[1] : parts[0] // table }); targetColumns = targetSchema.Rows; } if (mapping.DestinationOrdinal < 0 || mapping.DestinationOrdinal > targetColumns.Count) throw new IndexOutOfRangeException(String.Format("The specified ordinal of the target column ({0}) is outside the range of the column count ({1}) of table {2}", new object[] { mapping.DestinationOrdinal, targetColumns.Count, this.tableName })); string columnName = (string)(targetColumns[mapping.DestinationOrdinal]["COLUMN_NAME"]); builder.Append(columnName.Replace("`", "``")); } else builder.Append(mapping.DestinationColumn.Replace("`", "``")); builder.Append("`"); } builder.Append(") VALUES ("); for (int i = 0; i < mappings.Count; i++) { if (i != 0) builder.Append(", "); builder.Append("?"); } builder.Append(")"); } string sqlString = builder.ToString(); #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDbBulkLoader::WriteToServer: "+sqlString); #endif if (this.connection.State != ConnectionState.Open) this.connection.Open(); using (NuoDbCommand command = new NuoDbCommand(sqlString, this.connection)) { command.Prepare(); int totalSize = 0; // do the check for out-of-range values just once foreach (NuoDbBulkLoaderColumnMapping mapping in mappings) { if (mapping.SourceColumn == null && mapping.SourceOrdinal < 0 || mapping.SourceOrdinal > feeder.FieldCount) throw new IndexOutOfRangeException(String.Format("The specified ordinal of the source column ({0}) is outside the range of the column count ({1})", new object[] { mapping.SourceOrdinal, feeder.FieldCount })); } while (true) { EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); dataStream.startMessage(Protocol.ExecuteBatchPreparedStatement); dataStream.encodeInt(command.handle); int batchCount = 0; for (; batchCount < this.batchSize && feeder.MoveNext(); batchCount++) { dataStream.encodeInt(command.Parameters.Count); if (mappings.Count == 0) { for (int i = 0; i < feeder.FieldCount; i++) { dataStream.encodeDotNetObject(feeder[i]); } } else { foreach (NuoDbBulkLoaderColumnMapping mapping in mappings) { if (mapping.SourceColumn == null) { dataStream.encodeDotNetObject(feeder[mapping.SourceOrdinal]); } else { dataStream.encodeDotNetObject(feeder[mapping.SourceColumn]); } } } } // the iterator hasn't found any more data to import, let's break out if (batchCount == 0) break; dataStream.encodeInt(-1); dataStream.encodeInt(batchCount); totalSize += batchCount; #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDbBulkLoader::WriteToServer: sending a batch of " + batchCount + " rows"); #endif this.connection.InternalConnection.sendAndReceive(dataStream); string firstViolationString = ""; int firstViolation = 0; bool haserrors = false; for (int i = 0; i < batchCount; i++) { int result = dataStream.getInt(); if (result == EXECUTE_FAILED) { if (this.connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION6) { int status = dataStream.getInt(); string s = dataStream.getString(); // Only take the first constraint violation. if (NuoDbSqlCode.FindCode(status).SQLState.Equals("CONSTRAINT_ERROR") && firstViolation == 0) { firstViolation = status; firstViolationString = s; } } haserrors = true; } } if (this.connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION3) { long txnId = dataStream.getLong(); int nodeId = dataStream.getInt(); long commitSequence = dataStream.getLong(); this.connection.InternalConnection.setLastTransaction(txnId, nodeId, commitSequence); } if (handlers.Count != 0) { BatchProcessedEventHandler[] tmpArray = new BatchProcessedEventHandler[handlers.Count]; handlers.CopyTo(tmpArray); BatchProcessedEventArgs args = new BatchProcessedEventArgs(); args.BatchSize = batchCount; args.TotalSize = totalSize; args.HasErrors = haserrors; foreach (BatchProcessedEventHandler h in tmpArray) { h.Invoke(this, args); } } if (haserrors) { if (firstViolation == 0) { throw new NuoDbSqlException("", NuoDbSqlCode.FindError("BATCH_UPDATE_ERROR")); } else { throw new NuoDbSqlException(firstViolationString, NuoDbSqlCode.FindError("BATCH_UPDATE_ERROR")); } } } } }
internal int ExecuteBatch(DataFeeder feed, int maxBatchSize = Int32.MaxValue) { checkConnection(); if (isPrepared) { Close(); } Prepare(false); EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); dataStream.startMessage(Protocol.ExecuteBatchPreparedStatement); dataStream.encodeInt(handle); int batchCount = 0; while (batchCount < maxBatchSize && feed.MoveNext()) { batchCount++; dataStream.encodeInt(feed.FieldCount); for (int i = 0; i < feed.FieldCount; i++) { dataStream.encodeDotNetObject(feed[i]); } } // the iterator hasn't found any more data to import, let's break out if (batchCount > 0) { dataStream.encodeInt(-1); dataStream.encodeInt(batchCount); connection.InternalConnection.sendAndReceive(dataStream); bool hasErrors = false; string errorMessage = string.Empty; for (int i = 0; i < batchCount; i++) { int result = dataStream.getInt(); if (result < 0) { if (connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION6) { int sqlCode = dataStream.getInt(); string message = dataStream.getString(); errorMessage = AppendError(errorMessage, message, i); } hasErrors = true; } } if (connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION3) { long txnId = dataStream.getLong(); int nodeId = dataStream.getInt(); long commitSequence = dataStream.getLong(); connection.InternalConnection.setLastTransaction(txnId, nodeId, commitSequence); } if (hasErrors) { throw new NuoDbSqlException(errorMessage, NuoDbSqlCode.FindError("BATCH_UPDATE_ERROR")); } } return(batchCount); }
internal int ExecuteBatch(DataFeeder feed, int maxBatchSize = Int32.MaxValue) { checkConnection(); if (isPrepared) { Close(); } Prepare(false); EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); dataStream.startMessage(Protocol.ExecuteBatchPreparedStatement); dataStream.encodeInt(handle); int batchCount = 0; while (batchCount < maxBatchSize && feed.MoveNext()) { batchCount++; dataStream.encodeInt(feed.FieldCount); for (int i = 0; i < feed.FieldCount; i++) { dataStream.encodeDotNetObject(feed[i]); } } // the iterator hasn't found any more data to import, let's break out if (batchCount > 0) { dataStream.encodeInt(-1); dataStream.encodeInt(batchCount); connection.InternalConnection.sendAndReceive(dataStream); bool hasErrors = false; string errorMessage = string.Empty; for (int i = 0; i < batchCount; i++) { int result = dataStream.getInt(); if (result < 0) { if (connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION6) { int sqlCode = dataStream.getInt(); string message = dataStream.getString(); errorMessage = AppendError(errorMessage, message, i); } hasErrors = true; } } if (connection.InternalConnection.protocolVersion >= Protocol.PROTOCOL_VERSION3) { long txnId = dataStream.getLong(); int nodeId = dataStream.getInt(); long commitSequence = dataStream.getLong(); connection.InternalConnection.setLastTransaction(txnId, nodeId, commitSequence); } if (hasErrors) throw new NuoDbSqlException(errorMessage, NuoDbSqlCode.FindError("BATCH_UPDATE_ERROR")); } return batchCount; }