static bool prepare_common(int lineno, struct connection *con, const char *name, const char *variable) { struct statement *stmt; struct prepared_statement *this; PGresult *query; /* allocate new statement */ this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno); if (!this) return false; stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno); if (!stmt) { ecpg_free(this); return false; } memset(stmt, 0, sizeof(struct statement)); /* create statement */ stmt->lineno = lineno; stmt->connection = con; stmt->command = ecpg_strdup(variable, lineno); stmt->inlist = stmt->outlist = NULL; /* if we have C variables in our statement replace them with '?' */ replace_variables(&(stmt->command), lineno); /* add prepared statement to our list */ this->name = ecpg_strdup(name, lineno); this->stmt = stmt; /* and finally really prepare the statement */ query = PQprepare(stmt->connection->connection, name, stmt->command, 0, NULL); if (!ecpg_check_PQresult(query, stmt->lineno, stmt->connection->connection, stmt->compat)) { ecpg_free(stmt->command); ecpg_free(this->name); ecpg_free(this); ecpg_free(stmt); return false; } ecpg_log("prepare_common on line %d: name %s; query: \"%s\"\n", stmt->lineno, name, stmt->command); PQclear(query); this->prepared = true; if (con->prep_stmts == NULL) this->next = NULL; else this->next = con->prep_stmts; con->prep_stmts = this; return true; }
bool ECPGtrans(int lineno, const char *connection_name, const char *transaction) { PGresult *res; struct connection *con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) return false; ecpg_log("ECPGtrans on line %d: action \"%s\"; connection \"%s\"\n", lineno, transaction, con ? con->name : "null"); /* if we have no connection we just simulate the command */ if (con && con->connection) { /* * If we got a transaction command but have no open transaction, we * have to start one, unless we are in autocommit, where the * developers have to take care themselves. However, if the command is * a begin statement, we just execute it once. And if the command is * commit or rollback prepared, we don't execute it. */ if (PQtransactionStatus(con->connection) == PQTRANS_IDLE && !con->autocommit && strncmp(transaction, "begin", 5) != 0 && strncmp(transaction, "start", 5) != 0 && strncmp(transaction, "commit prepared", 15) != 0 && strncmp(transaction, "rollback prepared", 17) != 0) { res = PQexec(con->connection, "begin transaction"); if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(res); } res = PQexec(con->connection, transaction); if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(res); } return true; }
bool ECPGsetcommit(int lineno, const char *mode, const char *connection_name) { struct connection *con = ecpg_get_connection(connection_name); PGresult *results; if (!ecpg_init(con, connection_name, lineno)) return (false); ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name); if (con->autocommit == true && strncmp(mode, "off", strlen("off")) == 0) { if (con->committed) { results = PQexec(con->connection, "begin transaction"); if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(results); con->committed = false; } con->autocommit = false; } else if (con->autocommit == false && strncmp(mode, "on", strlen("on")) == 0) { if (!con->committed) { results = PQexec(con->connection, "commit"); if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(results); con->committed = true; } con->autocommit = true; } return true; }