public DataRowColumnSUKSWithConnectionFunctionality( DataColumnMetaData metadata, Int32 thisStreamIndex, ResizableArray <Byte> byteArray, DataRowColumnSUKS[] allDataRowStreams, TConnectionFunctionality connectionFunctionality, ReservedForStatement reservedForStatement ) : base(metadata, thisStreamIndex, byteArray, allDataRowStreams) { this.ConnectionFunctionality = ArgumentValidator.ValidateNotNull(nameof(connectionFunctionality), connectionFunctionality); this.ReservedForStatement = ArgumentValidator.ValidateNotNull(nameof(reservedForStatement), reservedForStatement); }
public PgSQLDataRowStream( PgSQLDataColumnMetaDataImpl metadata, Int32 thisStreamIndex, PgSQLDataRowStream[] allDataRowStreams, PostgreSQLProtocol protocol, ReservedForStatement reservedForStatement, RowDescription rowDescription ) : base(metadata, thisStreamIndex, protocol.Buffer, allDataRowStreams, protocol, reservedForStatement) { var fieldInfo = rowDescription.Fields[thisStreamIndex]; this._dataFormat = fieldInfo.DataFormat; }
protected override async Task <TStatementExecutionSimpleTaskParameter> ExecuteStatementAsBatch(StatementBuilder statement, ReservedForStatement reservedState) { // TODO somehow make statement name and chunk size parametrizable (var parameterIndices, var typeInfos, var typeIDs) = GetVariablesForExtendedQuerySequence(statement, this.TypeRegistry, (stmt, idx) => stmt.GetBatchParameterInfo(0, idx)); var ioArgs = this.GetIOArgs(); var stmtName = ((PgReservedForStatement)reservedState).StatementName; var chunkSize = 1000; // Send a parse message with statement name await new ParseMessage(statement.SQL, parameterIndices, typeIDs, stmtName).SendMessageAsync(ioArgs, true); // Now send describe message await new DescribeMessage(true, stmtName).SendMessageAsync(ioArgs, true); // And then Flush message for backend to send responses await FrontEndMessageWithNoContent.FLUSH.SendMessageAsync(ioArgs, false); // Receive first batch of messages BackendMessageObject msg = null; SQLStatementExecutionResult current = null; List <PgSQLError> notices = new List <PgSQLError>(); var sendBatch = true; while (msg == null) { msg = (await this.ReadMessagesUntilMeaningful(notices)).Item1; switch (msg) { case MessageWithNoContents nc: switch (nc.Code) { case BackendMessageCode.ParseComplete: // Continue reading messages msg = null; break; case BackendMessageCode.EmptyQueryResponse: // The statement does not produce any data, we are done sendBatch = false; break; case BackendMessageCode.NoData: // Do nothing, thus causing batch messages to be sent break; default: throw new PgSQLException("Unrecognized response at this point: " + msg.Code); } break; case RowDescription rd: throw new PgSQLException("Batch statements may only be used for non-query statements."); case ParameterDescription pd: if (!ArrayEqualityComparer <Int32> .ArrayEquality(pd.ObjectIDs, typeIDs)) { throw new PgSQLException("Backend required certain amount of parameters, but either they were not supplied, or were of wrong type."); } // Continue to RowDescription/NoData message msg = null; break; default: throw new PgSQLException("Unrecognized response at this point: " + msg.Code); } } if (sendBatch) { var batchCount = statement.BatchParameterCount; var affectedRowsArray = new Int32[batchCount]; // Send and receive messages asynchronously var commandTag = new String[1]; await Task.WhenAll( this.SendMessagesForBatch( statement, typeInfos, stmtName, ioArgs, chunkSize, batchCount ), this.ReceiveMessagesForBatch( notices, affectedRowsArray, commandTag ) ); current = new BatchCommandExecutionResultImpl( commandTag[0], new Lazy <SQLException[]>(() => notices?.Select(n => new PgSQLException(n))?.ToArray()), affectedRowsArray ); } return(current, null); }
protected abstract Task <TStatementExecutionSimpleTaskParameter> ExecuteStatementAsBatch(StatementBuilder stmt, ReservedForStatement reservedState);
protected override async Task <TStatementExecutionSimpleTaskParameter> ExecuteStatement(StatementBuilder stmt, ReservedForStatement reservationObject) { Task <TStatementExecutionSimpleTaskParameter> retValTask; if (stmt.HasBatchParameters()) { retValTask = this.ExecuteStatementAsBatch(stmt, reservationObject); } else if (stmt.SQLParameterCount > 0) { retValTask = this.ExecuteStatementAsPrepared(stmt, reservationObject); } else { retValTask = this.ExecuteStatementAsSimple(stmt, reservationObject); } return(await retValTask); }