mirror of
https://github.com/php/php-src.git
synced 2024-09-23 19:07:26 +00:00
310 lines
7.5 KiB
C
310 lines
7.5 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 5 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2004 The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.0 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_0.txt. |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Author: Ard Biesheuvel <abies@php.net> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
/* $Id$ */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "php.h"
|
|
#include "php_ini.h"
|
|
#include "ext/standard/info.h"
|
|
#include "pdo/php_pdo.h"
|
|
#include "pdo/php_pdo_driver.h"
|
|
#include "php_pdo_firebird.h"
|
|
#include "php_pdo_firebird_int.h"
|
|
|
|
static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
ISC_STATUS *s = H->isc_status;
|
|
char buf[128];
|
|
|
|
add_next_index_long(info, isc_sqlcode(s));
|
|
|
|
while (isc_interprete(buf,&s)) {
|
|
add_next_index_string(info, buf, 1);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
|
|
if (dbh->in_txn) {
|
|
if (dbh->auto_commit) {
|
|
if (isc_commit_transaction(H->isc_status, &H->tr)) {
|
|
/* error */
|
|
}
|
|
} else {
|
|
if (isc_rollback_transaction(H->isc_status, &H->tr)) {
|
|
/* error */
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isc_detach_database(H->isc_status, &H->db)) {
|
|
/* error */
|
|
}
|
|
|
|
pefree(H, dbh->is_persistent);
|
|
|
|
return 0;
|
|
}
|
|
/* }}} */
|
|
|
|
static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt,
|
|
long options, zval *driver_options TSRMLS_DC)
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
pdo_firebird_stmt *S = NULL;
|
|
|
|
do {
|
|
isc_stmt_handle s = NULL;
|
|
XSQLDA num_sqlda;
|
|
|
|
num_sqlda.version = PDO_FB_SQLDA_VERSION;
|
|
num_sqlda.sqln = 1;
|
|
|
|
/* prepare the statement */
|
|
if (isc_dsql_prepare(H->isc_status, &H->tr, &s, (short)sql_len, /* sigh */ (char*) sql,
|
|
PDO_FB_DIALECT, &num_sqlda)) {
|
|
/* error */
|
|
break;
|
|
}
|
|
|
|
/* allocate a statement handle of the right size */
|
|
S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld));
|
|
S->H = H;
|
|
S->stmt = s;
|
|
|
|
if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, S->out_sqlda)) {
|
|
/* error */
|
|
break;
|
|
}
|
|
|
|
/* TODO what about input params */
|
|
|
|
stmt->driver_data = S;
|
|
stmt->methods = &firebird_stmt_methods;
|
|
|
|
return 1;
|
|
|
|
} while (0);
|
|
|
|
if (S) {
|
|
efree(S);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
isc_stmt_handle stmt = NULL;
|
|
static char info_count[] = { isc_info_sql_records };
|
|
char result[64];
|
|
int ret = 0;
|
|
|
|
if (dbh->auto_commit && !dbh->in_txn) {
|
|
if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, 0, NULL)) {
|
|
/* error */
|
|
return -1;
|
|
}
|
|
dbh->in_txn = 1;
|
|
}
|
|
|
|
/* prepare */
|
|
if (isc_dsql_prepare(H->isc_status, &H->tr, &stmt, 0, (char*) sql, PDO_FB_DIALECT, NULL)) {
|
|
/* error */
|
|
return -1;
|
|
}
|
|
|
|
/* execute */
|
|
if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, NULL, NULL)) {
|
|
/* error */
|
|
return -1;
|
|
}
|
|
|
|
/* return the number of affected rows */
|
|
if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), info_count, sizeof(result),
|
|
result)) {
|
|
/* error */
|
|
return -1;
|
|
}
|
|
|
|
if (result[0] == isc_info_sql_records) {
|
|
unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
|
|
|
|
while (result[i] != isc_info_end && i < result_size) {
|
|
short len = (short)isc_vax_integer(&result[i+1],2);
|
|
if (result[i] != isc_info_req_select_count) {
|
|
ret += isc_vax_integer(&result[i+3],len);
|
|
}
|
|
i += len+3;
|
|
}
|
|
}
|
|
|
|
/* commit? */
|
|
if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
|
|
/* error */
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
|
|
if (isc_commit_transaction(H->isc_status, &H->tr)) {
|
|
/* error */
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
|
|
if (isc_rollback_transaction(H->isc_status, &H->tr)) {
|
|
/* error */
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
|
|
{
|
|
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
|
|
|
switch (attr) {
|
|
|
|
case PDO_ATTR_AUTOCOMMIT:
|
|
|
|
if (dbh->in_txn) {
|
|
/* Assume they want to commit whatever is outstanding */
|
|
if (isc_commit_retaining(H->isc_status, &H->tr)) {
|
|
/* error */
|
|
return 0;
|
|
}
|
|
dbh->in_txn = 0;
|
|
}
|
|
|
|
convert_to_long(val);
|
|
|
|
dbh->auto_commit = Z_LVAL_P(val);
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static struct pdo_dbh_methods firebird_methods = {
|
|
firebird_handle_closer,
|
|
firebird_handle_preparer,
|
|
firebird_handle_doer,
|
|
NULL,
|
|
NULL,
|
|
firebird_handle_commit,
|
|
firebird_handle_rollback,
|
|
firebird_handle_set_attribute,
|
|
NULL,
|
|
pdo_firebird_fetch_error_func,
|
|
};
|
|
|
|
static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
|
|
{
|
|
struct pdo_data_src_parser vars[] = {
|
|
{ "dbname", NULL, 0 },
|
|
{ "charset", NULL, 0 },
|
|
{ "role", NULL, 0 }
|
|
};
|
|
int i, ret = 0;
|
|
pdo_firebird_db_handle *H = dbh->driver_data = pecalloc(1,sizeof(*H),dbh->is_persistent);
|
|
|
|
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2);
|
|
|
|
do {
|
|
static char const dpb_flags[] = {
|
|
isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name };
|
|
char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval };
|
|
char dpb_buffer[256] = { isc_dpb_version1 }, *dpb;
|
|
short len;
|
|
|
|
dpb = dpb_buffer + 1;
|
|
|
|
/* loop through all the provided arguments and set dpb fields accordingly */
|
|
for (i = 0; i < sizeof(dpb_flags); ++i) {
|
|
if (dpb_values[i]) {
|
|
dpb += sprintf(dpb, "%c%c%s", dpb_flags[i], (unsigned char)strlen(dpb_values[i]),
|
|
dpb_values[i]);
|
|
}
|
|
}
|
|
|
|
/* fire it up baby! */
|
|
if (isc_attach_database(H->isc_status, 0, vars[0].optval, &H->db,(short)(dpb-dpb_buffer),
|
|
dpb_buffer)) {
|
|
break;
|
|
}
|
|
|
|
dbh->methods = &firebird_methods;
|
|
dbh->alloc_own_columns = 0;
|
|
dbh->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
|
|
dbh->native_case = PDO_CASE_UPPER;
|
|
|
|
ret = 1;
|
|
|
|
} while (0);
|
|
|
|
for (i = 0; i < sizeof(vars)/sizeof(vars[0]); ++i) {
|
|
if (vars[i].freeme) {
|
|
efree(vars[i].optval);
|
|
}
|
|
}
|
|
|
|
if (!ret) {
|
|
firebird_handle_closer(dbh TSRMLS_CC);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
/* }}} */
|
|
|
|
pdo_driver_t pdo_firebird_driver = {
|
|
PDO_DRIVER_HEADER(firebird),
|
|
pdo_firebird_handle_factory
|
|
};
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim600: noet sw=4 ts=4 fdm=marker
|
|
* vim<600: noet sw=4 ts=4
|
|
*/
|