123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694 |
- /*
- +----------------------------------------------------------------------+
- | Copyright (c) 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: |
- | https://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. |
- +----------------------------------------------------------------------+
- | Authors: Stig Sæther Bakken <ssb@php.net> |
- | Thies C. Arntzen <thies@thieso.net> |
- | Maxim Maletsky <maxim@maxim.cx> |
- | |
- | Collection support by Andy Sautins <asautins@veripost.net> |
- | Temporary LOB support by David Benson <dbenson@mancala.com> |
- | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
- | |
- | Redesigned by: Antony Dovgal <antony@zend.com> |
- | Andi Gutmans <andi@php.net> |
- | Wez Furlong <wez@omniti.com> |
- +----------------------------------------------------------------------+
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include "php.h"
- #include "ext/standard/info.h"
- #include "php_ini.h"
- #include "zend_smart_str.h"
- #ifdef HAVE_OCI8
- /* PHP 5.2 is the minimum supported version for OCI8 2.0 */
- #if PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1)
- #error Use PHP OCI8 1.4 for your version of PHP
- #elif PHP_MAJOR_VERSION < 7
- /* PHP 7 is the minimum supported version for OCI8 2.1 */
- #error Use PHP OCI8 2.0 for your version of PHP
- #elif PHP_MAJOR_VERSION < 8
- /* PHP 8 is the minimum supported version for OCI8 3.0 */
- #error Use PHP OCI8 2.2 for your version of PHP
- #endif
- #include "php_oci8.h"
- #include "php_oci8_int.h"
- #include "zend_hash.h"
- ZEND_DECLARE_MODULE_GLOBALS(oci)
- static PHP_GINIT_FUNCTION(oci);
- static PHP_GSHUTDOWN_FUNCTION(oci);
- /* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
- #ifndef Z_ADDREF_P
- #define Z_ADDREF_P(x) ZVAL_ADDREF(x)
- #endif
- /* For a user friendly message about environment setup */
- #if defined(PHP_WIN32)
- #define PHP_OCI8_LIB_PATH_MSG "PATH"
- #elif defined(__APPLE__)
- #define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
- #elif defined(_AIX)
- #define PHP_OCI8_LIB_PATH_MSG "LIBPATH"
- #elif defined(__hpux)
- #define PHP_OCI8_LIB_PATH_MSG "SHLIB_PATH"
- #else
- #define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
- #endif
- /* True globals, no need for thread safety */
- int le_connection;
- int le_pconnection;
- int le_statement;
- int le_descriptor;
- int le_psessionpool;
- int le_collection;
- zend_class_entry *oci_lob_class_entry_ptr;
- zend_class_entry *oci_coll_class_entry_ptr;
- #ifndef SQLT_BFILEE
- #define SQLT_BFILEE 114
- #endif
- #ifndef SQLT_CFILEE
- #define SQLT_CFILEE 115
- #endif
- #ifdef ZTS
- #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
- #else
- #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
- #endif
- /* {{{ static protos */
- static void php_oci_connection_list_dtor (zend_resource *);
- static void php_oci_pconnection_list_dtor (zend_resource *);
- static void php_oci_pconnection_list_np_dtor (zend_resource *);
- static void php_oci_statement_list_dtor (zend_resource *);
- static void php_oci_descriptor_list_dtor (zend_resource *);
- static void php_oci_spool_list_dtor(zend_resource *entry);
- static void php_oci_collection_list_dtor (zend_resource *);
- static int php_oci_persistent_helper(zval *zv);
- static int php_oci_connection_ping(php_oci_connection *);
- static int php_oci_connection_status(php_oci_connection *);
- static int php_oci_connection_close(php_oci_connection *);
- static void php_oci_spool_close(php_oci_spool *session_pool);
- static OCIEnv *php_oci_create_env(ub2 charsetid);
- static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode);
- static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode);
- static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid);
- static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, zend_string *hash_key, int charsetid);
- static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh);
- /* }}} */
- /* {{{ dynamically loadable module stuff */
- #if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G) || defined(COMPILE_DL_OCI8_12C) || defined(COMPILE_DL_OCI8_19)
- ZEND_GET_MODULE(oci8)
- #endif /* COMPILE_DL */
- /* }}} */
- #include "oci8_arginfo.h"
- static PHP_INI_MH(OnUpdateOldCloseSemantics)
- {
- bool *p = (bool *) ZEND_INI_GET_ADDR();
- *p = zend_ini_parse_bool(new_value);
- if (*p) {
- zend_error(E_DEPRECATED, "Directive oci8.old_oci_close_semantics is deprecated");
- }
- return SUCCESS;
- }
- /* {{{ extension definition structures */
- zend_module_entry oci8_module_entry = {
- STANDARD_MODULE_HEADER,
- "oci8", /* extension name */
- ext_functions, /* extension function list */
- PHP_MINIT(oci), /* extension-wide startup function */
- PHP_MSHUTDOWN(oci), /* extension-wide shutdown function */
- PHP_RINIT(oci), /* per-request startup function */
- PHP_RSHUTDOWN(oci), /* per-request shutdown function */
- PHP_MINFO(oci), /* information function */
- PHP_OCI8_VERSION,
- PHP_MODULE_GLOBALS(oci), /* globals descriptor */
- PHP_GINIT(oci), /* globals ctor */
- PHP_GSHUTDOWN(oci), /* globals dtor */
- NULL, /* post deactivate */
- STANDARD_MODULE_PROPERTIES_EX
- };
- /* }}} */
- /* {{{ PHP_INI */
- PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_oci_globals, oci_globals)
- STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent_timeout, zend_oci_globals, oci_globals)
- STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, OnUpdateLong, ping_interval, zend_oci_globals, oci_globals)
- STD_PHP_INI_BOOLEAN("oci8.privileged_connect", "0", PHP_INI_SYSTEM, OnUpdateBool, privileged_connect, zend_oci_globals, oci_globals)
- STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, OnUpdateLong, statement_cache_size, zend_oci_globals, oci_globals)
- STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, OnUpdateLong, default_prefetch, zend_oci_globals, oci_globals)
- STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateOldCloseSemantics, old_oci_close_semantics,zend_oci_globals, oci_globals)
- #if (OCI_MAJOR_VERSION >= 11)
- STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals)
- #endif
- #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
- STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals)
- #endif
- PHP_INI_END()
- /* }}} */
- /* {{{ startup, shutdown and info functions */
- /* {{{ php_oci_init_global_handles()
- *
- * Initialize global handles only when they are needed
- */
- static void php_oci_init_global_handles(void)
- {
- sword errstatus;
- sb4 ora_error_code = 0;
- text tmp_buf[PHP_OCI_ERRBUF_LEN]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
- errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
- if (errstatus == OCI_ERROR) {
- #ifdef HAVE_OCI_INSTANT_CLIENT
- php_error_docref(NULL, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
- #else
- php_error_docref(NULL, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
- #endif
- if (OCI_G(env)
- && OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
- && *tmp_buf) {
- php_error_docref(NULL, E_WARNING, "%s", tmp_buf);
- }
- OCI_G(env) = NULL;
- OCI_G(err) = NULL;
- return;
- }
- errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
- if (errstatus == OCI_SUCCESS) {
- #if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
- /* This fixes PECL bug 15988 (sqlnet.ora not being read). The
- * root cause was fixed in Oracle 10.2.0.4 but there is no
- * compile time method to check for that precise patch level,
- * nor can it be guaranteed that runtime will use the same
- * patch level the code was compiled with. So, we do this
- * code for all non 11g versions.
- */
- OCICPool *cpoolh;
- ub4 cpoolmode = 0x80000000; /* Pass invalid mode to OCIConnectionPoolCreate */
- PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
- PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
- PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
- PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
- #endif
- } else {
- OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
- if (ora_error_code) {
- int tmp_buf_len = (int) strlen((char *)tmp_buf);
- if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
- tmp_buf[tmp_buf_len - 1] = '\0';
- }
- if (errstatus == OCI_SUCCESS_WITH_INFO) {
- php_error_docref(NULL, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
- } else {
- php_error_docref(NULL, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
- OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
- OCI_G(env) = NULL;
- OCI_G(err) = NULL;
- }
- }
- }
- }
- /* }}} */
- /* {{{ PHP_GINIT_FUNCTION
- *
- * Zerofill globals during module init
- */
- static PHP_GINIT_FUNCTION(oci)
- {
- memset(oci_globals, 0, sizeof(zend_oci_globals));
- }
- /* }}} */
- /* {{{ PHP_GSHUTDOWN_FUNCTION
- *
- * Called for thread shutdown in ZTS, after module shutdown for non-ZTS
- * Free global handles (if they were initialized before)
- */
- static PHP_GSHUTDOWN_FUNCTION(oci)
- {
- if (oci_globals->err) {
- oci_globals->in_call = 1;
- OCIHandleFree((dvoid *) oci_globals->err, OCI_HTYPE_ERROR);
- oci_globals->in_call = 0;
- oci_globals->err = NULL;
- }
- if (oci_globals->env) {
- oci_globals->in_call = 1;
- OCIHandleFree((dvoid *) oci_globals->env, OCI_HTYPE_ENV);
- oci_globals->in_call = 0;
- oci_globals->env = NULL;
- }
- }
- /* }}} */
- PHP_MINIT_FUNCTION(oci)
- {
- REGISTER_INI_ENTRIES();
- le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
- le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
- le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
- le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
- le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
- le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
- oci_lob_class_entry_ptr = register_class_OCILob();
- oci_coll_class_entry_ptr = register_class_OCICollection();
- /* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
- REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
- /* for $LOB->seek() */
- REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
- /* for $LOB->flush() */
- REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
- /* for OCIBindByName (real "oci" names + short "php" names */
- REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
- #if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
- REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
- #endif
- #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
- REGISTER_LONG_CONSTANT("SQLT_BOL",SQLT_BOL, CONST_CS | CONST_PERSISTENT);
- #endif
- REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
- REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
- #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
- REGISTER_LONG_CONSTANT("OCI_B_BOL",SQLT_BOL, CONST_CS | CONST_PERSISTENT);
- #endif
- /* for OCIFetchStatement */
- REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
- /* for OCIFetchInto & OCIResult */
- REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
- /* for OCINewDescriptor (real "oci" names + short "php" names */
- REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
- /* for OCIWriteTemporaryLob */
- REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
- /* for Transparent Application Failover */
- REGISTER_LONG_CONSTANT("OCI_FO_END", OCI_FO_END, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_ABORT", OCI_FO_ABORT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_REAUTH", OCI_FO_REAUTH, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_BEGIN", OCI_FO_BEGIN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_ERROR", OCI_FO_ERROR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_NONE", OCI_FO_NONE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_SESSION", OCI_FO_SESSION, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_SELECT", OCI_FO_SELECT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_TXNAL", OCI_FO_TXNAL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OCI_FO_RETRY", OCI_FO_RETRY, CONST_CS | CONST_PERSISTENT);
- return SUCCESS;
- }
- PHP_RINIT_FUNCTION(oci)
- {
- OCI_G(num_links) = OCI_G(num_persistent);
- OCI_G(errcode) = 0;
- OCI_G(edition) = NULL;
- return SUCCESS;
- }
- PHP_MSHUTDOWN_FUNCTION(oci)
- {
- OCI_G(shutdown) = 1;
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
- }
- PHP_RSHUTDOWN_FUNCTION(oci)
- {
- /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
- * unable to process a pconnection because of a refcount, the processing would happen from
- * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
- */
- zend_hash_apply(&EG(persistent_list), php_oci_persistent_helper);
- if (OCI_G(edition)) {
- efree(OCI_G(edition));
- }
- return SUCCESS;
- }
- PHP_MINFO_FUNCTION(oci)
- {
- char buf[32];
- #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
- char ver[256];
- #endif
- php_info_print_table_start();
- php_info_print_table_row(2, "OCI8 Support", "enabled");
- #if defined(HAVE_OCI8_DTRACE)
- php_info_print_table_row(2, "OCI8 DTrace Support", "enabled");
- #else
- php_info_print_table_row(2, "OCI8 DTrace Support", "disabled");
- #endif
- php_info_print_table_row(2, "OCI8 Version", PHP_OCI8_VERSION);
- #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
- php_oci_client_get_version(ver, sizeof(ver));
- php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver);
- #else
- php_info_print_table_row(2, "Oracle Run-time Client Library Version", "Unknown");
- #endif
- #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
- snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
- #elif defined(PHP_OCI8_ORACLE_VERSION)
- snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
- #else
- snprintf(buf, sizeof(buf), "Unknown");
- #endif
- #if defined(HAVE_OCI_INSTANT_CLIENT)
- php_info_print_table_row(2, "Oracle Compile-time Instant Client Version", buf);
- #else
- php_info_print_table_row(2, "Oracle Compile-time Version", buf);
- #endif
- #if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
- #if defined(PHP_OCI8_DEF_DIR)
- php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
- #endif
- #if defined(PHP_OCI8_DEF_SHARED_LIBADD)
- php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
- #endif
- #endif
- php_info_print_table_end();
- DISPLAY_INI_ENTRIES();
- php_info_print_table_start();
- php_info_print_table_header(2, "Statistics", "");
- snprintf(buf, sizeof(buf), ZEND_LONG_FMT, OCI_G(num_persistent));
- php_info_print_table_row(2, "Active Persistent Connections", buf);
- snprintf(buf, sizeof(buf), ZEND_LONG_FMT, OCI_G(num_links));
- php_info_print_table_row(2, "Active Connections", buf);
- php_info_print_table_end();
- }
- /* }}} */
- /* {{{ list destructors */
- /* {{{ php_oci_connection_list_dtor()
- *
- * Non-persistent connection destructor
- */
- static void php_oci_connection_list_dtor(zend_resource *entry)
- {
- php_oci_connection *connection = (php_oci_connection *)entry->ptr;
- if (connection) {
- php_oci_connection_close(connection);
- OCI_G(num_links)--;
- }
- }
- /* }}} */
- /* {{{ php_oci_pconnection_list_dtor()
- *
- * Persistent connection destructor
- */
- static void php_oci_pconnection_list_dtor(zend_resource *entry)
- {
- php_oci_connection *connection = (php_oci_connection *)entry->ptr;
- if (connection) {
- php_oci_connection_close(connection);
- OCI_G(num_persistent)--;
- OCI_G(num_links)--;
- }
- }
- /* }}} */
- /* {{{ php_oci_pconnection_list_np_dtor()
- *
- * Non-Persistent destructor for persistent connection - This gets invoked when
- * the refcount of this goes to zero in the regular list
- */
- static void php_oci_pconnection_list_np_dtor(zend_resource *entry)
- {
- php_oci_connection *connection = (php_oci_connection *)entry->ptr;
- zval *zvp;
- zend_resource *le;
- /*
- * We cannot get connection as NULL or as a stub in this function. This is the function that
- * turns a pconnection to a stub
- *
- * If oci_password_change() changed the password of a persistent connection, close the
- * connection and remove it from the persistent connection cache. This means subsequent scripts
- * will be prevented from being able to present the old (now invalid) password to a usable
- * connection to the database; they must use the new password.
- *
- * Check for conditions that warrant removal of the hash entry
- */
- if (!connection->is_open ||
- connection->passwd_changed ||
- (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
- OCI_G(in_call)) {
- /* Remove the hash entry if present */
- if (connection->hash_key) {
- zvp = zend_hash_find(&EG(persistent_list), connection->hash_key);
- le = zvp ? Z_RES_P(zvp) : NULL;
- if (le != NULL && le->type == le_pconnection && le->ptr == connection) {
- zend_hash_del(&EG(persistent_list), connection->hash_key);
- }
- else {
- php_oci_connection_close(connection);
- OCI_G(num_persistent)--;
- }
- }
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_P_DTOR_CLOSE_ENABLED()) {
- DTRACE_OCI8_CONNECT_P_DTOR_CLOSE(connection);
- }
- #endif /* HAVE_OCI8_DTRACE */
- } else {
- /*
- * Release the connection to underlying pool. We do this unconditionally so that
- * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
- * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
- * takes the refcount to zero.
- *
- * If oci_old_close_semantics is set, we artificially bump up the refcount and decremented
- * only at request shutdown.
- */
- php_oci_connection_release(connection);
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_P_DTOR_RELEASE_ENABLED()) {
- DTRACE_OCI8_CONNECT_P_DTOR_RELEASE(connection);
- }
- #endif /* HAVE_OCI8_DTRACE */
- }
- }
- /* }}} */
- /* {{{ php_oci_statement_list_dtor()
- *
- * Statement destructor
- */
- static void php_oci_statement_list_dtor(zend_resource *entry)
- {
- php_oci_statement *statement = (php_oci_statement *)entry->ptr;
- php_oci_statement_free(statement);
- }
- /* }}} */
- /* {{{ php_oci_descriptor_list_dtor()
- *
- * Descriptor destructor
- */
- static void php_oci_descriptor_list_dtor(zend_resource *entry)
- {
- php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
- php_oci_lob_free(descriptor);
- }
- /* }}} */
- /* {{{ php_oci_collection_list_dtor()
- *
- * Collection destructor
- */
- static void php_oci_collection_list_dtor(zend_resource *entry)
- {
- php_oci_collection *collection = (php_oci_collection *)entry->ptr;
- php_oci_collection_close(collection);
- }
- /* }}} */
- /* }}} */
- /* {{{ Hash Destructors */
- /* {{{ php_oci_define_hash_dtor()
- *
- * Define hash destructor
- */
- void php_oci_define_hash_dtor(zval *data)
- {
- php_oci_define *define = (php_oci_define *) Z_PTR_P(data);
- if (define->name) {
- efree(define->name);
- define->name = NULL;
- }
- zval_ptr_dtor(&define->val);
- efree(define);
- }
- /* }}} */
- /* {{{ php_oci_bind_hash_dtor()
- *
- * Bind hash destructor
- */
- void php_oci_bind_hash_dtor(zval *data)
- {
- php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data);
- if (!Z_ISUNDEF(bind->val)) {
- zval_ptr_dtor(&bind->val);
- ZVAL_UNDEF(&bind->val);
- }
- if (bind->array.elements) {
- efree(bind->array.elements);
- bind->array.elements = NULL;
- }
- if (bind->array.element_lengths) {
- efree(bind->array.element_lengths);
- bind->array.element_lengths = NULL;
- }
- if (bind->array.indicators) {
- efree(bind->array.indicators);
- bind->array.indicators = NULL;
- }
- efree(bind);
- }
- /* }}} */
- /* {{{ php_oci_column_hash_dtor()
- *
- * Column hash destructor
- */
- void php_oci_column_hash_dtor(zval *data)
- {
- php_oci_out_column *column = (php_oci_out_column *) Z_PTR_P(data);
- if (column->stmtid) {
- zend_list_close(column->stmtid);
- }
- if (column->descid) {
- if (GC_REFCOUNT(column->descid) == 1)
- zend_list_close(column->descid);
- else {
- GC_DELREF(column->descid);
- }
- }
- if (column->data) {
- efree(column->data);
- }
- if (column->name) {
- efree(column->name);
- }
- efree(column);
- }
- /* }}} */
- /* {{{ php_oci_descriptor_flush_hash_dtor()
- *
- * Flush descriptors on commit
- */
- void php_oci_descriptor_flush_hash_dtor(zval *data)
- {
- php_oci_descriptor *descriptor = (php_oci_descriptor *) Z_PTR_P(data);
- if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
- php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE);
- descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
- }
- data = NULL;
- }
- /* }}} */
- /* }}} */
- /* {{{ php_oci_connection_descriptors_free()
- *
- * Free descriptors for a connection
- */
- void php_oci_connection_descriptors_free(php_oci_connection *connection)
- {
- zend_hash_destroy(connection->descriptors);
- efree(connection->descriptors);
- connection->descriptors = NULL;
- connection->descriptor_count = 0;
- }
- /* }}} */
- /* {{{ php_oci_error()
- *
- * Fetch & print out error message if we get an error
- * Returns an Oracle error number
- */
- sb4 php_oci_error(OCIError *err_p, sword errstatus)
- {
- text errbuf[PHP_OCI_ERRBUF_LEN];
- sb4 errcode = 0; /* Oracle error number */
- switch (errstatus) {
- case OCI_SUCCESS:
- break;
- case OCI_SUCCESS_WITH_INFO:
- errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
- if (errcode) {
- php_error_docref(NULL, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
- } else {
- php_error_docref(NULL, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
- }
- break;
- case OCI_NEED_DATA:
- php_error_docref(NULL, E_WARNING, "OCI_NEED_DATA");
- break;
- case OCI_NO_DATA:
- errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
- if (errcode) {
- php_error_docref(NULL, E_WARNING, "%s", errbuf);
- } else {
- php_error_docref(NULL, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
- }
- break;
- case OCI_ERROR:
- errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
- if (errcode) {
- php_error_docref(NULL, E_WARNING, "%s", errbuf);
- } else {
- php_error_docref(NULL, E_WARNING, "Failed to fetch error message");
- }
- break;
- case OCI_INVALID_HANDLE:
- php_error_docref(NULL, E_WARNING, "OCI_INVALID_HANDLE");
- break;
- case OCI_STILL_EXECUTING:
- php_error_docref(NULL, E_WARNING, "OCI_STILL_EXECUTING");
- break;
- case OCI_CONTINUE:
- php_error_docref(NULL, E_WARNING, "OCI_CONTINUE");
- break;
- default:
- php_error_docref(NULL, E_WARNING, "Unknown OCI error code: %d", errstatus);
- break;
- }
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_ERROR_ENABLED()) {
- DTRACE_OCI8_ERROR((int)errstatus, (long)errcode);
- }
- #endif /* HAVE_OCI8_DTRACE */
- return errcode;
- }
- /* }}} */
- /* {{{ php_oci_fetch_errmsg()
- *
- * Fetch error message into the buffer from the error handle provided
- */
- sb4 php_oci_fetch_errmsg(OCIError *error_handle, text *error_buf, size_t error_buf_size)
- {
- sb4 error_code = 0;
- PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, error_buf, (ub4)error_buf_size, (ub4)OCI_HTYPE_ERROR));
- if (error_code) {
- int err_buf_len = (int) strlen((char *)error_buf);
- if (err_buf_len && error_buf[err_buf_len - 1] == '\n') {
- error_buf[err_buf_len - 1] = '\0';
- }
- }
- return error_code;
- }
- /* }}} */
- /* {{{ php_oci_fetch_sqltext_offset()
- *
- * Compute offset in the SQL statement
- */
- int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset)
- {
- sword errstatus;
- *sqltext = NULL;
- *error_offset = 0;
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
- if (errstatus != OCI_SUCCESS) {
- statement->errcode = php_oci_error(statement->err, errstatus);
- PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
- return 1;
- }
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
- if (errstatus != OCI_SUCCESS) {
- statement->errcode = php_oci_error(statement->err, errstatus);
- PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
- return 1;
- }
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_do_connect()
- *
- * Connect wrapper
- */
- void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
- {
- php_oci_connection *connection;
- char *username, *password;
- char *dbname = NULL, *charset = NULL;
- size_t username_len = 0, password_len = 0;
- size_t dbname_len = 0, charset_len = 0;
- zend_long session_mode = OCI_DEFAULT;
- /* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
- ZEND_PARSE_PARAMETERS_START(2, 5)
- Z_PARAM_STRING(username, username_len)
- Z_PARAM_STRING(password, password_len)
- Z_PARAM_OPTIONAL
- Z_PARAM_STRING_OR_NULL(dbname, dbname_len)
- Z_PARAM_STRING(charset, charset_len)
- Z_PARAM_LONG(session_mode)
- ZEND_PARSE_PARAMETERS_END();
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_ENTRY_ENABLED()) {
- DTRACE_OCI8_CONNECT_ENTRY(username, dbname, charset, session_mode, persistent, exclusive);
- }
- #endif /* HAVE_OCI8_DTRACE */
- if (!charset_len) {
- charset = NULL;
- }
- connection = php_oci_do_connect_ex(username, (int) username_len, password, (int) password_len, NULL, 0, dbname, (int) dbname_len, charset, session_mode, persistent, exclusive);
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_RETURN_ENABLED()) {
- DTRACE_OCI8_CONNECT_RETURN(connection);
- }
- #endif /* HAVE_OCI8_DTRACE */
- if (!connection) {
- RETURN_FALSE;
- }
- RETURN_RES(connection->id);
- }
- /* }}} */
- /* {{{ php_oci_do_connect_ex()
- *
- * The real connect function. Allocates all the resources needed, establishes the connection and
- * returns the result handle (or NULL)
- */
- php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, zend_long session_mode, int persistent, int exclusive)
- {
- zval *zvp;
- zend_resource *le = NULL;
- zend_resource new_le;
- php_oci_connection *connection = NULL;
- smart_str hashed_details = {0};
- time_t timestamp;
- php_oci_spool *session_pool = NULL;
- bool use_spool = 1; /* Default is to use client-side session pool */
- bool ping_done = 0;
- ub2 charsetid = 0;
- ub2 charsetid_nls_lang = 0;
- if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
- php_error_docref(NULL, E_WARNING, "Invalid session mode specified (" ZEND_LONG_FMT ")", session_mode);
- return NULL;
- }
- if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
- if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
- php_error_docref(NULL, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
- return NULL;
- }
- if (session_mode & PHP_OCI_CRED_EXT) {
- #ifdef PHP_WIN32
- /* Disable external authentication on Windows as Impersonation is not yet handled.
- * TODO: Re-enable this once OCI provides capability.
- */
- php_error_docref(NULL, E_WARNING, "External Authentication is not supported on Windows");
- return NULL;
- #endif
- if (username_len != 1 || username[0] != '/' || password_len != 0) {
- php_error_docref(NULL, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
- return NULL;
- }
- }
- if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
- /* Increase security by not caching privileged oci_pconnect() connections. The
- * connection becomes equivalent to oci_connect() or oci_new_connect().
- */
- persistent = 0;
- if (!OCI_G(privileged_connect)) {
- php_error_docref(NULL, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
- return NULL;
- }
- }
- }
- /* Initialize global handles if they weren't initialized before */
- if (OCI_G(env) == NULL) {
- php_oci_init_global_handles();
- if (OCI_G(env) == NULL) {
- return NULL;
- }
- }
- /* We cannot use the new session create logic (OCISessionGet from
- * client-side session pool) when privileged connect or password
- * change is attempted or OCI_CRED_EXT mode is specified.
- * TODO: Re-enable this when OCI provides support.
- */
- if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
- use_spool = 0;
- }
- smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
- smart_str_appendl_ex(&hashed_details, username, username_len, 0);
- smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
- /* DRCP: connection_class is an attribute of a connection */
- if (OCI_G(connection_class)){
- smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
- }
- smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
- /* Add edition attribute to the hash */
- if (OCI_G(edition)){
- smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
- }
- smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
- if (password_len) {
- zend_ulong password_hash;
- password_hash = zend_hash_func(password, password_len);
- smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
- }
- smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
- if (dbname) {
- smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
- }
- smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
- if (charset && *charset) {
- PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
- if (!charsetid) {
- php_error_docref(NULL, E_WARNING, "Invalid character set name: %s", charset);
- } else {
- smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
- }
- }
- /* use NLS_LANG if no or invalid charset specified */
- if (!charsetid) {
- size_t rsize = 0;
- sword result;
- PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
- if (result != OCI_SUCCESS) {
- charsetid_nls_lang = 0;
- }
- smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
- }
- timestamp = time(NULL);
- smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
- if (persistent) {
- smart_str_appendl_ex(&hashed_details, "pc", sizeof("pc") - 1, 0);
- }
- smart_str_0(&hashed_details);
- /* make it lowercase */
- zend_str_tolower(ZSTR_VAL(hashed_details.s), ZSTR_LEN(hashed_details.s));
- if (!exclusive && !new_password) {
- bool found = 0;
- if (persistent && ((zvp = zend_hash_find(&EG(persistent_list), hashed_details.s))) != NULL) {
- zend_resource *le = Z_RES_P(zvp);
- found = 1;
- /* found */
- if (le->type == le_pconnection) {
- connection = (php_oci_connection *)le->ptr;
- }
- } else if (!persistent && ((zvp = zend_hash_find(&EG(regular_list), hashed_details.s)) != NULL)) {
- le = Z_RES_P(zvp);
- found = 1;
- if (le->type == le_index_ptr) {
- zend_resource *ptr;
- ptr = (zend_resource *) le->ptr;
- if (ptr && (ptr->type == le_connection)) {
- connection = (php_oci_connection *)ptr->ptr;
- }
- }
- }
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_LOOKUP_ENABLED()) {
- DTRACE_OCI8_CONNECT_LOOKUP(connection, connection && connection->is_stub ? 1 : 0);
- }
- #endif /* HAVE_OCI8_DTRACE */
- /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
- * private spool A connection is a stub if it is only a cached structure and the real
- * connection is released to its underlying private session pool. We currently do not have
- * stub support for non-persistent conns.
- *
- * TODO: put in negative code for non-persistent stubs
- */
- if (connection && connection->is_persistent && connection->is_stub) {
- if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, (int) session_mode)) {
- smart_str_free(&hashed_details);
- zend_hash_del(&EG(persistent_list), connection->hash_key);
- return NULL;
- }
- /* We do the ping in php_oci_create_session, no need to ping again below */
- ping_done = 1;
- }
- if (connection) {
- if (connection->is_open) {
- /* found an open connection. now ping it */
- if (connection->is_persistent) {
- /* Check connection liveness in the following order:
- * 1) always check OCI_ATTR_SERVER_STATUS
- * 2) see if it's time to ping it
- * 3) ping it if needed
- */
- if (php_oci_connection_status(connection)) {
- /* Only ping if:
- *
- * 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
- *
- * 2) current_timestamp > next_ping, which means "it's time to check if it's
- * still alive"
- */
- if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection)) {
- /* server died */
- } else {
- php_oci_connection *tmp = (php_oci_connection *) NULL;
- zval *tmp_val = (zval *) NULL;
- /* okay, the connection is open and the server is still alive */
- connection->used_this_request = 1;
- if (connection->id) {
- tmp_val = zend_hash_index_find(&EG(regular_list), connection->id->handle);
- if ((tmp_val != NULL) && (Z_TYPE_P(tmp_val) == IS_RESOURCE)) {
- tmp = Z_RES_VAL_P(tmp_val);
- }
- if ((tmp_val != NULL) && (tmp != NULL) &&
- (ZSTR_LEN(tmp->hash_key) == ZSTR_LEN(hashed_details.s)) &&
- (memcmp(ZSTR_VAL(tmp->hash_key), ZSTR_VAL(hashed_details.s),
- ZSTR_LEN(tmp->hash_key)) == 0)) {
- connection = tmp;
- GC_ADDREF(connection->id);
- }
- } else {
- PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection);
- /* Persistent connections: For old close semantics we artificially
- * bump up the refcount to prevent the non-persistent destructor
- * from getting called until request shutdown. The refcount is
- * decremented in the persistent helper
- */
- if (OCI_G(old_oci_close_semantics)) {
- GC_ADDREF(connection->id);
- }
- }
- smart_str_free(&hashed_details);
- return connection;
- }
- }
- /* server died */
- } else {
- /* we do not ping non-persistent connections */
- smart_str_free(&hashed_details);
- GC_ADDREF(connection->id);
- return connection;
- }
- } /* is_open is true? */
- /* Server died - connection not usable. The is_open=true can also fall through to here,
- * if ping fails
- */
- if (persistent){
- connection->is_open = 0;
- connection->used_this_request = 1;
- /* We have to do a hash_del but need to preserve the resource if there is a positive
- * refcount. Set the data pointer in the list entry to NULL
- */
- if (connection == connection->id->ptr && le) {
- le->ptr = NULL;
- }
- zend_hash_del(&EG(persistent_list), hashed_details.s);
- } else {
- /* We only remove the hash entry. The resource and the list entry with its pointer
- * to the resource are still intact
- */
- zend_hash_del(&EG(regular_list), hashed_details.s);
- }
- connection = NULL;
- } else if (found) {
- /* found something, but it's not a connection, delete it */
- if (persistent) {
- zend_hash_del(&EG(persistent_list), hashed_details.s);
- } else {
- zend_hash_del(&EG(regular_list), hashed_details.s);
- }
- }
- }
- /* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
- * a last resort, return a non-persistent connection.
- */
- if (persistent) {
- bool alloc_non_persistent = 0;
- if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
- /* try to find an idle connection and kill it */
- zend_hash_apply(&EG(persistent_list), php_oci_persistent_helper);
- if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
- /* all persistent connactions are in use, fallback to non-persistent connection creation */
- php_error_docref(NULL, E_NOTICE, "Too many open persistent connections (" ZEND_LONG_FMT ")", OCI_G(num_persistent));
- alloc_non_persistent = 1;
- }
- }
- if (alloc_non_persistent) {
- connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
- connection->hash_key = zend_string_dup(hashed_details.s, 0);
- connection->is_persistent = 0;
- ZVAL_UNDEF(&connection->taf_callback);
- #ifdef HAVE_OCI8_DTRACE
- connection->client_id = NULL;
- #endif
- } else {
- connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
- if (connection == NULL) {
- return NULL;
- }
- connection->hash_key = zend_string_dup(hashed_details.s, 1);
- if (connection->hash_key == NULL) {
- free(connection);
- return NULL;
- }
- connection->is_persistent = 1;
- ZVAL_UNDEF(&connection->taf_callback);
- #ifdef HAVE_OCI8_DTRACE
- connection->client_id = NULL;
- #endif
- }
- } else {
- connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
- connection->hash_key = zend_string_dup(hashed_details.s, 0);
- connection->is_persistent = 0;
- ZVAL_UNDEF(&connection->taf_callback);
- #ifdef HAVE_OCI8_DTRACE
- connection->client_id = NULL;
- #endif
- }
- /* {{{ Get the session pool that suits this connection request from the persistent list. This
- * step is only for non-persistent connections as persistent connections have private session
- * pools. Non-persistent conns use shared session pool to allow for optimizations such as
- * caching the physical connection (for DRCP) even when the non-persistent php connection is
- * destroyed.
- *
- * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
- */
- if (use_spool && !connection->is_persistent) {
- if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang))==NULL)
- {
- php_oci_connection_close(connection);
- smart_str_free(&hashed_details);
- return NULL;
- }
- }
- /* }}} */
- connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
- /* Mark password as unchanged by PHP during the duration of the database session */
- connection->passwd_changed = 0;
- smart_str_free(&hashed_details);
- if (charsetid) {
- connection->charset = charsetid;
- } else {
- connection->charset = charsetid_nls_lang;
- }
- /* Old session creation semantics when session pool cannot be used Eg: privileged
- * connect/password change
- */
- if (!use_spool) {
- if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, (int) session_mode)) {
- php_oci_connection_close(connection);
- return NULL;
- }
- } else {
- /* create using the client-side session pool */
- if (php_oci_create_session(connection, session_pool, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, (int) session_mode)) {
- php_oci_connection_close(connection);
- return NULL;
- }
- }
- /* Mark it as open */
- connection->is_open = 1;
- /* add to the appropriate hash */
- if (connection->is_persistent) {
- connection->used_this_request = 1;
- PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection);
- /* Persistent connections: For old close semantics we artificially bump up the refcount to
- * prevent the non-persistent destructor from getting called until request shutdown. The
- * refcount is decremented in the persistent helper
- */
- if (OCI_G(old_oci_close_semantics)) {
- GC_ADDREF(connection->id);
- }
- zend_register_persistent_resource_ex(connection->hash_key, connection, le_pconnection);
- OCI_G(num_persistent)++;
- OCI_G(num_links)++;
- } else if (!exclusive) {
- PHP_OCI_REGISTER_RESOURCE(connection, le_connection);
- new_le.ptr = connection->id;
- new_le.type = le_index_ptr;
- zend_hash_update_mem(&EG(regular_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource));
- OCI_G(num_links)++;
- } else {
- PHP_OCI_REGISTER_RESOURCE(connection, le_connection);
- OCI_G(num_links)++;
- }
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_TYPE_ENABLED()) {
- DTRACE_OCI8_CONNECT_TYPE(connection->is_persistent ? 1 : 0, exclusive ? 1 : 0, connection, OCI_G(num_persistent), OCI_G(num_links));
- }
- #endif /* HAVE_OCI8_DTRACE */
- return connection;
- }
- /* }}} */
- /* {{{ php_oci_connection_ping()
- *
- * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
- */
- static int php_oci_connection_ping(php_oci_connection *connection)
- {
- sword errstatus;
- #if (!((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))))
- char version[256];
- #endif
- OCI_G(errcode) = 0; /* assume ping is successful */
- /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
- * such as from Pre-10.1 servers, the error is still from the server and we would have
- * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
- * Pre-10.2 clients
- */
- #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
- PHP_OCI_CALL_RETURN(errstatus, OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
- #else
- /* use good old OCIServerVersion() */
- PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
- #endif
- if (errstatus == OCI_SUCCESS) {
- return 1;
- } else {
- sb4 error_code = 0;
- text tmp_buf[PHP_OCI_ERRBUF_LEN];
- /* Treat ORA-1010 as a successful Ping */
- OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
- if (error_code == 1010) {
- return 1;
- }
- OCI_G(errcode) = error_code;
- }
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_connection_status()
- *
- * Check connection status (pre-ping check)
- */
- static int php_oci_connection_status(php_oci_connection *connection)
- {
- ub4 ss = OCI_SERVER_NOT_CONNECTED;
- sword errstatus;
- /* get OCI_ATTR_SERVER_STATUS */
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
- if (errstatus == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
- return 1;
- }
- /* ignore errors here, just return failure */
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_connection_rollback()
- *
- * Rollback connection
- */
- int php_oci_connection_rollback(php_oci_connection *connection)
- {
- sword errstatus;
- PHP_OCI_CALL_RETURN(errstatus, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
- connection->rb_on_disconnect = 0;
- if (errstatus != OCI_SUCCESS) {
- connection->errcode = php_oci_error(connection->err, errstatus);
- PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
- return 1;
- }
- connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_connection_commit()
- *
- * Commit connection
- */
- int php_oci_connection_commit(php_oci_connection *connection)
- {
- sword errstatus;
- PHP_OCI_CALL_RETURN(errstatus, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
- connection->rb_on_disconnect = 0;
- if (errstatus != OCI_SUCCESS) {
- connection->errcode = php_oci_error(connection->err, errstatus);
- PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
- return 1;
- }
- connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_connection_close()
- *
- * Close the connection and free all its resources
- */
- static int php_oci_connection_close(php_oci_connection *connection)
- {
- int result = 0;
- bool in_call_save = OCI_G(in_call);
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECTION_CLOSE_ENABLED()) {
- DTRACE_OCI8_CONNECTION_CLOSE(connection);
- }
- #endif /* HAVE_OCI8_DTRACE */
- if (!connection->is_stub) {
- /* Release resources associated with connection */
- php_oci_connection_release(connection);
- }
- if (!connection->using_spool && connection->svc) {
- PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
- }
- if (connection->err) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
- }
- if (connection->authinfo) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
- }
- /* No Handlefrees for session pool connections */
- if (!connection->using_spool) {
- if (connection->session) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
- }
- if (connection->is_attached) {
- PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
- }
- if (connection->svc) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
- }
- if (connection->server) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
- }
- if (connection->env) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
- }
- } else if (connection->private_spool) {
- /* Keep this as the last member to be freed, as there are dependencies
- * (like env) on the session pool
- */
- php_oci_spool_close(connection->private_spool);
- connection->private_spool = NULL;
- }
- if (GC_REFCOUNT(connection->hash_key) >= 2) {
- zend_hash_del(&EG(regular_list), connection->hash_key);
- }
- if (connection->hash_key) {
- pefree(connection->hash_key, connection->is_persistent);
- connection->hash_key = NULL;
- }
- #ifdef HAVE_OCI8_DTRACE
- if (connection->client_id) {
- pefree(connection->client_id, connection->is_persistent);
- connection->client_id = NULL;
- }
- #endif /* HAVE_OCI8_DTRACE */
- if (!Z_ISUNDEF(connection->taf_callback)) {
- /* If it's NULL, then its value should be freed already */
- if (!Z_ISNULL(connection->taf_callback)) {
- zval_ptr_dtor(&connection->taf_callback);
- }
- ZVAL_UNDEF(&connection->taf_callback);
- }
- pefree(connection, connection->is_persistent);
- connection = NULL;
- OCI_G(in_call) = in_call_save;
- return result;
- }
- /* }}} */
- /* {{{ php_oci_connection_release()
- *
- * Release the connection's resources. This involves freeing descriptors and rolling back
- * transactions, setting timeout-related parameters etc. For session-pool using connections, the
- * underlying connection is released to its session pool.
- */
- int php_oci_connection_release(php_oci_connection *connection)
- {
- int result = 0;
- bool in_call_save = OCI_G(in_call);
- time_t timestamp = time(NULL);
- if (connection->is_stub) {
- return 0;
- }
- if (connection->descriptors) {
- php_oci_connection_descriptors_free(connection);
- }
- if (connection->svc) {
- /* rollback outstanding transactions */
- if (connection->rb_on_disconnect) {
- if (php_oci_connection_rollback(connection)) {
- /* rollback failed */
- result = 1;
- }
- }
- }
- if (OCI_G(persistent_timeout) > 0) {
- connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
- }
- /* We may have half-cooked connections to clean up */
- if (connection->next_pingp) {
- if (OCI_G(ping_interval) >= 0) {
- *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
- } else {
- /* ping_interval is -1 */
- *(connection->next_pingp) = 0;
- }
- }
- /* Release the session (stubs are filtered out at the beginning)*/
- if (connection->using_spool) {
- ub4 rlsMode = OCI_DEFAULT;
- if (result) {
- rlsMode |= OCI_SESSRLS_DROPSESS;
- }
- /* Sessions for non-persistent connections should be dropped. For 11 and above, the session
- * pool has its own mechanism for doing so for purity NEW connections. We need to do so
- * explicitly for 10.2 and earlier.
- */
- #if (!(OCI_MAJOR_VERSION >= 11))
- if (!connection->is_persistent) {
- rlsMode |= OCI_SESSRLS_DROPSESS;
- }
- #endif
- if (connection->svc) {
- PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
- 0, rlsMode));
- }
- /* It no longer has relation with the database session. However authinfo and env are
- * cached
- */
- connection->svc = NULL;
- connection->server = NULL;
- connection->session = NULL;
- connection->is_attached = connection->is_open = connection->rb_on_disconnect = connection->used_this_request = 0;
- connection->is_stub = 1;
- /* Cut the link between the connection structure and the time_t structure allocated within
- * the OCI session
- */
- connection->next_pingp = NULL;
- #ifdef HAVE_OCI8_DTRACE
- if (connection->client_id) {
- pefree(connection->client_id, connection->is_persistent);
- connection->client_id = NULL;
- }
- #endif /* HAVE_OCI8_DTRACE */
- }
- /* Always set id to null, so next time a new resource is being registered. */
- connection->id = NULL;
- OCI_G(in_call) = in_call_save;
- return result;
- }
- /* }}} */
- /* {{{ php_oci_password_change()
- *
- * Change password for the user with the username given
- */
- int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len)
- {
- sword errstatus;
- PHP_OCI_CALL_RETURN(errstatus, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
- if (errstatus != OCI_SUCCESS) {
- connection->errcode = php_oci_error(connection->err, errstatus);
- PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
- return 1;
- }
- connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
- connection->passwd_changed = 1;
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_client_get_version()
- *
- * Get Oracle client library version
- */
- void php_oci_client_get_version(char *version, size_t version_size)
- {
- #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIClientVersion only available 10.2 onwards */
- sword major_version = 0;
- sword minor_version = 0;
- sword update_num = 0;
- sword patch_num = 0;
- sword port_update_num = 0;
- PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num));
- snprintf(version, version_size, "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num);
- #else
- memcpy(version, "Unknown", sizeof("Unknown"));
- #endif
- }
- /* }}} */
- /* {{{ php_oci_server_get_version()
- *
- * Get Oracle server version
- */
- int php_oci_server_get_version(php_oci_connection *connection, char *version, size_t version_size)
- {
- sword errstatus;
- PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, connection->err, (text *)version, (ub4) version_size, OCI_HTYPE_SVCCTX));
- if (errstatus != OCI_SUCCESS) {
- connection->errcode = php_oci_error(connection->err, errstatus);
- PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
- return 1;
- }
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_column_to_zval()
- *
- * Convert php_oci_out_column struct into zval
- */
- int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode)
- {
- php_oci_descriptor *descriptor;
- ub4 lob_length;
- int column_size;
- char *lob_buffer = (char *)0;
- int lob_fetch_status;
- if (column->indicator == -1) { /* column is NULL */
- ZVAL_NULL(value);
- return 0;
- }
- if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
- ZVAL_RES(value, column->stmtid);
- GC_ADDREF(column->stmtid);
- } else if (column->is_descr) {
- if (column->data_type != SQLT_RDD) {
- /* reset descriptor's length */
- descriptor = (php_oci_descriptor *) column->descid->ptr;
- if (!descriptor) {
- php_error_docref(NULL, E_WARNING, "Unable to find LOB descriptor #" ZEND_LONG_FMT, column->descid->handle);
- return 1;
- }
- descriptor->lob_size = -1;
- descriptor->lob_current_position = 0;
- descriptor->buffering = 0;
- }
- if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
- /* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
- if (column->chunk_size)
- descriptor->chunk_size = column->chunk_size;
- lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length);
- if (descriptor->chunk_size) /* Cache the chunk_size to avoid recalling OCILobGetChunkSize */
- column->chunk_size = descriptor->chunk_size;
- php_oci_temp_lob_close(descriptor);
- if (lob_fetch_status) {
- ZVAL_FALSE(value);
- return 1;
- } else {
- if (lob_length > 0) {
- ZVAL_STRINGL(value, lob_buffer, lob_length);
- } else {
- ZVAL_EMPTY_STRING(value);
- }
- if (lob_buffer)
- efree(lob_buffer);
- return 0;
- }
- } else {
- /* return the locator */
- object_init_ex(value, oci_lob_class_entry_ptr);
- add_property_resource(value, "descriptor", column->descid);
- GC_ADDREF(column->descid);
- }
- } else {
- switch (column->retcode) {
- case 0:
- /* intact value */
- if (column->piecewise) {
- column_size = column->retlen4;
- } else {
- column_size = column->retlen;
- }
- break;
- default:
- ZVAL_FALSE(value);
- return 0;
- }
- ZVAL_STRINGL(value, column->data, column_size);
- }
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_fetch_row()
- *
- * Fetch the next row from the given statement
- * Has logic for Oracle 12c Implicit Result Sets
- */
- void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
- {
- zval *z_statement, *array;
- zval *placeholder = (zval*) NULL;
- /* zend_array *temp_array = (zend_array *) NULL;*/
- php_oci_statement *statement; /* statement that will be fetched from */
- #if (OCI_MAJOR_VERSION >= 12)
- php_oci_statement *invokedstatement; /* statement this function was invoked with */
- #endif /* OCI_MAJOR_VERSION */
- php_oci_out_column *column;
- ub4 nrows = 1;
- int i;
- zend_long fetch_mode = 0;
- if (expected_args > 2) {
- /* only for ocifetchinto BC */
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_RESOURCE(z_statement)
- Z_PARAM_ZVAL(array)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(fetch_mode)
- ZEND_PARSE_PARAMETERS_END();
- if (ZEND_NUM_ARGS() == 2) {
- fetch_mode = mode;
- }
- if (Z_ISREF_P(array))
- placeholder = Z_REFVAL_P(array);
- else
- placeholder = array;
- } else if (expected_args == 2) {
- /* only for oci_fetch_array() */
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_RESOURCE(z_statement)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(fetch_mode)
- ZEND_PARSE_PARAMETERS_END();
- if (ZEND_NUM_ARGS() == 1) {
- fetch_mode = mode;
- }
- } else {
- /* for all oci_fetch_*() */
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_RESOURCE(z_statement)
- ZEND_PARSE_PARAMETERS_END();
- fetch_mode = mode;
- }
- if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
- /* none of the modes present, use the default one */
- if (mode & PHP_OCI_ASSOC) {
- fetch_mode |= PHP_OCI_ASSOC;
- }
- if (mode & PHP_OCI_NUM) {
- fetch_mode |= PHP_OCI_NUM;
- }
- }
- #if (OCI_MAJOR_VERSION < 12)
- PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
- if (php_oci_statement_fetch(statement, nrows)) {
- RETURN_FALSE; /* end of fetch */
- }
- #else /* OCI_MAJOR_VERSION */
- PHP_OCI_ZVAL_TO_STATEMENT(z_statement, invokedstatement);
- if (invokedstatement->impres_flag == PHP_OCI_IMPRES_NO_CHILDREN ||
- invokedstatement->impres_flag == PHP_OCI_IMPRES_IS_CHILD) {
- /* Already know there are no Implicit Result Sets */
- statement = invokedstatement;
- } else if (invokedstatement->impres_flag == PHP_OCI_IMPRES_HAS_CHILDREN) {
- /* Previously saw an Implicit Result Set in an earlier invocation of php_oci_fetch_row */
- statement = (php_oci_statement *)invokedstatement->impres_child_stmt;
- } else {
- sword errstatus;
- /* Check for an Implicit Result Set on this statement handle */
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)invokedstatement->stmt, OCI_HTYPE_STMT,
- (dvoid *) &invokedstatement->impres_count,
- (ub4 *)NULL, OCI_ATTR_IMPLICIT_RESULT_COUNT, invokedstatement->err));
- if (errstatus) {
- RETURN_FALSE;
- }
- if (invokedstatement->impres_count > 0) {
- /* Make it so the fetch occurs on the first Implicit Result Set */
- statement = php_oci_get_implicit_resultset(invokedstatement);
- if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT))
- RETURN_FALSE;
- invokedstatement->impres_count--;
- invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement;
- invokedstatement->impres_flag = PHP_OCI_IMPRES_HAS_CHILDREN;
- } else {
- statement = invokedstatement; /* didn't find Implicit Result Sets */
- invokedstatement->impres_flag = PHP_OCI_IMPRES_NO_CHILDREN; /* Don't bother checking again */
- }
- }
- if (php_oci_statement_fetch(statement, nrows)) {
- /* End of fetch */
- if (invokedstatement->impres_count > 0) {
- /* Check next Implicit Result Set */
- statement = php_oci_get_implicit_resultset(invokedstatement);
- if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT))
- RETURN_FALSE;
- invokedstatement->impres_count--;
- invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement;
- if (php_oci_statement_fetch(statement, nrows)) {
- /* End of all fetches */
- RETURN_FALSE;
- }
- } else {
- RETURN_FALSE;
- }
- }
- #endif /* OCI_MAJOR_VERSION */
- if (placeholder == NULL) {
- placeholder = return_value;
- } else {
- zval_ptr_dtor(placeholder);
- }
- array_init(placeholder);
- for (i = 0; i < statement->ncolumns; i++) {
- column = php_oci_statement_get_column(statement, i + 1, NULL, 0);
- if (column == NULL) {
- continue;
- }
- if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
- continue;
- }
- if (!(column->indicator == -1)) {
- zval element;
- php_oci_column_to_zval(column, &element, (int) fetch_mode);
- if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
- add_index_zval(placeholder, i, &element);
- }
- if (fetch_mode & PHP_OCI_ASSOC) {
- if (fetch_mode & PHP_OCI_NUM) {
- Z_TRY_ADDREF_P(&element);
- }
- add_assoc_zval(placeholder, column->name, &element);
- }
- } else {
- if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
- add_index_null(placeholder, i);
- }
- if (fetch_mode & PHP_OCI_ASSOC) {
- add_assoc_null(placeholder, column->name);
- }
- }
- }
- if (expected_args > 2) {
- RETURN_LONG(statement->ncolumns);
- }
- }
- /* }}} */
- /* {{{ php_oci_persistent_helper()
- *
- * Helper function to close/rollback persistent connections at the end of request. A return value of
- * 1 indicates that the connection is to be destroyed
- */
- static int php_oci_persistent_helper(zval *zv)
- {
- zend_resource *le = Z_RES_P(zv);
- time_t timestamp;
- php_oci_connection *connection;
- timestamp = time(NULL);
- /* Persistent connection stubs are also counted as they have private session pools */
- if (le->type == le_pconnection) {
- connection = (php_oci_connection *)le->ptr;
- /* Remove TAF callback function as it's bound to current request */
- if (connection->used_this_request && !Z_ISUNDEF(connection->taf_callback) && !Z_ISNULL(connection->taf_callback)) {
- php_oci_unregister_taf_callback(connection);
- }
- if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CONNECT_EXPIRY_ENABLED()) {
- DTRACE_OCI8_CONNECT_EXPIRY(connection, connection->is_stub ? 1 : 0, (long)connection->idle_expiry, (long)timestamp);
- }
- #endif /* HAVE_OCI8_DTRACE */
- if (connection->idle_expiry < timestamp) {
- /* connection has timed out */
- return ZEND_HASH_APPLY_REMOVE;
- }
- }
- }
- return ZEND_HASH_APPLY_KEEP;
- }
- /* }}} */
- /* {{{ php_oci_create_spool()
- *
- * Create(alloc + Init) Session pool for the given dbname and charsetid
- */
- static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, zend_string *hash_key, int charsetid)
- {
- php_oci_spool *session_pool = NULL;
- bool iserror = 0;
- ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
- OCIAuthInfo *spoolAuth = NULL;
- sword errstatus;
- /* Allocate sessionpool out of persistent memory */
- session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
- if (session_pool == NULL) {
- iserror = 1;
- goto exit_create_spool;
- }
- /* Populate key if passed */
- if (hash_key && (ZSTR_LEN(hash_key) > 0)) {
- session_pool->spool_hash_key = zend_string_dup(hash_key, 1);
- if (session_pool->spool_hash_key == NULL) {
- iserror = 1;
- goto exit_create_spool;
- }
- }
- /* Create the session pool's env */
- if (!(session_pool->env = php_oci_create_env(charsetid))) {
- iserror = 1;
- goto exit_create_spool;
- }
- /* Allocate the pool handle */
- PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- goto exit_create_spool;
- }
- /* Allocate the session pool error handle - This only for use in the destructor, as there is a
- * generic bug which can free up the OCI_G(err) variable before destroying connections. We
- * cannot use this for other roundtrip calls as there is no way the user can access this error
- */
- PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- goto exit_create_spool;
- }
- /* Disable RLB as we mostly have single-connection pools */
- #if (OCI_MAJOR_VERSION > 10)
- poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
- #else
- poolmode = OCI_SPC_HOMOGENEOUS;
- #endif
- #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
- /* {{{ Allocate auth handle for session pool */
- PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- goto exit_create_spool;
- }
- /* }}} */
- /* {{{ Set the edition attribute on the auth handle */
- if (OCI_G(edition)) {
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err)));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- goto exit_create_spool;
- }
- }
- /* }}} */
- /* {{{ Set the driver name attribute on the auth handle */
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- goto exit_create_spool;
- }
- /* }}} */
- /* {{{ Set the auth handle on the session pool */
- PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err)));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- goto exit_create_spool;
- }
- /* }}} */
- #endif
- /* Create the homogeneous session pool - We have different session pools for every different
- * username, password, charset and dbname.
- */
- PHP_OCI_CALL_RETURN(errstatus, OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
- if (errstatus != OCI_SUCCESS) {
- OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
- iserror = 1;
- }
- exit_create_spool:
- if (iserror && session_pool) {
- php_oci_spool_close(session_pool);
- session_pool = NULL;
- }
- if (spoolAuth) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
- }
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_SESSPOOL_CREATE_ENABLED()) {
- DTRACE_OCI8_SESSPOOL_CREATE(session_pool);
- }
- #endif /* HAVE_OCI8_DTRACE */
- return session_pool;
- }
- /* }}} */
- /* {{{ php_oci_get_spool()
- *
- * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
- * non-persistent connections.
- */
- static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid)
- {
- smart_str spool_hashed_details = {0};
- php_oci_spool *session_pool = NULL;
- zend_resource *spool_out_le = NULL;
- bool iserror = 0;
- zval *spool_out_zv = NULL;
- /* {{{ Create the spool hash key */
- smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
- smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
- smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
- /* Add edition attribute to the hash */
- if (OCI_G(edition)){
- smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
- }
- smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
- if (password_len) {
- zend_ulong password_hash;
- password_hash = zend_hash_func(password, password_len);
- smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
- }
- smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
- if (dbname_len) {
- smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
- }
- smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
- smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
- /* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
- smart_str_0(&spool_hashed_details);
- zend_str_tolower(ZSTR_VAL(spool_hashed_details.s), ZSTR_LEN(spool_hashed_details.s));
- /* }}} */
- spool_out_zv = zend_hash_find(&EG(persistent_list), spool_hashed_details.s);
- if (spool_out_zv != NULL) {
- spool_out_le = Z_RES_P(spool_out_zv);
- }
- if (spool_out_le == NULL) {
- session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.s, charsetid);
- if (session_pool == NULL) {
- iserror = 1;
- goto exit_get_spool;
- }
- zend_register_persistent_resource_ex(session_pool->spool_hash_key, session_pool, le_psessionpool);
- } else if (spool_out_le->type == le_psessionpool &&
- ZSTR_LEN(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == ZSTR_LEN(spool_hashed_details.s) &&
- memcmp(ZSTR_VAL(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key), ZSTR_VAL(spool_hashed_details.s), ZSTR_LEN(spool_hashed_details.s)) == 0) {
- /* retrieve the cached session pool */
- session_pool = (php_oci_spool *)(spool_out_le->ptr);
- }
- exit_get_spool:
- smart_str_free(&spool_hashed_details);
- if (iserror && session_pool) {
- php_oci_spool_close(session_pool);
- session_pool = NULL;
- }
- return session_pool;
- }
- /* }}} */
- /* {{{ php_oci_create_env()
- *
- * Create the OCI environment choosing the correct function for the OCI version
- */
- static OCIEnv *php_oci_create_env(ub2 charsetid)
- {
- OCIEnv *retenv = NULL;
- /* create an environment using the character set id */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIEnvNlsCreate, (&retenv, OCI_G(events) ? PHP_OCI_INIT_MODE | OCI_EVENTS : PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, charsetid, charsetid));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- sb4 ora_error_code = 0;
- text ora_msg_buf[PHP_OCI_ERRBUF_LEN]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
- #ifdef HAVE_OCI_INSTANT_CLIENT
- php_error_docref(NULL, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
- #else
- php_error_docref(NULL, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
- #endif
- if (retenv
- && OCIErrorGet(retenv, (ub4)1, NULL, &ora_error_code, ora_msg_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
- && *ora_msg_buf) {
- php_error_docref(NULL, E_WARNING, "%s", ora_msg_buf);
- }
- return NULL;
- }
- return retenv;
- }
- /* }}} */
- /* {{{ php_oci_old_create_session()
- *
- * This function is to be deprecated in future in favour of OCISessionGet which is used in
- * php_oci_do_connect_ex
- */
- static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode)
- {
- ub4 statement_cache_size = 0;
- if (OCI_G(statement_cache_size) > 0) {
- if (OCI_G(statement_cache_size) > SB4MAXVAL)
- statement_cache_size = (ub4) SB4MAXVAL;
- else
- statement_cache_size = (ub4) OCI_G(statement_cache_size);
- }
- /* Create the OCI environment separate for each connection */
- if (!(connection->env = php_oci_create_env(connection->charset))) {
- return 1;
- }
- /* {{{ Allocate our server handle */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- /* {{{ Attach to the server */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- connection->is_attached = 1;
- /* {{{ Allocate our session handle */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- /* {{{ Allocate our private error-handle */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- /* {{{ Allocate our service-context */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- /* {{{ Set the username */
- if (username) {
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) username, (ub4) username_len, (ub4) OCI_ATTR_USERNAME, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- }
- /* }}} */
- /* {{{ Set the password */
- if (password) {
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) password, (ub4) password_len, (ub4) OCI_ATTR_PASSWORD, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- }
- /* }}} */
- /* {{{ Set the edition attribute on the session handle */
- #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
- if (OCI_G(edition)) {
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(edition), (ub4) (strlen(OCI_G(edition))), (ub4) OCI_ATTR_EDITION, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- }
- #endif
- /* }}} */
- /* {{{ Set the driver name attribute on the session handle */
- #if (OCI_MAJOR_VERSION >= 11)
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- #endif
- /* }}} */
- /* {{{ Set the server handle in the service handle */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- /* {{{ Set the authentication handle in the service handle */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- if (new_password) {
- /* {{{ Try to change password if new one was provided */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPasswordChange, (connection->svc, OCI_G(err), (text *)username, username_len, (text *)password, password_len, (text *)new_password, new_password_len, OCI_AUTH));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* }}} */
- } else {
- /* {{{ start the session */
- ub4 cred_type = OCI_CRED_RDBMS;
- /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
- if (session_mode & PHP_OCI_CRED_EXT) {
- cred_type = OCI_CRED_EXT;
- session_mode ^= PHP_OCI_CRED_EXT;
- }
- session_mode |= OCI_STMT_CACHE;
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
- * user's password has expired, but is still usable.
- */
- if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
- return 1;
- }
- }
- /* }}} */
- }
- /* Brand new connection: Init and update the next_ping in the connection */
- if (php_oci_ping_init(connection, OCI_G(err)) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* Successfully created session */
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_create_session()
- *
- * Create session using client-side session pool - new norm
- */
- static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode)
- {
- php_oci_spool *actual_spool = NULL;
- #if (OCI_MAJOR_VERSION > 10)
- ub4 purity = -2; /* Illegal value to initialize */
- #endif
- time_t timestamp = time(NULL);
- ub4 statement_cache_size = 0;
- if (OCI_G(statement_cache_size) > 0) {
- if (OCI_G(statement_cache_size) > SB4MAXVAL)
- statement_cache_size = (ub4) SB4MAXVAL;
- else
- statement_cache_size = (ub4) OCI_G(statement_cache_size);
- }
- /* Persistent connections have private session pools */
- if (connection->is_persistent && !connection->private_spool &&
- !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, connection->charset))) {
- return 1;
- }
- actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
- connection->env = actual_spool->env;
- /* Do this upfront so that connection close on an error would know that this is a session pool
- * connection. Failure to do this would result in crashes in error scenarios
- */
- if (!connection->using_spool) {
- connection->using_spool = 1;
- }
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_SESSPOOL_TYPE_ENABLED()) {
- DTRACE_OCI8_SESSPOOL_TYPE(session_pool ? 1 : 0, session_pool ? session_pool : connection->private_spool);
- }
- #endif /* HAVE_OCI8_DTRACE */
- /* The passed in "connection" can be a cached stub from plist or freshly created. In the former
- * case, we do not have to allocate any handles
- */
- if (!connection->err) {
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- }
- /* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
- if (!connection->authinfo) {
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* Set the Connection class and purity if OCI client version >= 11g */
- #if (OCI_MAJOR_VERSION > 10)
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(connection_class), (ub4)(strlen(OCI_G(connection_class))), (ub4)OCI_ATTR_CONNECTION_CLASS, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- if (connection->is_persistent)
- purity = OCI_ATTR_PURITY_SELF;
- else
- purity = OCI_ATTR_PURITY_NEW;
- PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_AUTHINFO, (dvoid *) &purity, (ub4)0, (ub4)OCI_ATTR_PURITY, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- #endif
- }
- /* }}} */
- /* {{{ Debug statements */
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_SESSPOOL_STATS_ENABLED()) {
- ub4 numfree = 0, numbusy = 0, numopen = 0;
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numopen, (ub4 *)0, OCI_ATTR_SPOOL_OPEN_COUNT, OCI_G(err)));
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numbusy, (ub4 *)0, OCI_ATTR_SPOOL_BUSY_COUNT, OCI_G(err)));
- numfree = numopen - numbusy; /* number of free connections in the pool */
- DTRACE_OCI8_SESSPOOL_STATS(numfree, numbusy, numopen);
- }
- #endif /* HAVE_OCI8_DTRACE */
- /* }}} */
- /* Ping loop: Ping and loop till we get a good connection. When a database instance goes
- * down, it can leave several bad connections that need to be flushed out before getting a
- * good one. In non-RAC, we always get a brand new connection at the end of the loop and in
- * RAC, we can get a good connection from a different instance before flushing out all bad
- * ones. We do not need to ping brand new connections.
- */
- do {
- /* Continue to use the global error handle as the connection is closed when an error occurs */
- PHP_OCI_CALL_RETURN(OCI_G(errcode),OCISessionGet, (connection->env, OCI_G(err), &(connection->svc), (OCIAuthInfo *)connection->authinfo, (OraText *)actual_spool->poolname, (ub4)actual_spool->poolname_len, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- /* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
- * is still usable.
- */
- if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
- return 1;
- }
- }
- /* {{{ Populate the session and server fields of the connection */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->server), (ub4 *)0, OCI_ATTR_SERVER, OCI_G(err)));
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err)));
- /* }}} */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- if (!(connection->next_pingp)){
- /* This is a brand new connection, we need not ping, but have to initialize ping */
- if (php_oci_ping_init(connection, OCI_G(err)) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- } else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
- if (php_oci_connection_ping(connection)) {
- /* Got a good connection - update next_ping and get out of ping loop */
- *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
- } else {
- /* Bad connection - remove from pool */
- PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
- connection->svc = NULL;
- connection->server = NULL;
- connection->session = NULL;
- }
- } /* If ping applicable */
- } while (!(connection->svc));
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- php_oci_error(OCI_G(err), OCI_G(errcode));
- return 1;
- }
- /* Session is now taken from the session pool and attached and open */
- connection->is_stub = 0;
- connection->is_attached = connection->is_open = 1;
- return 0;
- }
- /* }}} */
- /* {{{ php_oci_spool_list_dtor()
- *
- * Session pool destructor function
- */
- static void php_oci_spool_list_dtor(zend_resource *entry)
- {
- php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
- if (session_pool) {
- php_oci_spool_close(session_pool);
- }
- return;
- }
- /* }}} */
- /* {{{ php_oci_spool_close()
- *
- * Destroys the OCI Session Pool
- */
- static void php_oci_spool_close(php_oci_spool *session_pool)
- {
- if (session_pool->poolname_len) {
- PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
- (dvoid *) session_pool->err, OCI_SPD_FORCE));
- }
- if (session_pool->poolh) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
- }
- if (session_pool->err) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
- }
- if (session_pool->env) {
- PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
- }
- if (session_pool->spool_hash_key) {
- free(session_pool->spool_hash_key);
- }
- free(session_pool);
- }
- /* }}} */
- /* {{{ php_oci_ping_init()
- *
- * Initializes the next_ping time as a context value in the connection. We now use
- * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
- * non-persistent DRCP connections
- */
- static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh)
- {
- time_t *next_pingp = NULL;
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- return OCI_G(errcode);
- }
- /* This must be a brand-new connection. Allocate memory for the ping */
- if (!next_pingp) {
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- return OCI_G(errcode);
- }
- }
- if (OCI_G(ping_interval) >= 0) {
- time_t timestamp = time(NULL);
- *next_pingp = timestamp + OCI_G(ping_interval);
- } else {
- *next_pingp = 0;
- }
- /* Set the new ping value into the connection */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
- if (OCI_G(errcode) != OCI_SUCCESS) {
- OCIMemoryFree(connection->session, errh, next_pingp);
- return OCI_G(errcode);
- }
- /* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
- connection->next_pingp = next_pingp;
- return OCI_SUCCESS;
- }
- /* }}} */
- /* {{{ php_oci_dtrace_check_connection()
- *
- * DTrace output for connections that may have become invalid and marked for reopening
- */
- void php_oci_dtrace_check_connection(php_oci_connection *connection, sb4 errcode, ub4 serverStatus)
- {
- #ifdef HAVE_OCI8_DTRACE
- if (DTRACE_OCI8_CHECK_CONNECTION_ENABLED()) {
- DTRACE_OCI8_CHECK_CONNECTION(connection, connection->client_id, connection->is_open ? 1 : 0, (long)errcode, (unsigned long)serverStatus);
- }
- #endif /* HAVE_OCI8_DTRACE */
- }
- /* }}} */
- #endif /* HAVE_OCI8 */
|