// call PQexec internal ExecStatusType Exec(byte[] stmt, out IntPtr res) { if (mConnection == IntPtr.Zero) { res = IntPtr.Zero; return(ExecStatusType.PGRES_FATAL_ERROR); } unsafe { fixed(byte *st = stmt) { res = PqsqlWrapper.PQexec(mConnection, st); } } ExecStatusType s = ExecStatusType.PGRES_FATAL_ERROR; if (res != IntPtr.Zero) { s = PqsqlWrapper.PQresultStatus(res); } return(s); }
public void End() { IntPtr res; string err = string.Empty; #if CODECONTRACTS Contract.Assume(mConn != null); #endif IntPtr conn = mConn.PGConnection; if (mColBuf == IntPtr.Zero) { return; } int ret = PqsqlBinaryFormat.pqcb_put_end(mColBuf); // flush column buffer if (ret != 1) { err = err.Insert(0, "Could not send end-of-data indication: "); goto bailout; } res = PqsqlWrapper.PQgetResult(conn); if (res != IntPtr.Zero) { ExecStatusType s = PqsqlWrapper.PQresultStatus(res); PqsqlWrapper.PQclear(res); if (s == ExecStatusType.PGRES_COPY_IN) { // still in COPY_IN mode? bail out! byte[] b = PqsqlUTF8Statement.CreateUTF8Statement("COPY FROM cancelled by client"); unsafe { fixed(byte *bs = b) { ret = PqsqlWrapper.PQputCopyEnd(conn, bs); } } res = PqsqlWrapper.PQgetResult(conn); if (res != IntPtr.Zero) { s = PqsqlWrapper.PQresultStatus(res); PqsqlWrapper.PQclear(res); } err = err.Insert(0, "Cancelled COPY FROM while still in COPY_IN mode (" + s + "," + ret + "): "); goto bailout; } if (s != ExecStatusType.PGRES_COMMAND_OK) { err = err.Insert(0, "COPY FROM failed (" + s + "): "); goto bailout; } // consume all remaining results until we reach the NULL result while ((res = PqsqlWrapper.PQgetResult(conn)) != IntPtr.Zero) { // always free mResult PqsqlWrapper.PQclear(res); } return; } bailout: err += mConn.GetErrorMessage(); throw new PqsqlException(err); }
private static bool CheckOrRelease(IntPtr pgConn, out ConnStatusType connStatus, out PGTransactionStatusType tranStatus) { if (pgConn == IntPtr.Zero) { connStatus = ConnStatusType.CONNECTION_BAD; tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; return(false); } // is connection reusable? connStatus = PqsqlWrapper.PQstatus(pgConn); if (connStatus != ConnStatusType.CONNECTION_OK) { goto broken; } tranStatus = PqsqlWrapper.PQtransactionStatus(pgConn); if (tranStatus != PGTransactionStatusType.PQTRANS_IDLE) { goto broken; } // // now check the connection: first try to fix the client encoding if it is not utf8 for some reason. // if client_encoding is utf8, we send the empty query to check whether the socket is still usable // for the backend communiction. here, we could make use of tcp_keepalive settings. // int client_encoding = PqsqlWrapper.PQclientEncoding(pgConn); if (client_encoding == -1) { goto broken; } if (client_encoding == (int)PgEnc.PG_UTF8) // client_encoding == utf8 { // send empty query to test whether we are really connected (tcp_keepalive might have closed socket) unsafe { byte[] empty = { 0 }; // empty query string fixed(byte *eq = empty) { if (PqsqlWrapper.PQsendQuery(pgConn, eq) == 0) // could not send query { goto broken; } } } // Reading result: consume and clear remaining results until we reach the NULL result. // PQgetResult will block here IntPtr res; ExecStatusType st = ExecStatusType.PGRES_EMPTY_QUERY; while ((res = PqsqlWrapper.PQgetResult(pgConn)) != IntPtr.Zero) { ExecStatusType st0 = PqsqlWrapper.PQresultStatus(res); if (st0 != ExecStatusType.PGRES_EMPTY_QUERY) { st = st0; } // always free res PqsqlWrapper.PQclear(res); } if (st != ExecStatusType.PGRES_EMPTY_QUERY) // received wrong exec status { goto broken; } } else // set client_encoding to utf8 { // set client_encoding to test whether we are really connected (tcp_keepalive might have closed socket) if (PqsqlWrapper.PQsetClientEncoding(pgConn, PgEncName.PG_UTF8) != 0) { goto broken; } } return(true); // successfully reused connection broken: // reconnect with current connection setting PqsqlWrapper.PQreset(pgConn); connStatus = PqsqlWrapper.PQstatus(pgConn); if (connStatus == ConnStatusType.CONNECTION_OK) { tranStatus = PqsqlWrapper.PQtransactionStatus(pgConn); if (tranStatus == PGTransactionStatusType.PQTRANS_IDLE) { return(true); // successfully reconnected } } else { tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; } // could not reconnect: finally give up and clean up memory PqsqlWrapper.PQfinish(pgConn); return(false); }
private static bool DiscardConnection(IntPtr conn) { if (conn == IntPtr.Zero) { return(false); } bool rollback = false; ConnStatusType cs = PqsqlWrapper.PQstatus(conn); if (cs != ConnStatusType.CONNECTION_OK) { return(false); // connection broken } PGTransactionStatusType ts = PqsqlWrapper.PQtransactionStatus(conn); switch (ts) { case PGTransactionStatusType.PQTRANS_INERROR: /* idle, within failed transaction */ case PGTransactionStatusType.PQTRANS_INTRANS: /* idle, within transaction block */ rollback = true; break; case PGTransactionStatusType.PQTRANS_IDLE: /* connection idle */ // nothing to do break; // PGTransactionStatusType.PQTRANS_ACTIVE: /* command in progress */ // PGTransactionStatusType.PQTRANS_UNKNOWN: /* cannot determine status */ default: return(false); // connection broken } IntPtr res; ExecStatusType s = ExecStatusType.PGRES_FATAL_ERROR; // we need to rollback before we can discard the connection if (rollback) { unsafe { fixed(byte *st = PqsqlTransaction.RollbackStatement) { res = PqsqlWrapper.PQexec(conn, st); if (res != IntPtr.Zero) { s = PqsqlWrapper.PQresultStatus(res); PqsqlWrapper.PQclear(res); } } } if (s != ExecStatusType.PGRES_COMMAND_OK) { return(false); // connection broken } s = ExecStatusType.PGRES_FATAL_ERROR; } // discard connection unsafe { fixed(byte *st = DiscardAllStatement) { res = PqsqlWrapper.PQexec(conn, st); if (res != IntPtr.Zero) { s = PqsqlWrapper.PQresultStatus(res); PqsqlWrapper.PQclear(res); } } } if (s != ExecStatusType.PGRES_COMMAND_OK) { return(false); // connection broken } return(true); // connection successfully resetted }
protected string Error() { IntPtr res; string err = string.Empty; IntPtr conn = mConn.PGConnection; res = PqsqlWrapper.PQgetResult(conn); if (res != IntPtr.Zero) { ExecStatusType s = PqsqlWrapper.PQresultStatus(res); PqsqlWrapper.PQclear(res); if (s == ExecStatusType.PGRES_COPY_IN || s == ExecStatusType.PGRES_COPY_OUT) { if (s == ExecStatusType.PGRES_COPY_IN) { // still in COPY_IN mode? bail out! byte[] b = PqsqlUTF8Statement.CreateUTF8Statement("COPY cancelled by client"); int end; unsafe { fixed(byte *bs = b) { end = PqsqlWrapper.PQputCopyEnd(conn, bs); } } if (end != 1) { err = err.Insert(0, "Cannot cancel COPY (" + s + "): "); goto bailout; } } res = PqsqlWrapper.PQgetResult(conn); if (res != IntPtr.Zero) { s = PqsqlWrapper.PQresultStatus(res); PqsqlWrapper.PQclear(res); } } if (s != ExecStatusType.PGRES_COMMAND_OK) { err = err.Insert(0, "COPY failed (" + s + "): "); goto bailout; } // consume all remaining results until we reach the NULL result while ((res = PqsqlWrapper.PQgetResult(conn)) != IntPtr.Zero) { // always free mResult PqsqlWrapper.PQclear(res); } return(err); } bailout: err += mConn.GetErrorMessage(); return(err); }