static char *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *len) { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; char *id = NULL; PGresult *res; ExecStatusType status; if (name == NULL) { res = PQexec(H->server, "SELECT LASTVAL()"); } else { const char *q[1]; q[0] = name; res = PQexecParams(H->server, "SELECT CURRVAL($1)", 1, NULL, q, NULL, NULL, 0); } status = PQresultStatus(res); if (res && (status == PGRES_TUPLES_OK)) { id = estrdup((char *)PQgetvalue(res, 0, 0)); *len = PQgetlength(res, 0, 0); } else { pdo_pgsql_error(dbh, status, pdo_pgsql_sqlstate(res)); } if (res) { PQclear(res); } return id; }
static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len) { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; PGresult *res; zend_long ret = 1; ExecStatusType qs; if (!(res = PQexec(H->server, sql))) { /* fatal error */ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); return -1; } qs = PQresultStatus(res); if (qs != PGRES_COMMAND_OK && qs != PGRES_TUPLES_OK) { pdo_pgsql_error(dbh, qs, pdo_pgsql_sqlstate(res)); PQclear(res); return -1; } H->pgoid = PQoidValue(res); if (qs == PGRES_COMMAND_OK) { ZEND_ATOL(ret, PQcmdTuples(res)); } else { ret = Z_L(0); } PQclear(res); return ret; }
static int pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh) { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; PGresult *res; int ret = 1; res = PQexec(H->server, cmd); if (PQresultStatus(res) != PGRES_COMMAND_OK) { pdo_pgsql_error(dbh, PQresultStatus(res), pdo_pgsql_sqlstate(res)); ret = 0; } PQclear(res); return ret; }
static int pgsql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; if (S->cursor_name) { char *ori_str = NULL; char *q = NULL; ExecStatusType status; switch (ori) { case PDO_FETCH_ORI_NEXT: spprintf(&ori_str, 0, "NEXT"); break; case PDO_FETCH_ORI_PRIOR: spprintf(&ori_str, 0, "BACKWARD"); break; case PDO_FETCH_ORI_FIRST: spprintf(&ori_str, 0, "FIRST"); break; case PDO_FETCH_ORI_LAST: spprintf(&ori_str, 0, "LAST"); break; case PDO_FETCH_ORI_ABS: spprintf(&ori_str, 0, "ABSOLUTE %pd", offset); break; case PDO_FETCH_ORI_REL: spprintf(&ori_str, 0, "RELATIVE %pd", offset); break; default: return 0; } spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name); efree(ori_str); S->result = PQexec(S->H->server, q); efree(q); status = PQresultStatus(S->result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result)); return 0; } if (PQntuples(S->result)) { S->current_row = 1; return 1; } else { return 0; } } else { if (S->current_row < stmt->row_count) { S->current_row++; return 1; } else { return 0; } } }
static int pgsql_stmt_execute(pdo_stmt_t *stmt) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; pdo_pgsql_db_handle *H = S->H; ExecStatusType status; /* ensure that we free any previous unfetched results */ if(S->result) { PQclear(S->result); S->result = NULL; } S->current_row = 0; if (S->cursor_name) { char *q = NULL; if (S->is_prepared) { spprintf(&q, 0, "CLOSE %s", S->cursor_name); S->result = PQexec(H->server, q); efree(q); } spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, stmt->active_query_string); S->result = PQexec(H->server, q); efree(q); /* check if declare failed */ status = PQresultStatus(S->result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result)); return 0; } /* the cursor was declared correctly */ S->is_prepared = 1; /* fetch to be able to get the number of tuples later, but don't advance the cursor pointer */ spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name); S->result = PQexec(H->server, q); efree(q); } else if (S->stmt_name) { /* using a prepared statement */ if (!S->is_prepared) { stmt_retry: /* we deferred the prepare until now, because we didn't * know anything about the parameter types; now we do */ S->result = PQprepare(H->server, S->stmt_name, S->query, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, S->param_types); status = PQresultStatus(S->result); switch (status) { case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: /* it worked */ S->is_prepared = 1; PQclear(S->result); break; default: { char *sqlstate = pdo_pgsql_sqlstate(S->result); /* 42P05 means that the prepared statement already existed. this can happen if you use * a connection pooling software line pgpool which doesn't close the db-connection once * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we * deallocate it and retry ONCE (thies 2005.12.15) */ if (sqlstate && !strcmp(sqlstate, "42P05")) { char buf[100]; /* stmt_name == "pdo_crsr_%08x" */ PGresult *res; snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name); res = PQexec(H->server, buf); if (res) { PQclear(res); } goto stmt_retry; } else { pdo_pgsql_error_stmt(stmt, status, sqlstate); return 0; } } } } S->result = PQexecPrepared(H->server, S->stmt_name, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, (const char**)S->param_values, S->param_lengths, S->param_formats, 0); } else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) { /* execute query with parameters */ S->result = PQexecParams(H->server, S->query, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, S->param_types, (const char**)S->param_values, S->param_lengths, S->param_formats, 0); } else { /* execute plain query (with embedded parameters) */ S->result = PQexec(H->server, stmt->active_query_string); } status = PQresultStatus(S->result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result)); return 0; } if (!stmt->executed && (!stmt->column_count || S->cols == NULL)) { stmt->column_count = (int) PQnfields(S->result); S->cols = ecalloc(stmt->column_count, sizeof(pdo_pgsql_column)); } if (status == PGRES_COMMAND_OK) { ZEND_ATOL(stmt->row_count, PQcmdTuples(S->result)); H->pgoid = PQoidValue(S->result); } else { stmt->row_count = (zend_long)PQntuples(S->result); } return 1; }