/* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_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. | +----------------------------------------------------------------------+ | Authors: Jouni Ahto | +----------------------------------------------------------------------+ */ /* $Id$ */ /* TODO: A lot... */ #include "php.h" #include "php_config.h" #include "php_interbase.h" #if HAVE_IBASE #include #include #include "php_string.h" #include "php_globals.h" /* {{{ extension definition structures */ function_entry ibase_functions[] = { PHP_FE(ibase_connect, NULL) PHP_FE(ibase_pconnect, NULL) PHP_FE(ibase_close, NULL) PHP_FE(ibase_query, NULL) PHP_FE(ibase_fetch_row, NULL) PHP_FE(ibase_free_result, NULL) PHP_FE(ibase_prepare, NULL) PHP_FE(ibase_bind, NULL) PHP_FE(ibase_execute, NULL) PHP_FE(ibase_free_query, NULL) PHP_FE(ibase_timefmt, NULL) {NULL, NULL, NULL} }; php3_module_entry ibase_module_entry = { "InterBase", ibase_functions, PHP_MINIT(ibase), NULL, PHP_RINIT(ibase), NULL, PHP_MINFO(ibase), STANDARD_MODULE_PROPERTIES }; /* }}} */ /* {{{ thread safety stuff */ #if defined(THREAD_SAFE) typedef ibase_global_struct{ ibase_module php3_ibase_module; } ibase_global_struct; #define IBASE_GLOBAL(a) ibase_globals->a #define IBASE_TLS_VARS \ ibase_global_struct *ibase_globals; \ ibase_globals=TlsGetValue(IBASETls); #else #define IBASE_GLOBAL(a) a #define IBASE_TLS_VARS ibase_module php3_ibase_module; #endif /* }}} */ /* {{{ _php3_ibase_close_link() */ static void _php3_ibase_close_link(isc_db_handle db) { ISC_STATUS status[20]; IBASE_TLS_VARS; isc_detach_database(status, &db); IBASE_GLOBAL(php3_ibase_module).num_links--; } /* }}} */ /* {{{ _php3_ibase_close_plink() */ static void _php3_ibase_close_plink(isc_db_handle db) { ISC_STATUS status[20]; IBASE_TLS_VARS; isc_detach_database(status, &db); php3_ibase_module.num_persistent--; php3_ibase_module.num_links--; } /* }}} */ /* {{{ _php3_ibase_free_result() */ static void _php3_ibase_free_result(ibase_result_handle *result) { int i; ISC_STATUS status[20]; IBASE_TLS_VARS; if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions && result->commitok) { isc_commit_transaction(status, &result->trans); } if (result->sqlda != NULL) { for (i = 0; i < result->sqlda->sqld; i++) { efree(result->sqlda->sqlvar[i].sqldata); efree(result->sqlda->sqlvar[i].sqlind); } efree(result->sqlda); } isc_dsql_free_statement(status, &result->result, DSQL_drop); efree(result); } /* }}} */ /* {{{ _php3_ibase_free_query() */ static void _php3_ibase_free_query(ibase_query_handle *query) { int i; ISC_STATUS status[20]; if (query->sqlda != NULL) { if (query->alloced) { for (i = 0; i < query->sqlda->sqld; i++) { efree(query->sqlda->sqlvar[i].sqldata); efree(query->sqlda->sqlvar[i].sqlind); } } efree(query->sqlda); } isc_dsql_free_statement(status, &query->query, DSQL_drop); efree(query); } /* }}} */ /* {{{ startup, shutdown and info functions */ PHP_MINIT_FUNCTION(ibase) { IBASE_TLS_VARS; if (cfg_get_long("ibase.allow_persistent", &IBASE_GLOBAL(php3_ibase_module).allow_persistent) == FAILURE) { IBASE_GLOBAL(php3_ibase_module).allow_persistent = 1; } if (cfg_get_long("ibase.max_persistent", &IBASE_GLOBAL(php3_ibase_module).max_persistent) == FAILURE) { IBASE_GLOBAL(php3_ibase_module).max_persistent = -1; } if (cfg_get_long("ibase.max_links", &IBASE_GLOBAL(php3_ibase_module).max_links) == FAILURE) { IBASE_GLOBAL(php3_ibase_module).max_links = -1; } /* if (cfg_get_long("ibase.manualtransactions", &IBASE_GLOBAL(php3_ibase_module).manualtransactions) == FAILURE) { IBASE_GLOBAL(php3_ibase_module).manualtransactions = 0; } */ IBASE_GLOBAL(php3_ibase_module).manualtransactions = 0; if (cfg_get_string("ibase.default_user", &IBASE_GLOBAL(php3_ibase_module).default_user) == FAILURE || IBASE_GLOBAL(php3_ibase_module).default_user[0] == 0) { IBASE_GLOBAL(php3_ibase_module).default_user = ""; } if (cfg_get_string("ibase.default_password", &IBASE_GLOBAL(php3_ibase_module).default_password) == FAILURE || IBASE_GLOBAL(php3_ibase_module).default_password[0] == 0) { IBASE_GLOBAL(php3_ibase_module).default_password = ""; } if (cfg_get_string("ibase.timeformat", &IBASE_GLOBAL(php3_ibase_module).timeformat) == FAILURE) { IBASE_GLOBAL(php3_ibase_module).timeformat = "%Y-%m-%d %H:%M:%S"; } IBASE_GLOBAL(php3_ibase_module).num_persistent=0; IBASE_GLOBAL(php3_ibase_module).le_result = register_list_destructors(_php3_ibase_free_result, NULL); IBASE_GLOBAL(php3_ibase_module).le_query = register_list_destructors(_php3_ibase_free_query, NULL); IBASE_GLOBAL(php3_ibase_module).le_link = register_list_destructors(_php3_ibase_close_link, NULL); IBASE_GLOBAL(php3_ibase_module).le_plink = register_list_destructors(NULL, _php3_ibase_close_plink); return SUCCESS; } PHP_RINIT_FUNCTION(ibase) { IBASE_TLS_VARS; IBASE_GLOBAL(php3_ibase_module).default_link=-1; IBASE_GLOBAL(php3_ibase_module).num_links = php3_ibase_module.num_persistent; return SUCCESS; } /* TODO IF NEEDED int php3_mfinish_ibase(void) { } int php3_rfinish_ibase(void) { } */ PHP_MINFO_FUNCTION(ibase) { /* TODO */ } /* }}} */ /* {{{ _php_ibase_attach_db() */ static int _php_ibase_attach_db(char *server, char *uname, int uname_len, char *passwd, int passwd_len, isc_db_handle *db) { ISC_STATUS status[20]; int db_parbuf_len = 4; short foo = 4; char dpb[255], *db_parbuf; if (uname_len) { db_parbuf_len += uname_len + 2; } if (passwd_len) { db_parbuf_len += passwd_len + 2; } db_parbuf = dpb; *db_parbuf++ = isc_dpb_version1; *db_parbuf++ = isc_dpb_num_buffers; *db_parbuf++ = 1; *db_parbuf++ = 90; if (uname_len) { if (passwd_len) { isc_expand_dpb(&db_parbuf, &foo, isc_dpb_user_name, uname, isc_dpb_password, passwd, NULL); } else { isc_expand_dpb(&db_parbuf, &foo, isc_dpb_user_name, uname, NULL); } } isc_attach_database(status, strlen(server), server, db, db_parbuf_len, dpb); if (status[0] == 1 && status[1]) { php_error(E_WARNING,"Unable to connect to InterBase server: %s", "XXX"); return 1; } return 0; } /* }}} */ /* {{{ _php3_ibase_connect() */ static void _php3_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) { pval *server, *uname, *passwd; char *ib_server, *ib_uname, *ib_passwd; int ib_server_len, ib_uname_len, ib_passwd_len; isc_db_handle db_handle = NULL; char *hashed_details; int hashed_details_length; IBASE_TLS_VARS; ib_uname = IBASE_GLOBAL(php3_ibase_module).default_user; ib_passwd = IBASE_GLOBAL(php3_ibase_module).default_password; ib_uname_len = ib_uname ? strlen(ib_uname) : 0; ib_passwd_len = ib_passwd ? strlen(ib_passwd) : 0; switch(ARG_COUNT(ht)) { case 1: { if (getParameters(ht, 1, &server) == FAILURE) { RETURN_FALSE; } convert_to_string(server); ib_server = server->value.str.val; ib_server_len = server->value.str.len; hashed_details_length = server->value.str.len+ib_uname_len+ib_passwd_len+5+3; hashed_details = (char *) emalloc(hashed_details_length+1); sprintf(hashed_details, "ibase_%s_%s_%s", ib_server, ib_uname, ib_passwd); } break; case 2: { if (getParameters(ht, 2, &server, &uname) == FAILURE) { RETURN_FALSE; } convert_to_string(server); convert_to_string(uname); ib_server = server->value.str.val; ib_uname = uname->value.str.val; ib_server_len = server->value.str.len; ib_uname_len = uname->value.str.len; hashed_details_length = server->value.str.len+uname->value.str.len+ib_passwd_len+5+3; hashed_details = (char *) emalloc(hashed_details_length+1); sprintf(hashed_details, "ibase_%s_%s_%s", ib_server, ib_uname, ib_passwd); } break; case 3: { if (getParameters(ht, 3, &server, &uname, &passwd) == FAILURE) { RETURN_FALSE; } convert_to_string(server); convert_to_string(uname); convert_to_string(passwd); ib_server = server->value.str.val; ib_uname = uname->value.str.val; ib_passwd = passwd->value.str.val; ib_server_len = server->value.str.len; ib_uname_len = uname->value.str.len; ib_passwd_len = passwd->value.str.len; hashed_details_length = server->value.str.len+uname->value.str.len+passwd->value.str.len+5+3; hashed_details = (char *) emalloc(hashed_details_length+1); sprintf(hashed_details, "ibase_%s_%s_%s", ib_server, ib_uname, ib_passwd); } break; default: WRONG_PARAM_COUNT; break; } if (persistent) { list_entry *le; if (zend_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { list_entry new_le; if (IBASE_GLOBAL(php3_ibase_module).max_links!=-1 && IBASE_GLOBAL(php3_ibase_module).num_links>=IBASE_GLOBAL(php3_ibase_module).max_links) { php_error(E_WARNING,"InterBase: Too many open links (%d)", IBASE_GLOBAL(php3_ibase_module).num_links); efree(hashed_details); RETURN_FALSE; } if (IBASE_GLOBAL(php3_ibase_module).max_persistent!=-1 && IBASE_GLOBAL(php3_ibase_module).num_persistent>=IBASE_GLOBAL(php3_ibase_module).max_persistent) { php_error(E_WARNING,"InterBase: Too many open persistent links (%d)", IBASE_GLOBAL(php3_ibase_module).num_persistent); efree(hashed_details); RETURN_FALSE; } /* create the link */ if (_php_ibase_attach_db(ib_server, ib_uname, ib_uname_len, ib_passwd, ib_passwd_len, &db_handle)) { efree(hashed_details); RETURN_FALSE; } /* hash it up */ new_le.type = php3_ibase_module.le_plink; new_le.ptr = db_handle; if (zend_hash_update(plist, hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) { efree(hashed_details); RETURN_FALSE; } IBASE_GLOBAL(php3_ibase_module).num_links++; IBASE_GLOBAL(php3_ibase_module).num_persistent++; } else { if (le->type != IBASE_GLOBAL(php3_ibase_module).le_plink) { RETURN_FALSE; } /* TODO: ensure that the link did not die */ db_handle = (isc_db_handle) le->ptr; } return_value->value.lval = php3_list_insert(db_handle, IBASE_GLOBAL(php3_ibase_module).le_plink); return_value->type = IS_LONG; } else { list_entry *index_ptr, new_index_ptr; /* first we check the hash for the hashed_details key. if it exists, * it should point us to the right offset where the actual pgsql link sits. * if it doesn't, open a new pgsql link, add it to the resource list, * and add a pointer to it with hashed_details as the key. */ if (zend_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) { int type,link; void *ptr; if (index_ptr->type != le_index_ptr) { RETURN_FALSE; } link = (int) index_ptr->ptr; ptr = php3_list_find(link,&type); /* check if the link is still there */ if (ptr && (type==IBASE_GLOBAL(php3_ibase_module).le_link || type==IBASE_GLOBAL(php3_ibase_module).le_plink)) { return_value->value.lval = IBASE_GLOBAL(php3_ibase_module).default_link = link; return_value->type = IS_LONG; efree(hashed_details); return; } else { zend_hash_del(list,hashed_details,hashed_details_length+1); } } if (IBASE_GLOBAL(php3_ibase_module).max_links!=-1 && IBASE_GLOBAL(php3_ibase_module).num_links>=IBASE_GLOBAL(php3_ibase_module).max_links) { php_error(E_WARNING,"InterBase: Too many open links (%d)", IBASE_GLOBAL(php3_ibase_module).num_links); efree(hashed_details); RETURN_FALSE; } /* create the link */ if (_php_ibase_attach_db(ib_server, ib_uname, ib_uname_len, ib_passwd, ib_passwd_len, &db_handle)) { efree(hashed_details); RETURN_FALSE; } /* add it to the list */ return_value->value.lval = php3_list_insert(db_handle, IBASE_GLOBAL(php3_ibase_module).le_link); return_value->type = IS_LONG; /* add it to the hash */ new_index_ptr.ptr = (void *) return_value->value.lval; new_index_ptr.type = le_index_ptr; if (zend_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) { efree(hashed_details); RETURN_FALSE; } IBASE_GLOBAL(php3_ibase_module).num_links++; } efree(hashed_details); IBASE_GLOBAL(php3_ibase_module).default_link=return_value->value.lval; } /* }}} */ /* {{{ proto int ibase_connect(string database [, string username] [, string password]) Open a connection to an InterBase database */ PHP_FUNCTION(ibase_connect) { _php3_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ /* {{{ proto int ibase_pconnect(string database [, string username] [, string password]) Open a persistent connection to an InterBase database */ PHP_FUNCTION(ibase_pconnect) { _php3_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ /* {{{ proto int ibase_close([int link_identifier]) Close an InterBase connection */ PHP_FUNCTION(ibase_close) { pval *ibase_link; int id, type; isc_db_handle db_handle; IBASE_TLS_VARS; switch (ARG_COUNT(ht)) { case 0: id = IBASE_GLOBAL(php3_ibase_module).default_link; break; case 1: if (getParameters(ht, 1, &ibase_link) == FAILURE) { RETURN_FALSE; } convert_to_long(ibase_link); id = ibase_link->value.lval; break; default: WRONG_PARAM_COUNT; break; } db_handle = (isc_db_handle) php3_list_find(id, &type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_link && type!=IBASE_GLOBAL(php3_ibase_module).le_plink) { php_error(E_WARNING, "%d is not an InterBase link index",id); RETURN_FALSE; } php3_list_delete(ibase_link->value.lval); RETURN_TRUE; } /* }}} */ /* {{{ _php3_ibase_prepare() */ static XSQLDA *_php3_ibase_prepare(isc_db_handle db, isc_tr_handle tr, isc_stmt_handle *query_handle, char *query) { ISC_STATUS status[20]; XSQLDA *isqlda; isqlda = (XSQLDA *) emalloc(XSQLDA_LENGTH(0)); isqlda->sqln = 0; isqlda->version = SQLDA_VERSION1; if (isc_dsql_allocate_statement(status, &db, query_handle)) { php_error(E_WARNING, "InterBase: couldn't allocate space for query"); return NULL; } if (isc_dsql_prepare(status, &tr, query_handle, 0, query, 1, isqlda)) { php_error(E_WARNING, "InterBase: couldn't prepare query"); return NULL; } /* * Check if query has placeholders and needs binding. If it has, allocate * input sqlda big enough and return it. */ if (isc_dsql_describe_bind(status, query_handle, 1, isqlda)) { php_error(E_WARNING, "InterBase: couldn't describe placeholders in query"); } if (isqlda->sqld > 1) { isqlda = (XSQLDA *) erealloc(isqlda, XSQLDA_LENGTH(isqlda->sqld)); isqlda->sqln = isqlda->sqld; isqlda->version = SQLDA_VERSION1; if (isc_dsql_describe(status, query_handle, 1, isqlda)) { php_error(E_WARNING, "InterBase: couldn't describe query"); } return isqlda; } else if (isqlda->sqld == 1) { return isqlda; } else { efree(isqlda); return NULL; } } /* }}} */ /* {{{ _php3_ibase_execute() */ static XSQLDA *_php3_ibase_execute(isc_tr_handle tr_handle, isc_stmt_handle query_handle, XSQLDA *isqlda, ISC_STATUS *status) { int i, coltype; static char query_info[] = { isc_info_sql_stmt_type }; char info_buffer[18]; short l; long query_type; XSQLDA *osqlda; /* * Find out what kind of query is to be executed. */ if (!isc_dsql_sql_info(status, &query_handle, sizeof(query_info), query_info, sizeof(info_buffer), info_buffer)) { l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2); query_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3, l); } if (query_type == isc_info_sql_stmt_select || query_type == isc_info_sql_stmt_select_for_upd) { /* * Select, need to allocate output sqlda and and prepare it for use. */ osqlda = (XSQLDA *) emalloc(XSQLDA_LENGTH(0)); osqlda->sqln = 0; osqlda->version = SQLDA_VERSION1; if (isc_dsql_describe(status, &query_handle, 1, osqlda)) { php_error(E_WARNING, "InterBase: couldn't describe query"); } if (osqlda->sqld) { osqlda = (XSQLDA *) erealloc(osqlda, XSQLDA_LENGTH(osqlda->sqld)); osqlda->sqln = osqlda->sqld; osqlda->version = SQLDA_VERSION1; if (isc_dsql_describe(status, &query_handle, 1, osqlda)) { php_error(E_WARNING, "InterBase: couldn't describe query"); } } for (i = 0; i < osqlda->sqld; i++) { osqlda->sqlvar[i].sqlind = (short *) emalloc(sizeof(short)); coltype = osqlda->sqlvar[i].sqltype & ~1; switch(coltype) { case SQL_TEXT: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(char)*(osqlda->sqlvar[i].sqllen)); break; case SQL_VARYING: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(char)*(osqlda->sqlvar[i].sqllen+2)); break; case SQL_SHORT: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(short)); break; case SQL_LONG: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(long)); break; case SQL_FLOAT: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(float)); break; case SQL_DOUBLE: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(double)); break; case SQL_DATE: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(ISC_QUAD)); break; case SQL_BLOB: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(ISC_QUAD)); break; case SQL_ARRAY: osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(ISC_QUAD)); break; } } if (isqlda == NULL) { if (isc_dsql_execute(status, &tr_handle, &query_handle, 1, NULL)) { php_error(E_WARNING, "InterBase: couldn't execute query"); return NULL; } else { return osqlda; } } else { if (isc_dsql_execute2(status, &tr_handle, &query_handle, 1, isqlda, osqlda)) { php_error(E_WARNING, "InterBase: couldn't execute query"); return NULL; } else { return osqlda; } } } else { /* Not select */ if (isc_dsql_execute(status, &tr_handle, &query_handle, 1, isqlda)) { php_error(E_WARNING, "InterBase: couldn't execute query"); } /* if (!php3_ibase_module.manualtransactions) { if(0) { isc_commit_transaction(status, tr_handle); } else { isc_rollback_transaction(status, tr_handle); } } */ } return NULL; } /* }}} */ /* {{{ proto int ibase_query([int link_identifier, ]string query) Execute a query (without parameter placeholders). */ PHP_FUNCTION(ibase_query) { pval *query, *ibase_link; int id, type; isc_db_handle db_handle; isc_tr_handle tr_handle = NULL; isc_stmt_handle query_handle = NULL; ISC_STATUS status[20]; XSQLDA *isqlda, *osqlda; ibase_result_handle *ibase_result; IBASE_TLS_VARS; switch (ARG_COUNT(ht)) { case 1: if (getParameters(ht, 1, &query) == FAILURE) { RETURN_FALSE; } id = IBASE_GLOBAL(php3_ibase_module).default_link; break; case 2: if (getParameters(ht, 2, &ibase_link, &query) == FAILURE) { RETURN_FALSE; } convert_to_long(ibase_link); id = ibase_link->value.lval; break; default: WRONG_PARAM_COUNT; break; } db_handle = (isc_db_handle) php3_list_find(id, &type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_link && type!=IBASE_GLOBAL(php3_ibase_module).le_plink) { php_error(E_WARNING, "%d is not an InterBase link index", id); RETURN_FALSE; } convert_to_string(query); if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) { if (isc_start_transaction(status, &tr_handle, 1, &db_handle, 0, NULL)) { php_error(E_WARNING, "InterBase: couldn't start transaction"); RETURN_FALSE; } } isqlda = _php3_ibase_prepare(db_handle, tr_handle, &query_handle, query->value.str.val); if (isqlda != NULL) { isc_rollback_transaction(status, &tr_handle); isc_dsql_free_statement(status, &query_handle, DSQL_drop); php_error(E_WARNING, "InterBase: ibase_query doesn't support parameter placeholders in query"); RETURN_FALSE; } osqlda = _php3_ibase_execute(tr_handle, query_handle, isqlda, status); if (osqlda != NULL) { ibase_result = (ibase_result_handle *) emalloc(sizeof(ibase_result_handle)); ibase_result->result = query_handle; ibase_result->sqlda = osqlda; ibase_result->trans = tr_handle; ibase_result->commitok = 1; return_value->value.lval = php3_list_insert(ibase_result, php3_ibase_module.le_result); return_value->type = IS_LONG; } else { if (status[0] == 1 && status[1]) { if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) { isc_rollback_transaction(status, &tr_handle); isc_dsql_free_statement(status, &query_handle, DSQL_drop); RETURN_FALSE; } } else { if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) { isc_commit_transaction(status, &tr_handle); isc_dsql_free_statement(status, &query_handle, DSQL_drop); RETURN_FALSE; } } } } /* }}} */ /* {{{ proto int ibase_fetch_row(int result) Fetch a row from the results of a query. */ PHP_FUNCTION(ibase_fetch_row) { pval *result; pval *pval_ptr; int type; int i, coltype, collen; char string_data[255]; char *fieldname; char *char_data; /* struct tm t; */ ibase_result_handle *ibase_result; ISC_STATUS status[20]; XSQLVAR *var; IBASE_VCHAR *vchar; IBASE_TLS_VARS; PLS_FETCH(); if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(result); ibase_result = (ibase_result_handle *) php3_list_find(result->value.lval, &type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_result) { php_error(E_WARNING,"%d is not an InterBase result index", result->value.lval); RETURN_FALSE; } if (ibase_result->sqlda == NULL) { php_error(E_WARNING,"InterBase: trying to fetch results from a non-select query"); RETURN_FALSE; } var = ibase_result->sqlda->sqlvar; if (isc_dsql_fetch(status, &ibase_result->result, 1, ibase_result->sqlda) != 100L) { if (array_init(return_value)==FAILURE) { RETURN_FALSE; } for (i = 0; i < ibase_result->sqlda->sqld; i++) { var[i].sqlname[var[i].sqlname_length] = '\0'; fieldname = var[i].sqlname; if (*var[i].sqlind < 0) { /* XXX. Column is NULL. This is not the best idea to do, think something... */ add_get_index_stringl(return_value, i, NULL, 0, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); continue; } coltype = var[i].sqltype & ~1; switch(coltype) { case SQL_TEXT: { int len = var[i].sqllen; char_data = (char *)emalloc(sizeof(char)*(var[i].sqllen)); collen = sprintf(char_data, "%*.*s", len, len, ibase_result->sqlda->sqlvar[i].sqldata); if (PG(magic_quotes_runtime)) { int newlen; char *tmp = php_addslashes(char_data, collen, &newlen, 0); add_get_index_stringl(return_value, i, tmp, newlen, (void **) &pval_ptr, 0); } else { add_get_index_stringl(return_value, i, char_data, collen, (void **) &pval_ptr, 1); } zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); efree(char_data); } break; case SQL_VARYING: { vchar = (IBASE_VCHAR *) var[i].sqldata; char_data = (char *)emalloc(sizeof(char)*(vchar->var_len)); collen = sprintf(char_data, "%*.*s", vchar->var_len, vchar->var_len, vchar->var_str); if (PG(magic_quotes_runtime)) { int newlen; char *tmp = php_addslashes(char_data, collen, &newlen, 0); add_get_index_stringl(return_value, i, tmp, newlen, (void **) &pval_ptr, 0); } else { add_get_index_stringl(return_value, i, char_data, collen, (void **) &pval_ptr, 1); } zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); efree(char_data); } break; case SQL_SHORT: collen = sprintf(string_data, "%d", *(short *)(var[i].sqldata)); add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); break; case SQL_LONG: if (var[i].sqlscale) { int j, f = 1; float n; n = *(long *)(var[i].sqldata); for (j = 0; j < -var[i].sqlscale; j++) f *= 10; n /= f; collen = sprintf(string_data, "%.*f", -var[i].sqlscale, n); } else { collen = sprintf(string_data, "%ld", *(long *)(var[i].sqldata)); } add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); break; case SQL_FLOAT: collen = sprintf(string_data, "%f", *(float *)(var[i].sqldata)); add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); break; case SQL_DOUBLE: if (ibase_result->sqlda->sqlvar[i].sqlscale) { collen = sprintf(string_data, "%.*f", -var[i].sqlscale, *(double *)(var[i].sqldata)); } else { collen = sprintf(string_data, "%f", *(double *)(var[i].sqldata)); } add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); break; case SQL_DATE: { struct tm *t; t = emalloc(sizeof(struct tm)); isc_decode_date((ISC_QUAD *) var[i].sqldata, t); /* #if HAVE_STRFTIME collen = (int) strftime(string_data, 255, IBASE_GLOBAL(php3_ibase_module).timeformat, t); #else */ collen = sprintf(string_data, "%4d-%02d-%02d %02d:%02d:%02d", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); /* #endif */ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); efree(t); } break; case SQL_BLOB: case SQL_ARRAY: { /* TODO, currently just show the id */ ISC_QUAD bid; bid = *(ISC_QUAD ISC_FAR *) var[i].sqldata; sprintf(string_data, "%lx:%lx", bid.isc_quad_high, bid.isc_quad_low); add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1); zend_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr); } break; default: break; } } } else { RETURN_FALSE; } } /* }}} */ /* {{{ proto int ibase_free_result(int result) Free the memory used by a result. */ PHP_FUNCTION(ibase_free_result) { pval *result; ibase_result_handle *ibase_result; int type; IBASE_TLS_VARS; if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(result); if (result->value.lval==0) { RETURN_FALSE; } ibase_result = (ibase_result_handle *) php3_list_find(result->value.lval,&type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_result) { php_error(E_WARNING,"%d is not an InterBase result index",result->value.lval); RETURN_FALSE; } php3_list_delete(result->value.lval); RETURN_TRUE; } /* }}} */ /* {{{ proto int ibase_prepare([int link_identifier, ]string query) Prepare a query for later binding of parameter placeholders and execution. */ PHP_FUNCTION(ibase_prepare) { pval *query, *ibase_link; int id, type; isc_db_handle db_handle; isc_tr_handle tr_handle = NULL; isc_stmt_handle query_handle = NULL; ISC_STATUS status[20]; XSQLDA *isqlda; ibase_query_handle *ibase_query; IBASE_TLS_VARS; switch (ARG_COUNT(ht)) { case 1: if (getParameters(ht, 1, &query) == FAILURE) { RETURN_FALSE; } id = IBASE_GLOBAL(php3_ibase_module).default_link; break; case 2: if (getParameters(ht, 2, &ibase_link, &query) == FAILURE) { RETURN_FALSE; } convert_to_long(ibase_link); id = ibase_link->value.lval; break; default: WRONG_PARAM_COUNT; break; } db_handle = (isc_db_handle) php3_list_find(id, &type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_link && type!=IBASE_GLOBAL(php3_ibase_module).le_plink) { php_error(E_WARNING, "%d is not an InterBase link index", id); RETURN_FALSE; } convert_to_string(query); if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) { if (isc_start_transaction(status, &tr_handle, 1, &db_handle, 0, NULL)) { php_error(E_WARNING, "InterBase: couldn't start transaction"); RETURN_FALSE; } } isqlda = _php3_ibase_prepare(db_handle, tr_handle, &query_handle, query->value.str.val); ibase_query = (ibase_query_handle *) emalloc(sizeof(ibase_query_handle)); ibase_query->query = query_handle; ibase_query->sqlda = isqlda; ibase_query->trans = tr_handle; ibase_query->alloced = 0; return_value->value.lval = php3_list_insert(ibase_query, php3_ibase_module.le_query); return_value->type = IS_LONG; } /* }}} */ /* {{{ proto int ibase_bind (int query) Bind parameter placeholders in a previously prepared query. Still nonfunctional. */ PHP_FUNCTION(ibase_bind) { pval *query; ibase_query_handle *ibase_query; int type; IBASE_TLS_VARS; if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &query)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(query); if (query->value.lval==0) { RETURN_FALSE; } ibase_query = (ibase_query_handle *) php3_list_find(query->value.lval,&type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_query) { php_error(E_WARNING,"%d is not an InterBase query index",query->value.lval); RETURN_FALSE; } if (ibase_query->sqlda == NULL) { php_error(E_WARNING,"InterBase: trying to bind a query having no parameter placeholders"); RETURN_FALSE; } /* TODO for (i = 0; i < ibase_query->sqlda->sqld; i++) { ibase_query->sqlda->sqlvar[i].sqlind = (short *) emalloc(sizeof(short)); coltype = ibase_query->sqlda->sqlvar[i].sqltype & ~1; switch(coltype) { case SQL_TEXT: break; case SQL_VARYING: break; case SQL_SHORT: break; case SQL_LONG: break; case SQL_FLOAT: break; case SQL_DOUBLE: break; case SQL_DATE: break; case SQL_BLOB: break; case SQL_ARRAY: break; } } */ } /* }}} */ /* {{{ proto int ibase_execute(int query) Execute a previously prepared (and possibly binded) query. */ PHP_FUNCTION(ibase_execute) { pval *query; ibase_query_handle *ibase_query; ibase_result_handle *ibase_result; int type; ISC_STATUS status[20]; XSQLDA *osqlda; IBASE_TLS_VARS; if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &query)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(query); if (query->value.lval==0) { RETURN_FALSE; } ibase_query = (ibase_query_handle *) php3_list_find(query->value.lval,&type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_query) { php_error(E_WARNING,"%d is not an InterBase query index", query->value.lval); RETURN_FALSE; } osqlda = _php3_ibase_execute(ibase_query->trans, ibase_query->query, ibase_query->sqlda, status); ibase_result = (ibase_result_handle *) emalloc(sizeof(ibase_result_handle)); ibase_result->result = ibase_query->query; ibase_result->sqlda = osqlda; return_value->value.lval = php3_list_insert(ibase_result, IBASE_GLOBAL(php3_ibase_module).le_result); return_value->type = IS_LONG; } /* }}} */ /* {{{ proto int ibase_free_query(int query) Free memory used by a query */ PHP_FUNCTION(ibase_free_query) { pval *query; ibase_query_handle *ibase_query; int type; IBASE_TLS_VARS; if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &query)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(query); if (query->value.lval==0) { RETURN_FALSE; } ibase_query = (ibase_query_handle *) php3_list_find(query->value.lval, &type); if (type!=IBASE_GLOBAL(php3_ibase_module).le_query) { php_error(E_WARNING,"%d is not an InterBase query index", query->value.lval); RETURN_FALSE; } php3_list_delete(query->value.lval); RETURN_TRUE; } /* }}} */ /* {{{ proto int ibase_timefmt(string format) Sets the format of datetime columns returned from queries. Still nonfunctional. */ PHP_FUNCTION(ibase_timefmt) { pval *pmode; IBASE_TLS_VARS; #if HAVE_STRFTIME if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &pmode)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_string(pmode); RETURN_TRUE; #else php_error(E_WARNING,"InterBase: ibase_timefmt not supported on this platform"); RETURN_FALSE; #endif } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */