📄 ii.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 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_01.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. | +----------------------------------------------------------------------+ | Contributed by ECL IP'S Software & Services | | http://www.eclips-software.com | | mailto://idev@eclips-software.com | | Author: David H閚ot <henot@php.net> | +----------------------------------------------------------------------+ *//* $Id: ii.c,v 1.31.8.4.4.2 2007/01/01 09:46:43 sebastian Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_globals.h"#include "php_ini.h"#include "ext/standard/info.h"#include "php_ii.h"#include "ii.h"#include "ext/standard/php_string.h"#if HAVE_IIZEND_DECLARE_MODULE_GLOBALS(ii)/* True globals, no need for thread safety */static int le_ii_link, le_ii_plink;#define SAFE_STRING(s) ((s)?(s):"")/* Every user visible function must have an entry in ii_functions[].*/function_entry ii_functions[] = { PHP_FE(ingres_connect, NULL) PHP_FE(ingres_pconnect, NULL) PHP_FE(ingres_close, NULL) PHP_FE(ingres_query, NULL) PHP_FE(ingres_num_rows, NULL) PHP_FE(ingres_num_fields, NULL) PHP_FE(ingres_field_name, NULL) PHP_FE(ingres_field_type, NULL) PHP_FE(ingres_field_nullable, NULL) PHP_FE(ingres_field_length, NULL) PHP_FE(ingres_field_precision, NULL) PHP_FE(ingres_field_scale, NULL) PHP_FE(ingres_fetch_array, NULL) PHP_FE(ingres_fetch_row, NULL) PHP_FE(ingres_fetch_object, NULL) PHP_FE(ingres_rollback, NULL) PHP_FE(ingres_commit, NULL) PHP_FE(ingres_autocommit, NULL) {NULL, NULL, NULL} /* Must be the last line in ii_functions[] */};zend_module_entry ingres_ii_module_entry = { STANDARD_MODULE_HEADER, "ingres_ii", ii_functions, PHP_MINIT(ii), PHP_MSHUTDOWN(ii), PHP_RINIT(ii), PHP_RSHUTDOWN(ii), PHP_MINFO(ii), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_INGRES_IIZEND_GET_MODULE(ingres_ii)#endif/* php.ini entries*/PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("ingres.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateInt, allow_persistent, zend_ii_globals, ii_globals) STD_PHP_INI_ENTRY_EX("ingres.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_persistent, zend_ii_globals, ii_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX("ingres.max_links", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_links, zend_ii_globals, ii_globals, display_link_numbers) STD_PHP_INI_ENTRY("ingres.default_database", NULL, PHP_INI_ALL, OnUpdateString, default_database, zend_ii_globals, ii_globals) STD_PHP_INI_ENTRY("ingres.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_ii_globals, ii_globals) STD_PHP_INI_ENTRY("ingres.default_password", NULL, PHP_INI_ALL, OnUpdateString, default_password, zend_ii_globals, ii_globals)PHP_INI_END()/* closes statement in given link*/static int _close_statement(II_LINK *link){ IIAPI_CLOSEPARM closeParm; closeParm.cl_genParm.gp_callback = NULL; closeParm.cl_genParm.gp_closure = NULL; closeParm.cl_stmtHandle = link->stmtHandle; IIapi_close(&closeParm); ii_sync(&(closeParm.cl_genParm)); if (ii_success(&(closeParm.cl_genParm)) == II_FAIL) { return 1; } link->stmtHandle = NULL; link->fieldCount = 0; link->descriptor = NULL; return 0;}/* rolls back transaction in given link after closing the active transaction (if any)*/static int _rollback_transaction(II_LINK *link TSRMLS_DC){ IIAPI_ROLLBACKPARM rollbackParm; if (link->stmtHandle && _close_statement(link)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Unable to close statement !!"); return 1; } rollbackParm.rb_genParm.gp_callback = NULL; rollbackParm.rb_genParm.gp_closure = NULL; rollbackParm.rb_tranHandle = link->tranHandle; rollbackParm.rb_savePointHandle = NULL; IIapi_rollback(&rollbackParm); ii_sync(&(rollbackParm.rb_genParm)); if (ii_success(&(rollbackParm.rb_genParm)) == II_FAIL) { return 1; } link->tranHandle = NULL; return 0;}static void _close_ii_link(II_LINK *link TSRMLS_DC){ IIAPI_DISCONNPARM disconnParm; if (link->tranHandle && _rollback_transaction(link TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Unable to rollback transaction !!"); } disconnParm.dc_genParm.gp_callback = NULL; disconnParm.dc_genParm.gp_closure = NULL; disconnParm.dc_connHandle = link->connHandle; IIapi_disconnect(&disconnParm); free(link); IIG(num_links)--;}/* closes the given link, actually disconnecting from server and releasing associated resources after rolling back the active transaction (if any)*/static void php_close_ii_link(zend_rsrc_list_entry *rsrc TSRMLS_DC){ II_LINK *link = (II_LINK *) rsrc->ptr; _close_ii_link(link TSRMLS_CC);}/* closes the given persistent link, see _close_ii_link*/static void _close_ii_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC){ II_LINK *link = (II_LINK *) rsrc->ptr; _close_ii_link(link TSRMLS_CC); IIG(num_persistent)--;}/* cleans up the given persistent link. used when the request ends to 'refresh' the link for use by the next request*/static void _ai_clean_ii_plink(II_LINK *link TSRMLS_DC){ int ai_error = 0; IIAPI_DISCONNPARM disconnParm; IIAPI_AUTOPARM autoParm; /* if link as always been marked as broken do nothing */ /* This because we call this function directly from close function */ /* And it's called in the end of request */ if (link->connHandle == NULL) { return; } if (link->stmtHandle && _close_statement(link)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Unable to close statement !!"); ai_error = 1; } if (link->autocommit) { autoParm.ac_genParm.gp_callback = NULL; autoParm.ac_genParm.gp_closure = NULL; autoParm.ac_connHandle = link->connHandle; autoParm.ac_tranHandle = link->tranHandle; IIapi_autocommit(&autoParm); ii_sync(&(autoParm.ac_genParm)); if (ii_success(&(autoParm.ac_genParm)) == II_FAIL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Unable to disable autocommit"); } link->autocommit = 0; link->tranHandle = NULL; } if (link->tranHandle && _rollback_transaction(link TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Unable to rollback transaction !!"); } /* Assume link is broken, close it, and mark it as broken with conn Handle NULL */ if (ai_error) { disconnParm.dc_genParm.gp_callback = NULL; disconnParm.dc_genParm.gp_closure = NULL; disconnParm.dc_connHandle = link->connHandle; IIapi_disconnect(&disconnParm); link->connHandle = NULL; }}static void _clean_ii_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC){ II_LINK *link = (II_LINK *)rsrc->ptr; _ai_clean_ii_plink(link TSRMLS_CC);}/* sets the default link*/static void php_ii_set_default_link(int id TSRMLS_DC){ if (IIG(default_link) != -1) { zend_list_delete(IIG(default_link)); } IIG(default_link) = id; zend_list_addref(id);}/* gets the default link if none has been set, tries to open a new one with default parameters*/static int php_ii_get_default_link(INTERNAL_FUNCTION_PARAMETERS){ if (IIG(default_link) == -1) { /* no link opened yet, implicitly open one */ ht = 0; php_ii_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } return IIG(default_link);}static void php_ii_globals_init(zend_ii_globals *ii_globals){ ii_globals->num_persistent = 0;}/* Module initialization*/PHP_MINIT_FUNCTION(ii){ IIAPI_INITPARM initParm; ZEND_INIT_MODULE_GLOBALS(ii, php_ii_globals_init, NULL); REGISTER_INI_ENTRIES(); le_ii_link = zend_register_list_destructors_ex(php_close_ii_link, NULL, "ingres", module_number); le_ii_plink = zend_register_list_destructors_ex(_clean_ii_plink, _close_ii_plink, "ingres persistent", module_number); /* Constants registration */ REGISTER_LONG_CONSTANT("INGRES_ASSOC", II_ASSOC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INGRES_NUM", II_NUM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INGRES_BOTH", II_BOTH, CONST_CS | CONST_PERSISTENT); /* Ingres api initialization */ initParm.in_timeout = -1; /* timeout in ms, -1 = no timeout */ initParm.in_version = IIAPI_VERSION_1; /* api version used */ IIapi_initialize(&initParm); if (initParm.in_status == IIAPI_ST_SUCCESS) { return SUCCESS; } else { return FAILURE; }}/* Module shutdown*/PHP_MSHUTDOWN_FUNCTION(ii){ IIAPI_TERMPARM termParm; UNREGISTER_INI_ENTRIES(); /* Ingres api termination */ IIapi_terminate(&termParm); if (termParm.tm_status == IIAPI_ST_SUCCESS) { return SUCCESS; } else { return FAILURE; }}/* New request initialization*/PHP_RINIT_FUNCTION(ii){ IIG(default_link) = -1; IIG(num_links) = IIG(num_persistent); return SUCCESS;}/* End of request*/PHP_RSHUTDOWN_FUNCTION(ii){ if (IIG(default_link) != -1) { zend_list_delete(IIG(default_link)); IIG(default_link) = -1; } return SUCCESS;}/* Informations reported to phpinfo()*/PHP_MINFO_FUNCTION(ii){ char buf[32]; php_info_print_table_start(); php_info_print_table_header(2, "Ingres II Support", "enabled"); sprintf(buf, "%ld", IIG(num_persistent)); php_info_print_table_row(2, "Active Persistent Links", buf); sprintf(buf, "%ld", IIG(num_links)); php_info_print_table_row(2, "Active Links", buf); php_info_print_table_end(); DISPLAY_INI_ENTRIES();}/* Waits for completion of the last Ingres api call used because of the asynchronous design of this api*/static int ii_sync(IIAPI_GENPARM *genParm){ static IIAPI_WAITPARM waitParm = { -1, /* no timeout, we don't want asynchronous queries */ 0 /* wt_status (output) */ }; while (genParm->gp_completed == FALSE) { IIapi_wait(&waitParm); } if (waitParm.wt_status != IIAPI_ST_SUCCESS) { TSRMLS_FETCH(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Unexpected failure of IIapi_wait()"); return 0; } return 1;}/* Handles errors from Ingres api*/static int ii_success(IIAPI_GENPARM *genParm){ switch (genParm->gp_status) { case IIAPI_ST_SUCCESS: return II_OK; case IIAPI_ST_NO_DATA: return II_NO_DATA; default: if (genParm->gp_errorHandle == NULL) { /* no error message available */ TSRMLS_FETCH(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Server or API error - no error message available"); } else { IIAPI_GETEINFOPARM getEInfoParm; TSRMLS_FETCH(); getEInfoParm.ge_errorHandle = genParm->gp_errorHandle; IIapi_getErrorInfo(&getEInfoParm); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Server or API error : %s", getEInfoParm.ge_message); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: SQLSTATE : %s", getEInfoParm.ge_SQLSTATE); } return II_FAIL; }}/* Actually handles connection creation, either persistent or not*/static void php_ii_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent){ zval **database, **username, **password; char *db, *user, *pass; int argc; char *hashed_details; int hashed_details_length; IIAPI_CONNPARM connParm; II_LINK *link; /* Setting db, user and pass according to sql_safe_mode, parameters and/or default values */ argc = ZEND_NUM_ARGS(); if (PG(sql_safe_mode)) { /* sql_safe_mode */ if (argc > 0) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "SQL safe mode in effect - ignoring host/user/password information"); } db = pass = NULL; user = php_get_current_user(); hashed_details_length = strlen(user) + sizeof("ingres___") - 1; hashed_details = (char *) emalloc(hashed_details_length + 1); sprintf(hashed_details, "Ingres__%s_", user); } else { /* non-sql_safe_mode */ db = IIG(default_database); user = IIG(default_user); pass = IIG(default_password); if (argc > 3 || zend_get_parameters_ex(argc, &database, &username, &password) == FAILURE) { WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_string_ex(password); pass = Z_STRVAL_PP(password); /* Fall-through. */ case 2: convert_to_string_ex(username); user = Z_STRVAL_PP(username); /* Fall-through. */ case 1: convert_to_string_ex(database); db = Z_STRVAL_PP(database); /* Fall-through. */ case 0: break; } hashed_details_length = sizeof("ingres___") - 1 + strlen(SAFE_STRING(db)) + strlen(SAFE_STRING(user)) + strlen(SAFE_STRING(pass)); hashed_details = (char *) emalloc(hashed_details_length + 1); sprintf(hashed_details, "Ingres_%s_%s_%s", SAFE_STRING(db), SAFE_STRING(user), SAFE_STRING(pass)); } /* if asked for unauthorized persistency, issue a warning and go for a non-persistent link */ if (persistent && !IIG(allow_persistent)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Persistent links disabled !"); persistent = 0; } if (persistent) { list_entry *le; /* is this link already in the persistent list ? */ if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length + 1, (void **) &le) == FAILURE) { /* no, new persistent connection */ list_entry new_le; if (IIG(max_links) != -1 && IIG(num_links) >= IIG(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Too many open links (%d)", IIG(num_links)); efree(hashed_details); RETURN_FALSE; } if (IIG(max_persistent) != -1 && IIG(num_persistent) >= IIG(max_persistent)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ingres II: Too many open persistent links (%d)", IIG(num_persistent)); efree(hashed_details); RETURN_FALSE; } /* create the link */ connParm.co_genParm.gp_callback = NULL; connParm.co_genParm.gp_closure = NULL; connParm.co_target = db; connParm.co_username = user; connParm.co_password = pass; connParm.co_timeout = -1; /* -1 is no timeout */ connParm.co_connHandle = NULL; connParm.co_tranHandle = NULL; IIapi_connect(&connParm); if (!ii_sync(&(connParm.co_genParm)) || ii_success(&(connParm.co_genParm)) == II_FAIL) { efree(hashed_details);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -