oci8.c 117 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Stig Sæther Bakken <ssb@php.net> |
  16. | Thies C. Arntzen <thies@thieso.net> |
  17. | Maxim Maletsky <maxim@maxim.cx> |
  18. | |
  19. | Collection support by Andy Sautins <asautins@veripost.net> |
  20. | Temporary LOB support by David Benson <dbenson@mancala.com> |
  21. | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
  22. | |
  23. | Redesigned by: Antony Dovgal <antony@zend.com> |
  24. | Andi Gutmans <andi@php.net> |
  25. | Wez Furlong <wez@omniti.com> |
  26. +----------------------------------------------------------------------+
  27. */
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #include "php.h"
  32. #include "ext/standard/info.h"
  33. #include "php_ini.h"
  34. #include "zend_smart_str.h"
  35. #if HAVE_OCI8
  36. /* PHP 5.2 is the minimum supported version for OCI8 2.0 */
  37. #if PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1)
  38. #error Use PHP OCI8 1.4 for your version of PHP
  39. #elif PHP_MAJOR_VERSION < 7
  40. /* PHP 7 is the minimum supported version for OCI8 2.1 */
  41. #error Use PHP OCI8 2.0 for your version of PHP
  42. #endif
  43. #include "php_oci8.h"
  44. #include "php_oci8_int.h"
  45. #include "zend_hash.h"
  46. ZEND_DECLARE_MODULE_GLOBALS(oci)
  47. static PHP_GINIT_FUNCTION(oci);
  48. static PHP_GSHUTDOWN_FUNCTION(oci);
  49. /* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
  50. #ifndef Z_ADDREF_P
  51. #define Z_ADDREF_P(x) ZVAL_ADDREF(x)
  52. #endif
  53. /* For a user friendly message about environment setup */
  54. #if defined(PHP_WIN32)
  55. #define PHP_OCI8_LIB_PATH_MSG "PATH"
  56. #elif defined(__APPLE__)
  57. #define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
  58. #elif defined(_AIX)
  59. #define PHP_OCI8_LIB_PATH_MSG "LIBPATH"
  60. #elif defined(__hpux)
  61. #define PHP_OCI8_LIB_PATH_MSG "SHLIB_PATH"
  62. #else
  63. #define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
  64. #endif
  65. /* True globals, no need for thread safety */
  66. int le_connection;
  67. int le_pconnection;
  68. int le_statement;
  69. int le_descriptor;
  70. int le_psessionpool;
  71. int le_collection;
  72. zend_class_entry *oci_lob_class_entry_ptr;
  73. zend_class_entry *oci_coll_class_entry_ptr;
  74. #ifndef SQLT_BFILEE
  75. #define SQLT_BFILEE 114
  76. #endif
  77. #ifndef SQLT_CFILEE
  78. #define SQLT_CFILEE 115
  79. #endif
  80. #ifdef ZTS
  81. #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
  82. #else
  83. #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
  84. #endif
  85. /* {{{ static protos */
  86. static void php_oci_connection_list_dtor (zend_resource *);
  87. static void php_oci_pconnection_list_dtor (zend_resource *);
  88. static void php_oci_pconnection_list_np_dtor (zend_resource *);
  89. static void php_oci_statement_list_dtor (zend_resource *);
  90. static void php_oci_descriptor_list_dtor (zend_resource *);
  91. static void php_oci_spool_list_dtor(zend_resource *entry);
  92. static void php_oci_collection_list_dtor (zend_resource *);
  93. static int php_oci_persistent_helper(zval *zv);
  94. static int php_oci_connection_ping(php_oci_connection *);
  95. static int php_oci_connection_status(php_oci_connection *);
  96. static int php_oci_connection_close(php_oci_connection *);
  97. static void php_oci_spool_close(php_oci_spool *session_pool);
  98. static OCIEnv *php_oci_create_env(ub2 charsetid);
  99. 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);
  100. 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);
  101. 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);
  102. 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);
  103. static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh);
  104. /* }}} */
  105. /* {{{ dynamically loadable module stuff */
  106. #if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G) || defined(COMPILE_DL_OCI8_12C)
  107. ZEND_GET_MODULE(oci8)
  108. #endif /* COMPILE_DL */
  109. /* }}} */
  110. /* {{{ Function arginfo */
  111. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3)
  112. ZEND_ARG_INFO(0, statement_resource)
  113. ZEND_ARG_INFO(0, column_name)
  114. ZEND_ARG_INFO(1, variable)
  115. ZEND_ARG_INFO(0, type)
  116. ZEND_END_ARG_INFO()
  117. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_by_name, 0, 0, 3)
  118. ZEND_ARG_INFO(0, statement_resource)
  119. ZEND_ARG_INFO(0, column_name)
  120. ZEND_ARG_INFO(1, variable)
  121. ZEND_ARG_INFO(0, maximum_length)
  122. ZEND_ARG_INFO(0, type)
  123. ZEND_END_ARG_INFO()
  124. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_array_by_name, 0, 0, 4)
  125. ZEND_ARG_INFO(0, statement_resource)
  126. ZEND_ARG_INFO(0, column_name)
  127. ZEND_ARG_INFO(1, variable)
  128. ZEND_ARG_INFO(0, maximum_array_length)
  129. ZEND_ARG_INFO(0, maximum_item_length)
  130. ZEND_ARG_INFO(0, type)
  131. ZEND_END_ARG_INFO()
  132. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_descriptor, 0, 0, 1)
  133. ZEND_ARG_INFO(0, lob_descriptor)
  134. ZEND_END_ARG_INFO()
  135. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save, 0, 0, 2)
  136. ZEND_ARG_INFO(0, lob_descriptor)
  137. ZEND_ARG_INFO(0, data)
  138. ZEND_ARG_INFO(0, offset)
  139. ZEND_END_ARG_INFO()
  140. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import, 0, 0, 2)
  141. ZEND_ARG_INFO(0, lob_descriptor)
  142. ZEND_ARG_INFO(0, filename)
  143. ZEND_END_ARG_INFO()
  144. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_load, 0, 0, 1)
  145. ZEND_ARG_INFO(0, lob_descriptor)
  146. ZEND_END_ARG_INFO()
  147. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read, 0, 0, 2)
  148. ZEND_ARG_INFO(0, lob_descriptor)
  149. ZEND_ARG_INFO(0, length)
  150. ZEND_END_ARG_INFO()
  151. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_eof, 0, 0, 1)
  152. ZEND_ARG_INFO(0, lob_descriptor)
  153. ZEND_END_ARG_INFO()
  154. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_tell, 0, 0, 1)
  155. ZEND_ARG_INFO(0, lob_descriptor)
  156. ZEND_END_ARG_INFO()
  157. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_rewind, 0, 0, 1)
  158. ZEND_ARG_INFO(0, lob_descriptor)
  159. ZEND_END_ARG_INFO()
  160. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek, 0, 0, 2)
  161. ZEND_ARG_INFO(0, lob_descriptor)
  162. ZEND_ARG_INFO(0, offset)
  163. ZEND_ARG_INFO(0, whence)
  164. ZEND_END_ARG_INFO()
  165. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_size, 0, 0, 1)
  166. ZEND_ARG_INFO(0, lob_descriptor)
  167. ZEND_END_ARG_INFO()
  168. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write, 0, 0, 2)
  169. ZEND_ARG_INFO(0, lob_descriptor)
  170. ZEND_ARG_INFO(0, string)
  171. ZEND_ARG_INFO(0, length)
  172. ZEND_END_ARG_INFO()
  173. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append, 0, 0, 2)
  174. ZEND_ARG_INFO(0, lob_descriptor_to)
  175. ZEND_ARG_INFO(0, lob_descriptor_from)
  176. ZEND_END_ARG_INFO()
  177. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate, 0, 0, 1)
  178. ZEND_ARG_INFO(0, lob_descriptor)
  179. ZEND_ARG_INFO(0, length)
  180. ZEND_END_ARG_INFO()
  181. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase, 0, 0, 1)
  182. ZEND_ARG_INFO(0, lob_descriptor)
  183. ZEND_ARG_INFO(0, offset)
  184. ZEND_ARG_INFO(0, length)
  185. ZEND_END_ARG_INFO()
  186. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush, 0, 0, 1)
  187. ZEND_ARG_INFO(0, lob_descriptor)
  188. ZEND_ARG_INFO(0, flag)
  189. ZEND_END_ARG_INFO()
  190. ZEND_BEGIN_ARG_INFO_EX(arginfo_ocisetbufferinglob, 0, 0, 2)
  191. ZEND_ARG_INFO(0, lob_descriptor)
  192. ZEND_ARG_INFO(0, mode)
  193. ZEND_END_ARG_INFO()
  194. ZEND_BEGIN_ARG_INFO_EX(arginfo_ocigetbufferinglob, 0, 0, 1)
  195. ZEND_ARG_INFO(0, lob_descriptor)
  196. ZEND_END_ARG_INFO()
  197. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_copy, 0, 0, 2)
  198. ZEND_ARG_INFO(0, lob_descriptor_to)
  199. ZEND_ARG_INFO(0, lob_descriptor_from)
  200. ZEND_ARG_INFO(0, length)
  201. ZEND_END_ARG_INFO()
  202. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_is_equal, 0, 0, 2)
  203. ZEND_ARG_INFO(0, lob_descriptor)
  204. ZEND_ARG_INFO(0, lob_descriptor)
  205. ZEND_END_ARG_INFO()
  206. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export, 0, 0, 2)
  207. ZEND_ARG_INFO(0, lob_descriptor)
  208. ZEND_ARG_INFO(0, filename)
  209. ZEND_ARG_INFO(0, start)
  210. ZEND_ARG_INFO(0, length)
  211. ZEND_END_ARG_INFO()
  212. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_descriptor, 0, 0, 1)
  213. ZEND_ARG_INFO(0, connection_resource)
  214. ZEND_ARG_INFO(0, type)
  215. ZEND_END_ARG_INFO()
  216. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_rollback, 0, 0, 1)
  217. ZEND_ARG_INFO(0, connection_resource)
  218. ZEND_END_ARG_INFO()
  219. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_commit, 0, 0, 1)
  220. ZEND_ARG_INFO(0, connection_resource)
  221. ZEND_END_ARG_INFO()
  222. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_name, 0, 0, 2)
  223. ZEND_ARG_INFO(0, statement_resource)
  224. ZEND_ARG_INFO(0, column_number_or_name)
  225. ZEND_END_ARG_INFO()
  226. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_size, 0, 0, 2)
  227. ZEND_ARG_INFO(0, statement_resource)
  228. ZEND_ARG_INFO(0, column_number_or_name)
  229. ZEND_END_ARG_INFO()
  230. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_scale, 0, 0, 2)
  231. ZEND_ARG_INFO(0, statement_resource)
  232. ZEND_ARG_INFO(0, column_number_or_name)
  233. ZEND_END_ARG_INFO()
  234. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_precision, 0, 0, 2)
  235. ZEND_ARG_INFO(0, statement_resource)
  236. ZEND_ARG_INFO(0, column_number_or_name)
  237. ZEND_END_ARG_INFO()
  238. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type, 0, 0, 2)
  239. ZEND_ARG_INFO(0, statement_resource)
  240. ZEND_ARG_INFO(0, column_number_or_name)
  241. ZEND_END_ARG_INFO()
  242. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type_raw, 0, 0, 2)
  243. ZEND_ARG_INFO(0, statement_resource)
  244. ZEND_ARG_INFO(0, column_number_or_name)
  245. ZEND_END_ARG_INFO()
  246. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_is_null, 0, 0, 2)
  247. ZEND_ARG_INFO(0, statement_resource)
  248. ZEND_ARG_INFO(0, column_number_or_name)
  249. ZEND_END_ARG_INFO()
  250. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_internal_debug, 0, 0, 1)
  251. ZEND_ARG_INFO(0, mode)
  252. ZEND_END_ARG_INFO()
  253. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_execute, 0, 0, 1)
  254. ZEND_ARG_INFO(0, statement_resource)
  255. ZEND_ARG_INFO(0, mode)
  256. ZEND_END_ARG_INFO()
  257. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_cancel, 0, 0, 1)
  258. ZEND_ARG_INFO(0, statement_resource)
  259. ZEND_END_ARG_INFO()
  260. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch, 0, 0, 1)
  261. ZEND_ARG_INFO(0, statement_resource)
  262. ZEND_END_ARG_INFO()
  263. ZEND_BEGIN_ARG_INFO_EX(arginfo_ocifetchinto, 0, 0, 2)
  264. ZEND_ARG_INFO(0, statement_resource)
  265. ZEND_ARG_INFO(1, result)
  266. ZEND_ARG_INFO(0, mode)
  267. ZEND_END_ARG_INFO()
  268. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_all, 0, 0, 2)
  269. ZEND_ARG_INFO(0, statement_resource)
  270. ZEND_ARG_INFO(1, output)
  271. ZEND_ARG_INFO(0, skip)
  272. ZEND_ARG_INFO(0, maximum_rows)
  273. ZEND_ARG_INFO(0, flags)
  274. ZEND_END_ARG_INFO()
  275. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_object, 0, 0, 1)
  276. ZEND_ARG_INFO(0, statement_resource)
  277. ZEND_END_ARG_INFO()
  278. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_row, 0, 0, 1)
  279. ZEND_ARG_INFO(0, statement_resource)
  280. ZEND_END_ARG_INFO()
  281. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_assoc, 0, 0, 1)
  282. ZEND_ARG_INFO(0, statement_resource)
  283. ZEND_END_ARG_INFO()
  284. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_array, 0, 0, 1)
  285. ZEND_ARG_INFO(0, statement_resource)
  286. ZEND_ARG_INFO(0, mode)
  287. ZEND_END_ARG_INFO()
  288. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_statement, 0, 0, 1)
  289. ZEND_ARG_INFO(0, statement_resource)
  290. ZEND_END_ARG_INFO()
  291. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_close, 0, 0, 1)
  292. ZEND_ARG_INFO(0, connection_resource)
  293. ZEND_END_ARG_INFO()
  294. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_connect, 0, 0, 2)
  295. ZEND_ARG_INFO(0, username)
  296. ZEND_ARG_INFO(0, password)
  297. ZEND_ARG_INFO(0, connection_string)
  298. ZEND_ARG_INFO(0, character_set)
  299. ZEND_ARG_INFO(0, session_mode)
  300. ZEND_END_ARG_INFO()
  301. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_connect, 0, 0, 2)
  302. ZEND_ARG_INFO(0, username)
  303. ZEND_ARG_INFO(0, password)
  304. ZEND_ARG_INFO(0, connection_string)
  305. ZEND_ARG_INFO(0, character_set)
  306. ZEND_ARG_INFO(0, session_mode)
  307. ZEND_END_ARG_INFO()
  308. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_pconnect, 0, 0, 2)
  309. ZEND_ARG_INFO(0, username)
  310. ZEND_ARG_INFO(0, password)
  311. ZEND_ARG_INFO(0, connection_string)
  312. ZEND_ARG_INFO(0, character_set)
  313. ZEND_ARG_INFO(0, session_mode)
  314. ZEND_END_ARG_INFO()
  315. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_error, 0, 0, 0)
  316. ZEND_ARG_INFO(0, connection_or_statement_resource)
  317. ZEND_END_ARG_INFO()
  318. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_fields, 0, 0, 1)
  319. ZEND_ARG_INFO(0, statement_resource)
  320. ZEND_END_ARG_INFO()
  321. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2)
  322. ZEND_ARG_INFO(0, connection_resource)
  323. ZEND_ARG_INFO(0, sql_text)
  324. ZEND_END_ARG_INFO()
  325. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_get_implicit_resultset, 0, 0, 1)
  326. ZEND_ARG_INFO(0, statement_resource)
  327. ZEND_END_ARG_INFO()
  328. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2)
  329. ZEND_ARG_INFO(0, statement_resource)
  330. ZEND_ARG_INFO(0, number_of_rows)
  331. ZEND_END_ARG_INFO()
  332. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_identifier, 0, 0, 2)
  333. ZEND_ARG_INFO(0, connection_resource)
  334. ZEND_ARG_INFO(0, client_identifier)
  335. ZEND_END_ARG_INFO()
  336. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_edition, 0, 0, 1)
  337. ZEND_ARG_INFO(0, edition_name)
  338. ZEND_END_ARG_INFO()
  339. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_module_name, 0, 0, 2)
  340. ZEND_ARG_INFO(0, connection_resource)
  341. ZEND_ARG_INFO(0, module_name)
  342. ZEND_END_ARG_INFO()
  343. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_action, 0, 0, 2)
  344. ZEND_ARG_INFO(0, connection_resource)
  345. ZEND_ARG_INFO(0, action)
  346. ZEND_END_ARG_INFO()
  347. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2)
  348. ZEND_ARG_INFO(0, connection_resource)
  349. ZEND_ARG_INFO(0, client_information)
  350. ZEND_END_ARG_INFO()
  351. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_db_operation, 0, 0, 2)
  352. ZEND_ARG_INFO(0, connection_resource)
  353. ZEND_ARG_INFO(0, action)
  354. ZEND_END_ARG_INFO()
  355. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_call_timeout, 0, 0, 2)
  356. ZEND_ARG_INFO(0, connection_resource)
  357. ZEND_ARG_INFO(0, call_timeout)
  358. ZEND_END_ARG_INFO()
  359. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4)
  360. ZEND_ARG_INFO(0, connection_resource_or_connection_string)
  361. ZEND_ARG_INFO(0, username)
  362. ZEND_ARG_INFO(0, old_password)
  363. ZEND_ARG_INFO(0, new_password)
  364. ZEND_END_ARG_INFO()
  365. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_cursor, 0, 0, 1)
  366. ZEND_ARG_INFO(0, connection_resource)
  367. ZEND_END_ARG_INFO()
  368. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_result, 0, 0, 2)
  369. ZEND_ARG_INFO(0, statement_resource)
  370. ZEND_ARG_INFO(0, column_number_or_name)
  371. ZEND_END_ARG_INFO()
  372. ZEND_BEGIN_ARG_INFO(arginfo_oci_client_version, 0)
  373. ZEND_END_ARG_INFO()
  374. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_server_version, 0, 0, 1)
  375. ZEND_ARG_INFO(0, connection_resource)
  376. ZEND_END_ARG_INFO()
  377. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_statement_type, 0, 0, 1)
  378. ZEND_ARG_INFO(0, statement_resource)
  379. ZEND_END_ARG_INFO()
  380. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_rows, 0, 0, 1)
  381. ZEND_ARG_INFO(0, statement_resource)
  382. ZEND_END_ARG_INFO()
  383. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_collection, 0, 0, 1)
  384. ZEND_ARG_INFO(0, collection)
  385. ZEND_END_ARG_INFO()
  386. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append, 0, 0, 2)
  387. ZEND_ARG_INFO(0, collection)
  388. ZEND_ARG_INFO(0, value)
  389. ZEND_END_ARG_INFO()
  390. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get, 0, 0, 2)
  391. ZEND_ARG_INFO(0, collection)
  392. ZEND_ARG_INFO(0, index)
  393. ZEND_END_ARG_INFO()
  394. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign, 0, 0, 2)
  395. ZEND_ARG_INFO(0, collection_to)
  396. ZEND_ARG_INFO(0, collection_from)
  397. ZEND_END_ARG_INFO()
  398. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign, 0, 0, 3)
  399. ZEND_ARG_INFO(0, collection)
  400. ZEND_ARG_INFO(0, index)
  401. ZEND_ARG_INFO(0, value)
  402. ZEND_END_ARG_INFO()
  403. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_size, 0, 0, 1)
  404. ZEND_ARG_INFO(0, collection)
  405. ZEND_END_ARG_INFO()
  406. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_max, 0, 0, 1)
  407. ZEND_ARG_INFO(0, collection)
  408. ZEND_END_ARG_INFO()
  409. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim, 0, 0, 2)
  410. ZEND_ARG_INFO(0, collection)
  411. ZEND_ARG_INFO(0, number)
  412. ZEND_END_ARG_INFO()
  413. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_collection, 0, 0, 2)
  414. ZEND_ARG_INFO(0, connection_resource)
  415. ZEND_ARG_INFO(0, type_name)
  416. ZEND_ARG_INFO(0, schema_name)
  417. ZEND_END_ARG_INFO()
  418. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_register_taf_callback, 0, 0, 1)
  419. ZEND_ARG_INFO(0, connection_resource)
  420. ZEND_ARG_INFO(0, function_name)
  421. ZEND_END_ARG_INFO()
  422. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_unregister_taf_callback, 0, 0, 1)
  423. ZEND_ARG_INFO(0, connection_resource)
  424. ZEND_END_ARG_INFO()
  425. /* }}} */
  426. /* {{{ LOB Method arginfo */
  427. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save_method, 0, 0, 1)
  428. ZEND_ARG_INFO(0, data)
  429. ZEND_ARG_INFO(0, offset)
  430. ZEND_END_ARG_INFO()
  431. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import_method, 0, 0, 1)
  432. ZEND_ARG_INFO(0, filename)
  433. ZEND_END_ARG_INFO()
  434. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_load_method, 0)
  435. ZEND_END_ARG_INFO()
  436. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read_method, 0, 0, 1)
  437. ZEND_ARG_INFO(0, length)
  438. ZEND_END_ARG_INFO()
  439. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_eof_method, 0)
  440. ZEND_END_ARG_INFO()
  441. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_tell_method, 0)
  442. ZEND_END_ARG_INFO()
  443. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_rewind_method, 0)
  444. ZEND_END_ARG_INFO()
  445. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek_method, 0, 0, 1)
  446. ZEND_ARG_INFO(0, offset)
  447. ZEND_ARG_INFO(0, whence)
  448. ZEND_END_ARG_INFO()
  449. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_size_method, 0)
  450. ZEND_END_ARG_INFO()
  451. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_method, 0, 0, 1)
  452. ZEND_ARG_INFO(0, string)
  453. ZEND_ARG_INFO(0, length)
  454. ZEND_END_ARG_INFO()
  455. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append_method, 0, 0, 1)
  456. ZEND_ARG_INFO(0, lob_descriptor_from)
  457. ZEND_END_ARG_INFO()
  458. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate_method, 0, 0, 0)
  459. ZEND_ARG_INFO(0, length)
  460. ZEND_END_ARG_INFO()
  461. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase_method, 0, 0, 0)
  462. ZEND_ARG_INFO(0, offset)
  463. ZEND_ARG_INFO(0, length)
  464. ZEND_END_ARG_INFO()
  465. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush_method, 0, 0, 0)
  466. ZEND_ARG_INFO(0, flag)
  467. ZEND_END_ARG_INFO()
  468. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_setbuffering_method, 0, 0, 1)
  469. ZEND_ARG_INFO(0, mode)
  470. ZEND_END_ARG_INFO()
  471. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_getbuffering_method, 0)
  472. ZEND_END_ARG_INFO()
  473. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export_method, 0, 0, 1)
  474. ZEND_ARG_INFO(0, filename)
  475. ZEND_ARG_INFO(0, start)
  476. ZEND_ARG_INFO(0, length)
  477. ZEND_END_ARG_INFO()
  478. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_temporary_method, 0, 0, 1)
  479. ZEND_ARG_INFO(0, data)
  480. ZEND_ARG_INFO(0, type)
  481. ZEND_END_ARG_INFO()
  482. ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_close_method, 0)
  483. ZEND_END_ARG_INFO()
  484. ZEND_BEGIN_ARG_INFO(arginfo_oci_free_descriptor_method, 0)
  485. ZEND_END_ARG_INFO()
  486. /* }}} */
  487. /* {{{ Collection Method arginfo */
  488. ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_free_method, 0)
  489. ZEND_END_ARG_INFO()
  490. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append_method, 0, 0, 1)
  491. ZEND_ARG_INFO(0, value)
  492. ZEND_END_ARG_INFO()
  493. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get_method, 0, 0, 1)
  494. ZEND_ARG_INFO(0, index)
  495. ZEND_END_ARG_INFO()
  496. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign_method, 0, 0, 1)
  497. ZEND_ARG_INFO(0, collection_from)
  498. ZEND_END_ARG_INFO()
  499. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign_method, 0, 0, 2)
  500. ZEND_ARG_INFO(0, index)
  501. ZEND_ARG_INFO(0, value)
  502. ZEND_END_ARG_INFO()
  503. ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_size_method, 0)
  504. ZEND_END_ARG_INFO()
  505. ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_max_method, 0)
  506. ZEND_END_ARG_INFO()
  507. ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1)
  508. ZEND_ARG_INFO(0, number)
  509. ZEND_END_ARG_INFO()
  510. /* }}} */
  511. /* {{{ extension function prototypes
  512. */
  513. PHP_FUNCTION(oci_bind_by_name);
  514. PHP_FUNCTION(oci_bind_array_by_name);
  515. PHP_FUNCTION(oci_define_by_name);
  516. PHP_FUNCTION(oci_field_is_null);
  517. PHP_FUNCTION(oci_field_name);
  518. PHP_FUNCTION(oci_field_size);
  519. PHP_FUNCTION(oci_field_scale);
  520. PHP_FUNCTION(oci_field_precision);
  521. PHP_FUNCTION(oci_field_type);
  522. PHP_FUNCTION(oci_field_type_raw);
  523. PHP_FUNCTION(oci_execute);
  524. PHP_FUNCTION(oci_fetch);
  525. PHP_FUNCTION(oci_cancel);
  526. PHP_FUNCTION(ocifetchinto);
  527. PHP_FUNCTION(oci_fetch_object);
  528. PHP_FUNCTION(oci_fetch_row);
  529. PHP_FUNCTION(oci_fetch_assoc);
  530. PHP_FUNCTION(oci_fetch_array);
  531. PHP_FUNCTION(ocifetchstatement);
  532. PHP_FUNCTION(oci_fetch_all);
  533. PHP_FUNCTION(oci_free_statement);
  534. PHP_FUNCTION(oci_internal_debug);
  535. PHP_FUNCTION(oci_close);
  536. PHP_FUNCTION(oci_connect);
  537. PHP_FUNCTION(oci_new_connect);
  538. PHP_FUNCTION(oci_pconnect);
  539. PHP_FUNCTION(oci_error);
  540. PHP_FUNCTION(oci_free_descriptor);
  541. PHP_FUNCTION(oci_commit);
  542. PHP_FUNCTION(oci_rollback);
  543. PHP_FUNCTION(oci_new_descriptor);
  544. PHP_FUNCTION(oci_num_fields);
  545. PHP_FUNCTION(oci_parse);
  546. PHP_FUNCTION(oci_get_implicit_resultset);
  547. PHP_FUNCTION(oci_new_cursor);
  548. PHP_FUNCTION(oci_result);
  549. PHP_FUNCTION(oci_client_version);
  550. PHP_FUNCTION(oci_server_version);
  551. PHP_FUNCTION(oci_statement_type);
  552. PHP_FUNCTION(oci_num_rows);
  553. PHP_FUNCTION(oci_set_prefetch);
  554. PHP_FUNCTION(oci_set_client_identifier);
  555. PHP_FUNCTION(oci_set_db_operation);
  556. PHP_FUNCTION(oci_set_call_timeout);
  557. PHP_FUNCTION(oci_set_edition);
  558. PHP_FUNCTION(oci_set_module_name);
  559. PHP_FUNCTION(oci_set_action);
  560. PHP_FUNCTION(oci_set_client_info);
  561. PHP_FUNCTION(oci_password_change);
  562. PHP_FUNCTION(oci_lob_save);
  563. PHP_FUNCTION(oci_lob_import);
  564. PHP_FUNCTION(oci_lob_export);
  565. PHP_FUNCTION(oci_lob_load);
  566. PHP_FUNCTION(oci_lob_tell);
  567. PHP_FUNCTION(oci_lob_write);
  568. PHP_FUNCTION(oci_lob_append);
  569. PHP_FUNCTION(oci_lob_copy);
  570. PHP_FUNCTION(oci_lob_truncate);
  571. PHP_FUNCTION(oci_lob_erase);
  572. PHP_FUNCTION(oci_lob_flush);
  573. PHP_FUNCTION(ocisetbufferinglob);
  574. PHP_FUNCTION(ocigetbufferinglob);
  575. PHP_FUNCTION(oci_lob_is_equal);
  576. PHP_FUNCTION(oci_lob_rewind);
  577. PHP_FUNCTION(oci_lob_read);
  578. PHP_FUNCTION(oci_lob_eof);
  579. PHP_FUNCTION(oci_lob_seek);
  580. PHP_FUNCTION(oci_lob_size);
  581. PHP_FUNCTION(oci_lob_write_temporary);
  582. PHP_FUNCTION(oci_lob_close);
  583. PHP_FUNCTION(oci_new_collection);
  584. PHP_FUNCTION(oci_free_collection);
  585. PHP_FUNCTION(oci_collection_append);
  586. PHP_FUNCTION(oci_collection_element_get);
  587. PHP_FUNCTION(oci_collection_element_assign);
  588. PHP_FUNCTION(oci_collection_assign);
  589. PHP_FUNCTION(oci_collection_size);
  590. PHP_FUNCTION(oci_collection_max);
  591. PHP_FUNCTION(oci_collection_trim);
  592. PHP_FUNCTION(oci_register_taf_callback);
  593. PHP_FUNCTION(oci_unregister_taf_callback);
  594. /* }}} */
  595. /* {{{ extension definition structures
  596. */
  597. static const zend_function_entry php_oci_functions[] = {
  598. PHP_FE(oci_define_by_name, arginfo_oci_define_by_name)
  599. PHP_FE(oci_bind_by_name, arginfo_oci_bind_by_name)
  600. PHP_FE(oci_bind_array_by_name, arginfo_oci_bind_array_by_name)
  601. PHP_FE(oci_field_is_null, arginfo_oci_field_is_null)
  602. PHP_FE(oci_field_name, arginfo_oci_field_name)
  603. PHP_FE(oci_field_size, arginfo_oci_field_size)
  604. PHP_FE(oci_field_scale, arginfo_oci_field_scale)
  605. PHP_FE(oci_field_precision, arginfo_oci_field_precision)
  606. PHP_FE(oci_field_type, arginfo_oci_field_type)
  607. PHP_FE(oci_field_type_raw, arginfo_oci_field_type_raw)
  608. PHP_FE(oci_execute, arginfo_oci_execute)
  609. PHP_FE(oci_cancel, arginfo_oci_cancel)
  610. PHP_FE(oci_fetch, arginfo_oci_fetch)
  611. PHP_FE(oci_fetch_object, arginfo_oci_fetch_object)
  612. PHP_FE(oci_fetch_row, arginfo_oci_fetch_row)
  613. PHP_FE(oci_fetch_assoc, arginfo_oci_fetch_assoc)
  614. PHP_FE(oci_fetch_array, arginfo_oci_fetch_array)
  615. PHP_FE(ocifetchinto, arginfo_ocifetchinto)
  616. PHP_FE(oci_fetch_all, arginfo_oci_fetch_all)
  617. PHP_FE(oci_free_statement, arginfo_oci_free_statement)
  618. PHP_FE(oci_internal_debug, arginfo_oci_internal_debug)
  619. PHP_FE(oci_num_fields, arginfo_oci_num_fields)
  620. PHP_FE(oci_parse, arginfo_oci_parse)
  621. PHP_FE(oci_get_implicit_resultset, arginfo_oci_get_implicit_resultset)
  622. PHP_FE(oci_new_cursor, arginfo_oci_new_cursor)
  623. PHP_FE(oci_result, arginfo_oci_result)
  624. PHP_FE(oci_client_version, arginfo_oci_client_version)
  625. PHP_FE(oci_server_version, arginfo_oci_server_version)
  626. PHP_FE(oci_statement_type, arginfo_oci_statement_type)
  627. PHP_FE(oci_num_rows, arginfo_oci_num_rows)
  628. PHP_FE(oci_close, arginfo_oci_close)
  629. PHP_FE(oci_connect, arginfo_oci_connect)
  630. PHP_FE(oci_new_connect, arginfo_oci_new_connect)
  631. PHP_FE(oci_pconnect, arginfo_oci_pconnect)
  632. PHP_FE(oci_error, arginfo_oci_error)
  633. PHP_FE(oci_free_descriptor, arginfo_oci_free_descriptor)
  634. PHP_FE(oci_lob_save, arginfo_oci_lob_save)
  635. PHP_FE(oci_lob_import, arginfo_oci_lob_import)
  636. PHP_FE(oci_lob_size, arginfo_oci_lob_size)
  637. PHP_FE(oci_lob_load, arginfo_oci_lob_load)
  638. PHP_FE(oci_lob_read, arginfo_oci_lob_read)
  639. PHP_FE(oci_lob_eof, arginfo_oci_lob_eof)
  640. PHP_FE(oci_lob_tell, arginfo_oci_lob_tell)
  641. PHP_FE(oci_lob_truncate, arginfo_oci_lob_truncate)
  642. PHP_FE(oci_lob_erase, arginfo_oci_lob_erase)
  643. PHP_FE(oci_lob_flush, arginfo_oci_lob_flush)
  644. PHP_FE(ocisetbufferinglob, arginfo_ocisetbufferinglob)
  645. PHP_FE(ocigetbufferinglob, arginfo_ocigetbufferinglob)
  646. PHP_FE(oci_lob_is_equal, arginfo_oci_lob_is_equal)
  647. PHP_FE(oci_lob_rewind, arginfo_oci_lob_rewind)
  648. PHP_FE(oci_lob_write, arginfo_oci_lob_write)
  649. PHP_FE(oci_lob_append, arginfo_oci_lob_append)
  650. PHP_FE(oci_lob_copy, arginfo_oci_lob_copy)
  651. PHP_FE(oci_lob_export, arginfo_oci_lob_export)
  652. PHP_FE(oci_lob_seek, arginfo_oci_lob_seek)
  653. PHP_FE(oci_commit, arginfo_oci_commit)
  654. PHP_FE(oci_rollback, arginfo_oci_rollback)
  655. PHP_FE(oci_new_descriptor, arginfo_oci_new_descriptor)
  656. PHP_FE(oci_set_prefetch, arginfo_oci_set_prefetch)
  657. PHP_FE(oci_set_client_identifier, arginfo_oci_set_client_identifier)
  658. PHP_FE(oci_set_db_operation, arginfo_oci_set_db_operation)
  659. PHP_FE(oci_set_call_timeout, arginfo_oci_set_call_timeout)
  660. PHP_FE(oci_set_edition, arginfo_oci_set_edition)
  661. PHP_FE(oci_set_module_name, arginfo_oci_set_module_name)
  662. PHP_FE(oci_set_action, arginfo_oci_set_action)
  663. PHP_FE(oci_set_client_info, arginfo_oci_set_client_info)
  664. PHP_FE(oci_password_change, arginfo_oci_password_change)
  665. PHP_FE(oci_free_collection, arginfo_oci_free_collection)
  666. PHP_FE(oci_collection_append, arginfo_oci_collection_append)
  667. PHP_FE(oci_collection_element_get, arginfo_oci_collection_element_get)
  668. PHP_FE(oci_collection_element_assign, arginfo_oci_collection_element_assign)
  669. PHP_FE(oci_collection_assign, arginfo_oci_collection_assign)
  670. PHP_FE(oci_collection_size, arginfo_oci_collection_size)
  671. PHP_FE(oci_collection_max, arginfo_oci_collection_max)
  672. PHP_FE(oci_collection_trim, arginfo_oci_collection_trim)
  673. PHP_FE(oci_new_collection, arginfo_oci_new_collection)
  674. PHP_FE(oci_register_taf_callback, arginfo_oci_register_taf_callback)
  675. PHP_FE(oci_unregister_taf_callback, arginfo_oci_unregister_taf_callback)
  676. PHP_FALIAS(oci_free_cursor, oci_free_statement, arginfo_oci_free_statement)
  677. PHP_FALIAS(ocifreecursor, oci_free_statement, arginfo_oci_free_statement)
  678. PHP_FALIAS(ocibindbyname, oci_bind_by_name, arginfo_oci_bind_by_name)
  679. PHP_FALIAS(ocidefinebyname, oci_define_by_name, arginfo_oci_define_by_name)
  680. PHP_FALIAS(ocicolumnisnull, oci_field_is_null, arginfo_oci_field_is_null)
  681. PHP_FALIAS(ocicolumnname, oci_field_name, arginfo_oci_field_name)
  682. PHP_FALIAS(ocicolumnsize, oci_field_size, arginfo_oci_field_size)
  683. PHP_FALIAS(ocicolumnscale, oci_field_scale, arginfo_oci_field_scale)
  684. PHP_FALIAS(ocicolumnprecision, oci_field_precision, arginfo_oci_field_precision)
  685. PHP_FALIAS(ocicolumntype, oci_field_type, arginfo_oci_field_type)
  686. PHP_FALIAS(ocicolumntyperaw, oci_field_type_raw, arginfo_oci_field_type_raw)
  687. PHP_FALIAS(ociexecute, oci_execute, arginfo_oci_execute)
  688. PHP_FALIAS(ocicancel, oci_cancel, arginfo_oci_cancel)
  689. PHP_FALIAS(ocifetch, oci_fetch, arginfo_oci_fetch)
  690. PHP_FALIAS(ocifetchstatement, oci_fetch_all, arginfo_oci_fetch_all)
  691. PHP_FALIAS(ocifreestatement, oci_free_statement, arginfo_oci_free_statement)
  692. PHP_FALIAS(ociinternaldebug, oci_internal_debug, arginfo_oci_internal_debug)
  693. PHP_FALIAS(ocinumcols, oci_num_fields, arginfo_oci_num_fields)
  694. PHP_FALIAS(ociparse, oci_parse, arginfo_oci_parse)
  695. PHP_FALIAS(ocinewcursor, oci_new_cursor, arginfo_oci_new_cursor)
  696. PHP_FALIAS(ociresult, oci_result, arginfo_oci_result)
  697. PHP_FALIAS(ociserverversion, oci_server_version, arginfo_oci_server_version)
  698. PHP_FALIAS(ocistatementtype, oci_statement_type, arginfo_oci_statement_type)
  699. PHP_FALIAS(ocirowcount, oci_num_rows, arginfo_oci_num_rows)
  700. PHP_FALIAS(ocilogoff, oci_close, arginfo_oci_close)
  701. PHP_FALIAS(ocilogon, oci_connect, arginfo_oci_connect)
  702. PHP_FALIAS(ocinlogon, oci_new_connect, arginfo_oci_new_connect)
  703. PHP_FALIAS(ociplogon, oci_pconnect, arginfo_oci_pconnect)
  704. PHP_FALIAS(ocierror, oci_error, arginfo_oci_error)
  705. PHP_FALIAS(ocifreedesc, oci_free_descriptor, arginfo_oci_free_descriptor)
  706. PHP_FALIAS(ocisavelob, oci_lob_save, arginfo_oci_lob_save)
  707. PHP_FALIAS(ocisavelobfile, oci_lob_import, arginfo_oci_lob_import)
  708. PHP_FALIAS(ociwritelobtofile, oci_lob_export, arginfo_oci_lob_export)
  709. PHP_FALIAS(ociloadlob, oci_lob_load, arginfo_oci_lob_load)
  710. PHP_FALIAS(ocicommit, oci_commit, arginfo_oci_commit)
  711. PHP_FALIAS(ocirollback, oci_rollback, arginfo_oci_rollback)
  712. PHP_FALIAS(ocinewdescriptor, oci_new_descriptor, arginfo_oci_new_descriptor)
  713. PHP_FALIAS(ocisetprefetch, oci_set_prefetch, arginfo_oci_set_prefetch)
  714. PHP_FALIAS(ocipasswordchange, oci_password_change, arginfo_oci_password_change)
  715. PHP_FALIAS(ocifreecollection, oci_free_collection, arginfo_oci_free_collection)
  716. PHP_FALIAS(ocinewcollection, oci_new_collection, arginfo_oci_new_collection)
  717. PHP_FALIAS(ocicollappend, oci_collection_append, arginfo_oci_collection_append)
  718. PHP_FALIAS(ocicollgetelem, oci_collection_element_get, arginfo_oci_collection_element_get)
  719. PHP_FALIAS(ocicollassignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign)
  720. PHP_FALIAS(ocicollsize, oci_collection_size, arginfo_oci_collection_size)
  721. PHP_FALIAS(ocicollmax, oci_collection_max, arginfo_oci_collection_max)
  722. PHP_FALIAS(ocicolltrim, oci_collection_trim, arginfo_oci_collection_trim)
  723. PHP_FE_END
  724. };
  725. static const zend_function_entry php_oci_lob_class_functions[] = {
  726. PHP_FALIAS(load, oci_lob_load, arginfo_oci_lob_load_method)
  727. PHP_FALIAS(tell, oci_lob_tell, arginfo_oci_lob_tell_method)
  728. PHP_FALIAS(truncate, oci_lob_truncate, arginfo_oci_lob_truncate_method)
  729. PHP_FALIAS(erase, oci_lob_erase, arginfo_oci_lob_erase_method)
  730. PHP_FALIAS(flush, oci_lob_flush, arginfo_oci_lob_flush_method)
  731. PHP_FALIAS(setbuffering,ocisetbufferinglob, arginfo_oci_lob_setbuffering_method)
  732. PHP_FALIAS(getbuffering,ocigetbufferinglob, arginfo_oci_lob_getbuffering_method)
  733. PHP_FALIAS(rewind, oci_lob_rewind, arginfo_oci_lob_rewind_method)
  734. PHP_FALIAS(read, oci_lob_read, arginfo_oci_lob_read_method)
  735. PHP_FALIAS(eof, oci_lob_eof, arginfo_oci_lob_eof_method)
  736. PHP_FALIAS(seek, oci_lob_seek, arginfo_oci_lob_seek_method)
  737. PHP_FALIAS(write, oci_lob_write, arginfo_oci_lob_write_method)
  738. PHP_FALIAS(append, oci_lob_append, arginfo_oci_lob_append_method)
  739. PHP_FALIAS(size, oci_lob_size, arginfo_oci_lob_size_method)
  740. PHP_FALIAS(writetofile, oci_lob_export, arginfo_oci_lob_export_method)
  741. PHP_FALIAS(export, oci_lob_export, arginfo_oci_lob_export_method)
  742. PHP_FALIAS(import, oci_lob_import, arginfo_oci_lob_import_method)
  743. PHP_FALIAS(writetemporary, oci_lob_write_temporary, arginfo_oci_lob_write_temporary_method)
  744. PHP_FALIAS(close, oci_lob_close, arginfo_oci_lob_close_method)
  745. PHP_FALIAS(save, oci_lob_save, arginfo_oci_lob_save_method)
  746. PHP_FALIAS(savefile, oci_lob_import, arginfo_oci_lob_import_method)
  747. PHP_FALIAS(free, oci_free_descriptor, arginfo_oci_free_descriptor_method)
  748. PHP_FE_END
  749. };
  750. static const zend_function_entry php_oci_coll_class_functions[] = {
  751. PHP_FALIAS(append, oci_collection_append, arginfo_oci_collection_append_method)
  752. PHP_FALIAS(getelem, oci_collection_element_get, arginfo_oci_collection_element_get_method)
  753. PHP_FALIAS(assignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign_method)
  754. PHP_FALIAS(assign, oci_collection_assign, arginfo_oci_collection_assign_method)
  755. PHP_FALIAS(size, oci_collection_size, arginfo_oci_collection_size_method)
  756. PHP_FALIAS(max, oci_collection_max, arginfo_oci_collection_max_method)
  757. PHP_FALIAS(trim, oci_collection_trim, arginfo_oci_collection_trim_method)
  758. PHP_FALIAS(free, oci_free_collection, arginfo_oci_collection_free_method)
  759. PHP_FE_END
  760. };
  761. zend_module_entry oci8_module_entry = {
  762. STANDARD_MODULE_HEADER,
  763. "oci8", /* extension name */
  764. php_oci_functions, /* extension function list */
  765. PHP_MINIT(oci), /* extension-wide startup function */
  766. PHP_MSHUTDOWN(oci), /* extension-wide shutdown function */
  767. PHP_RINIT(oci), /* per-request startup function */
  768. PHP_RSHUTDOWN(oci), /* per-request shutdown function */
  769. PHP_MINFO(oci), /* information function */
  770. PHP_OCI8_VERSION,
  771. PHP_MODULE_GLOBALS(oci), /* globals descriptor */
  772. PHP_GINIT(oci), /* globals ctor */
  773. PHP_GSHUTDOWN(oci), /* globals dtor */
  774. NULL, /* post deactivate */
  775. STANDARD_MODULE_PROPERTIES_EX
  776. };
  777. /* }}} */
  778. /* {{{ PHP_INI */
  779. PHP_INI_BEGIN()
  780. STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_oci_globals, oci_globals)
  781. STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent_timeout, zend_oci_globals, oci_globals)
  782. STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, OnUpdateLong, ping_interval, zend_oci_globals, oci_globals)
  783. STD_PHP_INI_BOOLEAN("oci8.privileged_connect", "0", PHP_INI_SYSTEM, OnUpdateBool, privileged_connect, zend_oci_globals, oci_globals)
  784. STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, OnUpdateLong, statement_cache_size, zend_oci_globals, oci_globals)
  785. STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, OnUpdateLong, default_prefetch, zend_oci_globals, oci_globals)
  786. STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateBool, old_oci_close_semantics,zend_oci_globals, oci_globals)
  787. #if (OCI_MAJOR_VERSION >= 11)
  788. STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals)
  789. #endif
  790. #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
  791. STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals)
  792. #endif
  793. PHP_INI_END()
  794. /* }}} */
  795. /* {{{ startup, shutdown and info functions
  796. */
  797. /* {{{ php_oci_init_global_handles()
  798. *
  799. * Initialize global handles only when they are needed
  800. */
  801. static void php_oci_init_global_handles(void)
  802. {
  803. sword errstatus;
  804. sb4 ora_error_code = 0;
  805. text tmp_buf[PHP_OCI_ERRBUF_LEN]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
  806. errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
  807. if (errstatus == OCI_ERROR) {
  808. #ifdef HAVE_OCI_INSTANT_CLIENT
  809. 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");
  810. #else
  811. 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");
  812. #endif
  813. if (OCI_G(env)
  814. && OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
  815. && *tmp_buf) {
  816. php_error_docref(NULL, E_WARNING, "%s", tmp_buf);
  817. }
  818. OCI_G(env) = NULL;
  819. OCI_G(err) = NULL;
  820. return;
  821. }
  822. errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
  823. if (errstatus == OCI_SUCCESS) {
  824. #if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
  825. /* This fixes PECL bug 15988 (sqlnet.ora not being read). The
  826. * root cause was fixed in Oracle 10.2.0.4 but there is no
  827. * compile time method to check for that precise patch level,
  828. * nor can it be guaranteed that runtime will use the same
  829. * patch level the code was compiled with. So, we do this
  830. * code for all non 11g versions.
  831. */
  832. OCICPool *cpoolh;
  833. ub4 cpoolmode = 0x80000000; /* Pass invalid mode to OCIConnectionPoolCreate */
  834. PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
  835. PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
  836. PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
  837. PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
  838. #endif
  839. } else {
  840. OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
  841. if (ora_error_code) {
  842. int tmp_buf_len = (int) strlen((char *)tmp_buf);
  843. if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
  844. tmp_buf[tmp_buf_len - 1] = '\0';
  845. }
  846. if (errstatus == OCI_SUCCESS_WITH_INFO) {
  847. php_error_docref(NULL, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
  848. } else {
  849. php_error_docref(NULL, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
  850. OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
  851. OCI_G(env) = NULL;
  852. OCI_G(err) = NULL;
  853. }
  854. }
  855. }
  856. }
  857. /* }}} */
  858. /* {{{ php_oci_cleanup_global_handles()
  859. *
  860. * Free global handles (if they were initialized before)
  861. */
  862. static void php_oci_cleanup_global_handles(void)
  863. {
  864. if (OCI_G(err)) {
  865. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
  866. OCI_G(err) = NULL;
  867. }
  868. if (OCI_G(env)) {
  869. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));
  870. OCI_G(env) = NULL;
  871. }
  872. }
  873. /* }}} */
  874. /* {{{ PHP_GINIT_FUNCTION
  875. *
  876. * Zerofill globals during module init
  877. */
  878. static PHP_GINIT_FUNCTION(oci)
  879. {
  880. memset(oci_globals, 0, sizeof(zend_oci_globals));
  881. }
  882. /* }}} */
  883. /* {{{ PHP_GSHUTDOWN_FUNCTION
  884. *
  885. * Called for thread shutdown in ZTS, after module shutdown for non-ZTS
  886. */
  887. static PHP_GSHUTDOWN_FUNCTION(oci)
  888. {
  889. php_oci_cleanup_global_handles();
  890. }
  891. /* }}} */
  892. PHP_MINIT_FUNCTION(oci)
  893. {
  894. zend_class_entry oci_lob_class_entry;
  895. zend_class_entry oci_coll_class_entry;
  896. REGISTER_INI_ENTRIES();
  897. le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
  898. le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
  899. le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
  900. le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
  901. le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
  902. le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
  903. INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
  904. INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
  905. oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry);
  906. oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry);
  907. /* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
  908. REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
  909. REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
  910. REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
  911. REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
  912. REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
  913. REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
  914. REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
  915. REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
  916. /* for $LOB->seek() */
  917. REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
  918. REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
  919. REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
  920. /* for $LOB->flush() */
  921. REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
  922. /* for OCIBindByName (real "oci" names + short "php" names */
  923. REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
  924. REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
  925. REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
  926. REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
  927. REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
  928. REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
  929. REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
  930. REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
  931. REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
  932. REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
  933. REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
  934. REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
  935. REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
  936. REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
  937. REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
  938. REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
  939. REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
  940. REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
  941. REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
  942. REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
  943. #if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
  944. REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
  945. REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
  946. #endif
  947. #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
  948. REGISTER_LONG_CONSTANT("SQLT_BOL",SQLT_BOL, CONST_CS | CONST_PERSISTENT);
  949. #endif
  950. REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
  951. REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
  952. REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
  953. REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
  954. REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
  955. REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
  956. REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
  957. REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
  958. REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
  959. REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
  960. REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
  961. REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
  962. #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
  963. REGISTER_LONG_CONSTANT("OCI_B_BOL",SQLT_BOL, CONST_CS | CONST_PERSISTENT);
  964. #endif
  965. /* for OCIFetchStatement */
  966. REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
  967. REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
  968. /* for OCIFetchInto & OCIResult */
  969. REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
  970. REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
  971. REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
  972. REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
  973. REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
  974. /* for OCINewDescriptor (real "oci" names + short "php" names */
  975. REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
  976. REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
  977. REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
  978. REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
  979. REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
  980. REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
  981. /* for OCIWriteTemporaryLob */
  982. REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
  983. REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
  984. /* for Transparent Application Failover */
  985. REGISTER_LONG_CONSTANT("OCI_FO_END", OCI_FO_END, CONST_CS | CONST_PERSISTENT);
  986. REGISTER_LONG_CONSTANT("OCI_FO_ABORT", OCI_FO_ABORT, CONST_CS | CONST_PERSISTENT);
  987. REGISTER_LONG_CONSTANT("OCI_FO_REAUTH", OCI_FO_REAUTH, CONST_CS | CONST_PERSISTENT);
  988. REGISTER_LONG_CONSTANT("OCI_FO_BEGIN", OCI_FO_BEGIN, CONST_CS | CONST_PERSISTENT);
  989. REGISTER_LONG_CONSTANT("OCI_FO_ERROR", OCI_FO_ERROR, CONST_CS | CONST_PERSISTENT);
  990. REGISTER_LONG_CONSTANT("OCI_FO_NONE", OCI_FO_NONE, CONST_CS | CONST_PERSISTENT);
  991. REGISTER_LONG_CONSTANT("OCI_FO_SESSION", OCI_FO_SESSION, CONST_CS | CONST_PERSISTENT);
  992. REGISTER_LONG_CONSTANT("OCI_FO_SELECT", OCI_FO_SELECT, CONST_CS | CONST_PERSISTENT);
  993. REGISTER_LONG_CONSTANT("OCI_FO_TXNAL", OCI_FO_TXNAL, CONST_CS | CONST_PERSISTENT);
  994. REGISTER_LONG_CONSTANT("OCI_FO_RETRY", OCI_FO_RETRY, CONST_CS | CONST_PERSISTENT);
  995. return SUCCESS;
  996. }
  997. PHP_RINIT_FUNCTION(oci)
  998. {
  999. OCI_G(num_links) = OCI_G(num_persistent);
  1000. OCI_G(errcode) = 0;
  1001. OCI_G(edition) = NULL;
  1002. return SUCCESS;
  1003. }
  1004. PHP_MSHUTDOWN_FUNCTION(oci)
  1005. {
  1006. OCI_G(shutdown) = 1;
  1007. UNREGISTER_INI_ENTRIES();
  1008. return SUCCESS;
  1009. }
  1010. PHP_RSHUTDOWN_FUNCTION(oci)
  1011. {
  1012. /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
  1013. * unable to process a pconnection because of a refcount, the processing would happen from
  1014. * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
  1015. */
  1016. zend_hash_apply(&EG(persistent_list), php_oci_persistent_helper);
  1017. if (OCI_G(edition)) {
  1018. efree(OCI_G(edition));
  1019. }
  1020. return SUCCESS;
  1021. }
  1022. PHP_MINFO_FUNCTION(oci)
  1023. {
  1024. char buf[32];
  1025. #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
  1026. char ver[256];
  1027. #endif
  1028. php_info_print_table_start();
  1029. php_info_print_table_row(2, "OCI8 Support", "enabled");
  1030. #if defined(HAVE_OCI8_DTRACE)
  1031. php_info_print_table_row(2, "OCI8 DTrace Support", "enabled");
  1032. #else
  1033. php_info_print_table_row(2, "OCI8 DTrace Support", "disabled");
  1034. #endif
  1035. php_info_print_table_row(2, "OCI8 Version", PHP_OCI8_VERSION);
  1036. #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
  1037. php_oci_client_get_version(ver, sizeof(ver));
  1038. php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver);
  1039. #else
  1040. php_info_print_table_row(2, "Oracle Run-time Client Library Version", "Unknown");
  1041. #endif
  1042. #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
  1043. snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
  1044. #elif defined(PHP_OCI8_ORACLE_VERSION)
  1045. snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
  1046. #else
  1047. snprintf(buf, sizeof(buf), "Unknown");
  1048. #endif
  1049. #if defined(HAVE_OCI_INSTANT_CLIENT)
  1050. php_info_print_table_row(2, "Oracle Compile-time Instant Client Version", buf);
  1051. #else
  1052. php_info_print_table_row(2, "Oracle Compile-time Version", buf);
  1053. #endif
  1054. #if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
  1055. #if defined(PHP_OCI8_DEF_DIR)
  1056. php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
  1057. #endif
  1058. #if defined(PHP_OCI8_DEF_SHARED_LIBADD)
  1059. php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
  1060. #endif
  1061. #endif
  1062. php_info_print_table_end();
  1063. DISPLAY_INI_ENTRIES();
  1064. php_info_print_table_start();
  1065. php_info_print_table_header(2, "Statistics", "");
  1066. snprintf(buf, sizeof(buf), ZEND_LONG_FMT, OCI_G(num_persistent));
  1067. php_info_print_table_row(2, "Active Persistent Connections", buf);
  1068. snprintf(buf, sizeof(buf), ZEND_LONG_FMT, OCI_G(num_links));
  1069. php_info_print_table_row(2, "Active Connections", buf);
  1070. php_info_print_table_end();
  1071. }
  1072. /* }}} */
  1073. /* {{{ list destructors */
  1074. /* {{{ php_oci_connection_list_dtor()
  1075. *
  1076. * Non-persistent connection destructor
  1077. */
  1078. static void php_oci_connection_list_dtor(zend_resource *entry)
  1079. {
  1080. php_oci_connection *connection = (php_oci_connection *)entry->ptr;
  1081. if (connection) {
  1082. php_oci_connection_close(connection);
  1083. OCI_G(num_links)--;
  1084. }
  1085. }
  1086. /* }}} */
  1087. /* {{{ php_oci_pconnection_list_dtor()
  1088. *
  1089. * Persistent connection destructor
  1090. */
  1091. static void php_oci_pconnection_list_dtor(zend_resource *entry)
  1092. {
  1093. php_oci_connection *connection = (php_oci_connection *)entry->ptr;
  1094. if (connection) {
  1095. php_oci_connection_close(connection);
  1096. OCI_G(num_persistent)--;
  1097. OCI_G(num_links)--;
  1098. }
  1099. }
  1100. /* }}} */
  1101. /* {{{ php_oci_pconnection_list_np_dtor()
  1102. *
  1103. * Non-Persistent destructor for persistent connection - This gets invoked when
  1104. * the refcount of this goes to zero in the regular list
  1105. */
  1106. static void php_oci_pconnection_list_np_dtor(zend_resource *entry)
  1107. {
  1108. php_oci_connection *connection = (php_oci_connection *)entry->ptr;
  1109. zval *zvp;
  1110. zend_resource *le;
  1111. /*
  1112. * We cannot get connection as NULL or as a stub in this function. This is the function that
  1113. * turns a pconnection to a stub
  1114. *
  1115. * If oci_password_change() changed the password of a persistent connection, close the
  1116. * connection and remove it from the persistent connection cache. This means subsequent scripts
  1117. * will be prevented from being able to present the old (now invalid) password to a usable
  1118. * connection to the database; they must use the new password.
  1119. *
  1120. * Check for conditions that warrant removal of the hash entry
  1121. */
  1122. if (!connection->is_open ||
  1123. connection->passwd_changed ||
  1124. (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
  1125. OCI_G(in_call)) {
  1126. /* Remove the hash entry if present */
  1127. if (connection->hash_key) {
  1128. zvp = zend_hash_find(&EG(persistent_list), connection->hash_key);
  1129. le = zvp ? Z_RES_P(zvp) : NULL;
  1130. if (le != NULL && le->type == le_pconnection && le->ptr == connection) {
  1131. zend_hash_del(&EG(persistent_list), connection->hash_key);
  1132. }
  1133. else {
  1134. php_oci_connection_close(connection);
  1135. OCI_G(num_persistent)--;
  1136. }
  1137. }
  1138. #ifdef HAVE_OCI8_DTRACE
  1139. if (DTRACE_OCI8_CONNECT_P_DTOR_CLOSE_ENABLED()) {
  1140. DTRACE_OCI8_CONNECT_P_DTOR_CLOSE(connection);
  1141. }
  1142. #endif /* HAVE_OCI8_DTRACE */
  1143. } else {
  1144. /*
  1145. * Release the connection to underlying pool. We do this unconditionally so that
  1146. * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
  1147. * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
  1148. * takes the refcount to zero.
  1149. *
  1150. * If oci_old_close_semantics is set, we artificially bump up the refcount and decremented
  1151. * only at request shutdown.
  1152. */
  1153. php_oci_connection_release(connection);
  1154. #ifdef HAVE_OCI8_DTRACE
  1155. if (DTRACE_OCI8_CONNECT_P_DTOR_RELEASE_ENABLED()) {
  1156. DTRACE_OCI8_CONNECT_P_DTOR_RELEASE(connection);
  1157. }
  1158. #endif /* HAVE_OCI8_DTRACE */
  1159. }
  1160. }
  1161. /* }}} */
  1162. /* {{{ php_oci_statement_list_dtor()
  1163. *
  1164. * Statement destructor
  1165. */
  1166. static void php_oci_statement_list_dtor(zend_resource *entry)
  1167. {
  1168. php_oci_statement *statement = (php_oci_statement *)entry->ptr;
  1169. php_oci_statement_free(statement);
  1170. }
  1171. /* }}} */
  1172. /* {{{ php_oci_descriptor_list_dtor()
  1173. *
  1174. * Descriptor destructor
  1175. */
  1176. static void php_oci_descriptor_list_dtor(zend_resource *entry)
  1177. {
  1178. php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
  1179. php_oci_lob_free(descriptor);
  1180. }
  1181. /* }}} */
  1182. /* {{{ php_oci_collection_list_dtor()
  1183. *
  1184. * Collection destructor
  1185. */
  1186. static void php_oci_collection_list_dtor(zend_resource *entry)
  1187. {
  1188. php_oci_collection *collection = (php_oci_collection *)entry->ptr;
  1189. php_oci_collection_close(collection);
  1190. }
  1191. /* }}} */
  1192. /* }}} */
  1193. /* {{{ Hash Destructors */
  1194. /* {{{ php_oci_define_hash_dtor()
  1195. *
  1196. * Define hash destructor
  1197. */
  1198. void php_oci_define_hash_dtor(zval *data)
  1199. {
  1200. php_oci_define *define = (php_oci_define *) Z_PTR_P(data);
  1201. if (define->name) {
  1202. efree(define->name);
  1203. define->name = NULL;
  1204. }
  1205. zval_ptr_dtor(&define->val);
  1206. efree(define);
  1207. }
  1208. /* }}} */
  1209. /* {{{ php_oci_bind_hash_dtor()
  1210. *
  1211. * Bind hash destructor
  1212. */
  1213. void php_oci_bind_hash_dtor(zval *data)
  1214. {
  1215. php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data);
  1216. if (!Z_ISUNDEF(bind->val)) {
  1217. zval_ptr_dtor(&bind->val);
  1218. ZVAL_UNDEF(&bind->val);
  1219. }
  1220. if (bind->array.elements) {
  1221. efree(bind->array.elements);
  1222. bind->array.elements = NULL;
  1223. }
  1224. if (bind->array.element_lengths) {
  1225. efree(bind->array.element_lengths);
  1226. bind->array.element_lengths = NULL;
  1227. }
  1228. if (bind->array.indicators) {
  1229. efree(bind->array.indicators);
  1230. bind->array.indicators = NULL;
  1231. }
  1232. efree(bind);
  1233. }
  1234. /* }}} */
  1235. /* {{{ php_oci_column_hash_dtor()
  1236. *
  1237. * Column hash destructor
  1238. */
  1239. void php_oci_column_hash_dtor(zval *data)
  1240. {
  1241. php_oci_out_column *column = (php_oci_out_column *) Z_PTR_P(data);
  1242. if (column->stmtid) {
  1243. zend_list_close(column->stmtid);
  1244. }
  1245. if (column->descid) {
  1246. if (GC_REFCOUNT(column->descid) == 1)
  1247. zend_list_close(column->descid);
  1248. else {
  1249. GC_DELREF(column->descid);
  1250. }
  1251. }
  1252. if (column->data) {
  1253. efree(column->data);
  1254. }
  1255. if (column->name) {
  1256. efree(column->name);
  1257. }
  1258. efree(column);
  1259. }
  1260. /* }}} */
  1261. /* {{{ php_oci_descriptor_flush_hash_dtor()
  1262. *
  1263. * Flush descriptors on commit
  1264. */
  1265. void php_oci_descriptor_flush_hash_dtor(zval *data)
  1266. {
  1267. php_oci_descriptor *descriptor = (php_oci_descriptor *) Z_PTR_P(data);
  1268. if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
  1269. php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE);
  1270. descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
  1271. }
  1272. data = NULL;
  1273. }
  1274. /* }}} */
  1275. /* }}} */
  1276. /* {{{ php_oci_connection_descriptors_free()
  1277. *
  1278. * Free descriptors for a connection
  1279. */
  1280. void php_oci_connection_descriptors_free(php_oci_connection *connection)
  1281. {
  1282. zend_hash_destroy(connection->descriptors);
  1283. efree(connection->descriptors);
  1284. connection->descriptors = NULL;
  1285. connection->descriptor_count = 0;
  1286. }
  1287. /* }}} */
  1288. /* {{{ php_oci_error()
  1289. *
  1290. * Fetch & print out error message if we get an error
  1291. * Returns an Oracle error number
  1292. */
  1293. sb4 php_oci_error(OCIError *err_p, sword errstatus)
  1294. {
  1295. text errbuf[PHP_OCI_ERRBUF_LEN];
  1296. sb4 errcode = 0; /* Oracle error number */
  1297. switch (errstatus) {
  1298. case OCI_SUCCESS:
  1299. break;
  1300. case OCI_SUCCESS_WITH_INFO:
  1301. errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
  1302. if (errcode) {
  1303. php_error_docref(NULL, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
  1304. } else {
  1305. php_error_docref(NULL, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
  1306. }
  1307. break;
  1308. case OCI_NEED_DATA:
  1309. php_error_docref(NULL, E_WARNING, "OCI_NEED_DATA");
  1310. break;
  1311. case OCI_NO_DATA:
  1312. errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
  1313. if (errcode) {
  1314. php_error_docref(NULL, E_WARNING, "%s", errbuf);
  1315. } else {
  1316. php_error_docref(NULL, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
  1317. }
  1318. break;
  1319. case OCI_ERROR:
  1320. errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
  1321. if (errcode) {
  1322. php_error_docref(NULL, E_WARNING, "%s", errbuf);
  1323. } else {
  1324. php_error_docref(NULL, E_WARNING, "failed to fetch error message");
  1325. }
  1326. break;
  1327. case OCI_INVALID_HANDLE:
  1328. php_error_docref(NULL, E_WARNING, "OCI_INVALID_HANDLE");
  1329. break;
  1330. case OCI_STILL_EXECUTING:
  1331. php_error_docref(NULL, E_WARNING, "OCI_STILL_EXECUTING");
  1332. break;
  1333. case OCI_CONTINUE:
  1334. php_error_docref(NULL, E_WARNING, "OCI_CONTINUE");
  1335. break;
  1336. default:
  1337. php_error_docref(NULL, E_WARNING, "Unknown OCI error code: %d", errstatus);
  1338. break;
  1339. }
  1340. #ifdef HAVE_OCI8_DTRACE
  1341. if (DTRACE_OCI8_ERROR_ENABLED()) {
  1342. DTRACE_OCI8_ERROR((int)errstatus, (long)errcode);
  1343. }
  1344. #endif /* HAVE_OCI8_DTRACE */
  1345. return errcode;
  1346. }
  1347. /* }}} */
  1348. /* {{{ php_oci_fetch_errmsg()
  1349. *
  1350. * Fetch error message into the buffer from the error handle provided
  1351. */
  1352. sb4 php_oci_fetch_errmsg(OCIError *error_handle, text *error_buf, size_t error_buf_size)
  1353. {
  1354. sb4 error_code = 0;
  1355. PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, error_buf, (ub4)error_buf_size, (ub4)OCI_HTYPE_ERROR));
  1356. if (error_code) {
  1357. int err_buf_len = (int) strlen((char *)error_buf);
  1358. if (err_buf_len && error_buf[err_buf_len - 1] == '\n') {
  1359. error_buf[err_buf_len - 1] = '\0';
  1360. }
  1361. }
  1362. return error_code;
  1363. }
  1364. /* }}} */
  1365. /* {{{ php_oci_fetch_sqltext_offset()
  1366. *
  1367. * Compute offset in the SQL statement
  1368. */
  1369. int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset)
  1370. {
  1371. sword errstatus;
  1372. *sqltext = NULL;
  1373. *error_offset = 0;
  1374. PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
  1375. if (errstatus != OCI_SUCCESS) {
  1376. statement->errcode = php_oci_error(statement->err, errstatus);
  1377. PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
  1378. return 1;
  1379. }
  1380. PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
  1381. if (errstatus != OCI_SUCCESS) {
  1382. statement->errcode = php_oci_error(statement->err, errstatus);
  1383. PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
  1384. return 1;
  1385. }
  1386. return 0;
  1387. }
  1388. /* }}} */
  1389. /* {{{ php_oci_do_connect()
  1390. *
  1391. * Connect wrapper
  1392. */
  1393. void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
  1394. {
  1395. php_oci_connection *connection;
  1396. char *username, *password;
  1397. char *dbname = NULL, *charset = NULL;
  1398. size_t username_len = 0, password_len = 0;
  1399. size_t dbname_len = 0, charset_len = 0;
  1400. zend_long session_mode = OCI_DEFAULT;
  1401. /* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
  1402. ZEND_PARSE_PARAMETERS_START(2, 5)
  1403. Z_PARAM_STRING(username, username_len)
  1404. Z_PARAM_STRING(password, password_len)
  1405. Z_PARAM_OPTIONAL
  1406. Z_PARAM_STRING(dbname, dbname_len)
  1407. Z_PARAM_STRING(charset, charset_len)
  1408. Z_PARAM_LONG(session_mode)
  1409. ZEND_PARSE_PARAMETERS_END();
  1410. #ifdef HAVE_OCI8_DTRACE
  1411. if (DTRACE_OCI8_CONNECT_ENTRY_ENABLED()) {
  1412. DTRACE_OCI8_CONNECT_ENTRY(username, dbname, charset, session_mode, persistent, exclusive);
  1413. }
  1414. #endif /* HAVE_OCI8_DTRACE */
  1415. if (!charset_len) {
  1416. charset = NULL;
  1417. }
  1418. 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);
  1419. #ifdef HAVE_OCI8_DTRACE
  1420. if (DTRACE_OCI8_CONNECT_RETURN_ENABLED()) {
  1421. DTRACE_OCI8_CONNECT_RETURN(connection);
  1422. }
  1423. #endif /* HAVE_OCI8_DTRACE */
  1424. if (!connection) {
  1425. RETURN_FALSE;
  1426. }
  1427. RETURN_RES(connection->id);
  1428. }
  1429. /* }}} */
  1430. /* {{{ php_oci_do_connect_ex()
  1431. *
  1432. * The real connect function. Allocates all the resources needed, establishes the connection and
  1433. * returns the result handle (or NULL)
  1434. */
  1435. 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)
  1436. {
  1437. zval *zvp;
  1438. zend_resource *le;
  1439. zend_resource new_le;
  1440. php_oci_connection *connection = NULL;
  1441. smart_str hashed_details = {0};
  1442. time_t timestamp;
  1443. php_oci_spool *session_pool = NULL;
  1444. zend_bool use_spool = 1; /* Default is to use client-side session pool */
  1445. zend_bool ping_done = 0;
  1446. ub2 charsetid = 0;
  1447. ub2 charsetid_nls_lang = 0;
  1448. if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
  1449. php_error_docref(NULL, E_WARNING, "Invalid session mode specified (" ZEND_LONG_FMT ")", session_mode);
  1450. return NULL;
  1451. }
  1452. if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
  1453. if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
  1454. php_error_docref(NULL, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
  1455. return NULL;
  1456. }
  1457. if (session_mode & PHP_OCI_CRED_EXT) {
  1458. #ifdef PHP_WIN32
  1459. /* Disable external authentication on Windows as Impersonation is not yet handled.
  1460. * TODO: Re-enable this once OCI provides capability.
  1461. */
  1462. php_error_docref(NULL, E_WARNING, "External Authentication is not supported on Windows");
  1463. return NULL;
  1464. #endif
  1465. if (username_len != 1 || username[0] != '/' || password_len != 0) {
  1466. php_error_docref(NULL, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
  1467. return NULL;
  1468. }
  1469. }
  1470. if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
  1471. /* Increase security by not caching privileged oci_pconnect() connections. The
  1472. * connection becomes equivalent to oci_connect() or oci_new_connect().
  1473. */
  1474. persistent = 0;
  1475. if (!OCI_G(privileged_connect)) {
  1476. php_error_docref(NULL, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
  1477. return NULL;
  1478. }
  1479. }
  1480. }
  1481. /* Initialize global handles if they weren't initialized before */
  1482. if (OCI_G(env) == NULL) {
  1483. php_oci_init_global_handles();
  1484. if (OCI_G(env) == NULL) {
  1485. return NULL;
  1486. }
  1487. }
  1488. /* We cannot use the new session create logic (OCISessionGet from
  1489. * client-side session pool) when privileged connect or password
  1490. * change is attempted or OCI_CRED_EXT mode is specified.
  1491. * TODO: Re-enable this when OCI provides support.
  1492. */
  1493. if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
  1494. use_spool = 0;
  1495. }
  1496. smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
  1497. smart_str_appendl_ex(&hashed_details, username, username_len, 0);
  1498. smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
  1499. /* DRCP: connection_class is an attribute of a connection */
  1500. if (OCI_G(connection_class)){
  1501. smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
  1502. }
  1503. smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
  1504. /* Add edition attribute to the hash */
  1505. if (OCI_G(edition)){
  1506. smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
  1507. }
  1508. smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
  1509. if (password_len) {
  1510. zend_ulong password_hash;
  1511. password_hash = zend_inline_hash_func(password, password_len);
  1512. smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
  1513. }
  1514. smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
  1515. if (dbname) {
  1516. smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
  1517. }
  1518. smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
  1519. if (charset && *charset) {
  1520. PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
  1521. if (!charsetid) {
  1522. php_error_docref(NULL, E_WARNING, "Invalid character set name: %s", charset);
  1523. } else {
  1524. smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
  1525. }
  1526. }
  1527. /* use NLS_LANG if no or invalid charset specified */
  1528. if (!charsetid) {
  1529. size_t rsize = 0;
  1530. sword result;
  1531. PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
  1532. if (result != OCI_SUCCESS) {
  1533. charsetid_nls_lang = 0;
  1534. }
  1535. smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
  1536. }
  1537. timestamp = time(NULL);
  1538. smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
  1539. if (persistent) {
  1540. smart_str_appendl_ex(&hashed_details, "pc", sizeof("pc") - 1, 0);
  1541. }
  1542. smart_str_0(&hashed_details);
  1543. /* make it lowercase */
  1544. php_strtolower(ZSTR_VAL(hashed_details.s), ZSTR_LEN(hashed_details.s));
  1545. if (!exclusive && !new_password) {
  1546. zend_bool found = 0;
  1547. if (persistent && ((zvp = zend_hash_find(&EG(persistent_list), hashed_details.s))) != NULL) {
  1548. zend_resource *le = Z_RES_P(zvp);
  1549. found = 1;
  1550. /* found */
  1551. if (le->type == le_pconnection) {
  1552. connection = (php_oci_connection *)le->ptr;
  1553. }
  1554. } else if (!persistent && ((zvp = zend_hash_find(&EG(regular_list), hashed_details.s)) != NULL)) {
  1555. le = Z_RES_P(zvp);
  1556. found = 1;
  1557. if (le->type == le_index_ptr) {
  1558. zend_resource *ptr;
  1559. ptr = (zend_resource *) le->ptr;
  1560. if (ptr && (ptr->type == le_connection)) {
  1561. connection = (php_oci_connection *)ptr->ptr;
  1562. }
  1563. }
  1564. }
  1565. #ifdef HAVE_OCI8_DTRACE
  1566. if (DTRACE_OCI8_CONNECT_LOOKUP_ENABLED()) {
  1567. DTRACE_OCI8_CONNECT_LOOKUP(connection, connection && connection->is_stub ? 1 : 0);
  1568. }
  1569. #endif /* HAVE_OCI8_DTRACE */
  1570. /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
  1571. * private spool A connection is a stub if it is only a cached structure and the real
  1572. * connection is released to its underlying private session pool. We currently do not have
  1573. * stub support for non-persistent conns.
  1574. *
  1575. * TODO: put in negative code for non-persistent stubs
  1576. */
  1577. if (connection && connection->is_persistent && connection->is_stub) {
  1578. if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, (int) session_mode)) {
  1579. smart_str_free(&hashed_details);
  1580. zend_hash_del(&EG(persistent_list), connection->hash_key);
  1581. return NULL;
  1582. }
  1583. /* We do the ping in php_oci_create_session, no need to ping again below */
  1584. ping_done = 1;
  1585. }
  1586. if (connection) {
  1587. if (connection->is_open) {
  1588. /* found an open connection. now ping it */
  1589. if (connection->is_persistent) {
  1590. /* Check connection liveness in the following order:
  1591. * 1) always check OCI_ATTR_SERVER_STATUS
  1592. * 2) see if it's time to ping it
  1593. * 3) ping it if needed
  1594. */
  1595. if (php_oci_connection_status(connection)) {
  1596. /* Only ping if:
  1597. *
  1598. * 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
  1599. *
  1600. * 2) current_timestamp > next_ping, which means "it's time to check if it's
  1601. * still alive"
  1602. */
  1603. if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection)) {
  1604. /* server died */
  1605. } else {
  1606. php_oci_connection *tmp = (php_oci_connection *) NULL;
  1607. zval *tmp_val = (zval *) NULL;
  1608. /* okay, the connection is open and the server is still alive */
  1609. connection->used_this_request = 1;
  1610. if (connection->id) {
  1611. tmp_val = zend_hash_index_find(&EG(regular_list), connection->id->handle);
  1612. if ((tmp_val != NULL) && (Z_TYPE_P(tmp_val) == IS_RESOURCE)) {
  1613. tmp = Z_RES_VAL_P(tmp_val);
  1614. }
  1615. if ((tmp_val != NULL) && (tmp != NULL) &&
  1616. (ZSTR_LEN(tmp->hash_key) == ZSTR_LEN(hashed_details.s)) &&
  1617. (memcmp(ZSTR_VAL(tmp->hash_key), ZSTR_VAL(hashed_details.s),
  1618. ZSTR_LEN(tmp->hash_key)) == 0)) {
  1619. connection = tmp;
  1620. GC_ADDREF(connection->id);
  1621. }
  1622. } else {
  1623. PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection);
  1624. /* Persistent connections: For old close semantics we artificially
  1625. * bump up the refcount to prevent the non-persistent destructor
  1626. * from getting called until request shutdown. The refcount is
  1627. * decremented in the persistent helper
  1628. */
  1629. if (OCI_G(old_oci_close_semantics)) {
  1630. GC_ADDREF(connection->id);
  1631. }
  1632. }
  1633. smart_str_free(&hashed_details);
  1634. return connection;
  1635. }
  1636. }
  1637. /* server died */
  1638. } else {
  1639. /* we do not ping non-persistent connections */
  1640. smart_str_free(&hashed_details);
  1641. GC_ADDREF(connection->id);
  1642. return connection;
  1643. }
  1644. } /* is_open is true? */
  1645. /* Server died - connection not usable. The is_open=true can also fall through to here,
  1646. * if ping fails
  1647. */
  1648. if (persistent){
  1649. connection->is_open = 0;
  1650. connection->used_this_request = 1;
  1651. /* We have to do a hash_del but need to preserve the resource if there is a positive
  1652. * refcount. Set the data pointer in the list entry to NULL
  1653. */
  1654. if (connection == connection->id->ptr) {
  1655. le->ptr = NULL;
  1656. }
  1657. zend_hash_del(&EG(persistent_list), hashed_details.s);
  1658. } else {
  1659. /* We only remove the hash entry. The resource and the list entry with its pointer
  1660. * to the resource are still intact
  1661. */
  1662. zend_hash_del(&EG(regular_list), hashed_details.s);
  1663. }
  1664. connection = NULL;
  1665. } else if (found) {
  1666. /* found something, but it's not a connection, delete it */
  1667. if (persistent) {
  1668. zend_hash_del(&EG(persistent_list), hashed_details.s);
  1669. } else {
  1670. zend_hash_del(&EG(regular_list), hashed_details.s);
  1671. }
  1672. }
  1673. }
  1674. /* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
  1675. * a last resort, return a non-persistent connection.
  1676. */
  1677. if (persistent) {
  1678. zend_bool alloc_non_persistent = 0;
  1679. if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
  1680. /* try to find an idle connection and kill it */
  1681. zend_hash_apply(&EG(persistent_list), php_oci_persistent_helper);
  1682. if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
  1683. /* all persistent connactions are in use, fallback to non-persistent connection creation */
  1684. php_error_docref(NULL, E_NOTICE, "Too many open persistent connections (" ZEND_LONG_FMT ")", OCI_G(num_persistent));
  1685. alloc_non_persistent = 1;
  1686. }
  1687. }
  1688. if (alloc_non_persistent) {
  1689. connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
  1690. connection->hash_key = zend_string_dup(hashed_details.s, 0);
  1691. connection->is_persistent = 0;
  1692. ZVAL_UNDEF(&connection->taf_callback);
  1693. #ifdef HAVE_OCI8_DTRACE
  1694. connection->client_id = NULL;
  1695. #endif
  1696. } else {
  1697. connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
  1698. if (connection == NULL) {
  1699. return NULL;
  1700. }
  1701. connection->hash_key = zend_string_dup(hashed_details.s, 1);
  1702. if (connection->hash_key == NULL) {
  1703. free(connection);
  1704. return NULL;
  1705. }
  1706. connection->is_persistent = 1;
  1707. ZVAL_UNDEF(&connection->taf_callback);
  1708. #ifdef HAVE_OCI8_DTRACE
  1709. connection->client_id = NULL;
  1710. #endif
  1711. }
  1712. } else {
  1713. connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
  1714. connection->hash_key = zend_string_dup(hashed_details.s, 0);
  1715. connection->is_persistent = 0;
  1716. ZVAL_UNDEF(&connection->taf_callback);
  1717. #ifdef HAVE_OCI8_DTRACE
  1718. connection->client_id = NULL;
  1719. #endif
  1720. }
  1721. /* {{{ Get the session pool that suits this connection request from the persistent list. This
  1722. * step is only for non-persistent connections as persistent connections have private session
  1723. * pools. Non-persistent conns use shared session pool to allow for optimizations such as
  1724. * caching the physical connection (for DRCP) even when the non-persistent php connection is
  1725. * destroyed.
  1726. *
  1727. * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
  1728. */
  1729. if (use_spool && !connection->is_persistent) {
  1730. if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang))==NULL)
  1731. {
  1732. php_oci_connection_close(connection);
  1733. smart_str_free(&hashed_details);
  1734. return NULL;
  1735. }
  1736. }
  1737. /* }}} */
  1738. connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
  1739. /* Mark password as unchanged by PHP during the duration of the database session */
  1740. connection->passwd_changed = 0;
  1741. smart_str_free(&hashed_details);
  1742. if (charsetid) {
  1743. connection->charset = charsetid;
  1744. } else {
  1745. connection->charset = charsetid_nls_lang;
  1746. }
  1747. /* Old session creation semantics when session pool cannot be used Eg: privileged
  1748. * connect/password change
  1749. */
  1750. if (!use_spool) {
  1751. if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, (int) session_mode)) {
  1752. php_oci_connection_close(connection);
  1753. return NULL;
  1754. }
  1755. } else {
  1756. /* create using the client-side session pool */
  1757. 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)) {
  1758. php_oci_connection_close(connection);
  1759. return NULL;
  1760. }
  1761. }
  1762. /* Mark it as open */
  1763. connection->is_open = 1;
  1764. /* add to the appropriate hash */
  1765. if (connection->is_persistent) {
  1766. #if PHP_VERSION_ID < 70300
  1767. new_le.ptr = connection;
  1768. new_le.type = le_pconnection;
  1769. #endif
  1770. connection->used_this_request = 1;
  1771. PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection);
  1772. /* Persistent connections: For old close semantics we artificially bump up the refcount to
  1773. * prevent the non-persistent destructor from getting called until request shutdown. The
  1774. * refcount is decremented in the persistent helper
  1775. */
  1776. if (OCI_G(old_oci_close_semantics)) {
  1777. GC_ADDREF(connection->id);
  1778. }
  1779. #if PHP_VERSION_ID < 70300
  1780. zend_hash_update_mem(&EG(persistent_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource));
  1781. #else
  1782. zend_register_persistent_resource_ex(connection->hash_key, connection, le_pconnection);
  1783. #endif
  1784. OCI_G(num_persistent)++;
  1785. OCI_G(num_links)++;
  1786. } else if (!exclusive) {
  1787. PHP_OCI_REGISTER_RESOURCE(connection, le_connection);
  1788. new_le.ptr = connection->id;
  1789. new_le.type = le_index_ptr;
  1790. zend_hash_update_mem(&EG(regular_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource));
  1791. OCI_G(num_links)++;
  1792. } else {
  1793. PHP_OCI_REGISTER_RESOURCE(connection, le_connection);
  1794. OCI_G(num_links)++;
  1795. }
  1796. #ifdef HAVE_OCI8_DTRACE
  1797. if (DTRACE_OCI8_CONNECT_TYPE_ENABLED()) {
  1798. DTRACE_OCI8_CONNECT_TYPE(connection->is_persistent ? 1 : 0, exclusive ? 1 : 0, connection, OCI_G(num_persistent), OCI_G(num_links));
  1799. }
  1800. #endif /* HAVE_OCI8_DTRACE */
  1801. return connection;
  1802. }
  1803. /* }}} */
  1804. /* {{{ php_oci_connection_ping()
  1805. *
  1806. * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
  1807. */
  1808. static int php_oci_connection_ping(php_oci_connection *connection)
  1809. {
  1810. sword errstatus;
  1811. #if (!((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))))
  1812. char version[256];
  1813. #endif
  1814. OCI_G(errcode) = 0; /* assume ping is successful */
  1815. /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
  1816. * such as from Pre-10.1 servers, the error is still from the server and we would have
  1817. * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
  1818. * Pre-10.2 clients
  1819. */
  1820. #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
  1821. PHP_OCI_CALL_RETURN(errstatus, OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
  1822. #else
  1823. /* use good old OCIServerVersion() */
  1824. PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
  1825. #endif
  1826. if (errstatus == OCI_SUCCESS) {
  1827. return 1;
  1828. } else {
  1829. sb4 error_code = 0;
  1830. text tmp_buf[PHP_OCI_ERRBUF_LEN];
  1831. /* Treat ORA-1010 as a successful Ping */
  1832. OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
  1833. if (error_code == 1010) {
  1834. return 1;
  1835. }
  1836. OCI_G(errcode) = error_code;
  1837. }
  1838. return 0;
  1839. }
  1840. /* }}} */
  1841. /* {{{ php_oci_connection_status()
  1842. *
  1843. * Check connection status (pre-ping check)
  1844. */
  1845. static int php_oci_connection_status(php_oci_connection *connection)
  1846. {
  1847. ub4 ss = OCI_SERVER_NOT_CONNECTED;
  1848. sword errstatus;
  1849. /* get OCI_ATTR_SERVER_STATUS */
  1850. PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
  1851. if (errstatus == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
  1852. return 1;
  1853. }
  1854. /* ignore errors here, just return failure */
  1855. return 0;
  1856. }
  1857. /* }}} */
  1858. /* {{{ php_oci_connection_rollback()
  1859. *
  1860. * Rollback connection
  1861. */
  1862. int php_oci_connection_rollback(php_oci_connection *connection)
  1863. {
  1864. sword errstatus;
  1865. PHP_OCI_CALL_RETURN(errstatus, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
  1866. connection->rb_on_disconnect = 0;
  1867. if (errstatus != OCI_SUCCESS) {
  1868. connection->errcode = php_oci_error(connection->err, errstatus);
  1869. PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
  1870. return 1;
  1871. }
  1872. connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
  1873. return 0;
  1874. }
  1875. /* }}} */
  1876. /* {{{ php_oci_connection_commit()
  1877. *
  1878. * Commit connection
  1879. */
  1880. int php_oci_connection_commit(php_oci_connection *connection)
  1881. {
  1882. sword errstatus;
  1883. PHP_OCI_CALL_RETURN(errstatus, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
  1884. connection->rb_on_disconnect = 0;
  1885. if (errstatus != OCI_SUCCESS) {
  1886. connection->errcode = php_oci_error(connection->err, errstatus);
  1887. PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
  1888. return 1;
  1889. }
  1890. connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
  1891. return 0;
  1892. }
  1893. /* }}} */
  1894. /* {{{ php_oci_connection_close()
  1895. *
  1896. * Close the connection and free all its resources
  1897. */
  1898. static int php_oci_connection_close(php_oci_connection *connection)
  1899. {
  1900. int result = 0;
  1901. zend_bool in_call_save = OCI_G(in_call);
  1902. #ifdef HAVE_OCI8_DTRACE
  1903. if (DTRACE_OCI8_CONNECTION_CLOSE_ENABLED()) {
  1904. DTRACE_OCI8_CONNECTION_CLOSE(connection);
  1905. }
  1906. #endif /* HAVE_OCI8_DTRACE */
  1907. if (!connection->is_stub) {
  1908. /* Release resources associated with connection */
  1909. php_oci_connection_release(connection);
  1910. }
  1911. if (!connection->using_spool && connection->svc) {
  1912. PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
  1913. }
  1914. if (connection->err) {
  1915. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
  1916. }
  1917. if (connection->authinfo) {
  1918. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
  1919. }
  1920. /* No Handlefrees for session pool connections */
  1921. if (!connection->using_spool) {
  1922. if (connection->session) {
  1923. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
  1924. }
  1925. if (connection->is_attached) {
  1926. PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
  1927. }
  1928. if (connection->svc) {
  1929. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
  1930. }
  1931. if (connection->server) {
  1932. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
  1933. }
  1934. if (connection->env) {
  1935. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
  1936. }
  1937. } else if (connection->private_spool) {
  1938. /* Keep this as the last member to be freed, as there are dependencies
  1939. * (like env) on the session pool
  1940. */
  1941. php_oci_spool_close(connection->private_spool);
  1942. connection->private_spool = NULL;
  1943. }
  1944. if (GC_REFCOUNT(connection->hash_key) >= 2) {
  1945. zend_hash_del(&EG(regular_list), connection->hash_key);
  1946. }
  1947. if (connection->hash_key) {
  1948. pefree(connection->hash_key, connection->is_persistent);
  1949. connection->hash_key = NULL;
  1950. }
  1951. #ifdef HAVE_OCI8_DTRACE
  1952. if (connection->client_id) {
  1953. pefree(connection->client_id, connection->is_persistent);
  1954. connection->client_id = NULL;
  1955. }
  1956. #endif /* HAVE_OCI8_DTRACE */
  1957. if (!Z_ISUNDEF(connection->taf_callback)) {
  1958. /* If it's NULL, then its value should be freed already */
  1959. if (!Z_ISNULL(connection->taf_callback)) {
  1960. zval_ptr_dtor(&connection->taf_callback);
  1961. }
  1962. ZVAL_UNDEF(&connection->taf_callback);
  1963. }
  1964. pefree(connection, connection->is_persistent);
  1965. connection = NULL;
  1966. OCI_G(in_call) = in_call_save;
  1967. return result;
  1968. }
  1969. /* }}} */
  1970. /* {{{ php_oci_connection_release()
  1971. *
  1972. * Release the connection's resources. This involves freeing descriptors and rolling back
  1973. * transactions, setting timeout-related parameters etc. For session-pool using connections, the
  1974. * underlying connection is released to its session pool.
  1975. */
  1976. int php_oci_connection_release(php_oci_connection *connection)
  1977. {
  1978. int result = 0;
  1979. zend_bool in_call_save = OCI_G(in_call);
  1980. time_t timestamp = time(NULL);
  1981. if (connection->is_stub) {
  1982. return 0;
  1983. }
  1984. if (connection->descriptors) {
  1985. php_oci_connection_descriptors_free(connection);
  1986. }
  1987. if (connection->svc) {
  1988. /* rollback outstanding transactions */
  1989. if (connection->rb_on_disconnect) {
  1990. if (php_oci_connection_rollback(connection)) {
  1991. /* rollback failed */
  1992. result = 1;
  1993. }
  1994. }
  1995. }
  1996. if (OCI_G(persistent_timeout) > 0) {
  1997. connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
  1998. }
  1999. /* We may have half-cooked connections to clean up */
  2000. if (connection->next_pingp) {
  2001. if (OCI_G(ping_interval) >= 0) {
  2002. *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
  2003. } else {
  2004. /* ping_interval is -1 */
  2005. *(connection->next_pingp) = 0;
  2006. }
  2007. }
  2008. /* Release the session (stubs are filtered out at the beginning)*/
  2009. if (connection->using_spool) {
  2010. ub4 rlsMode = OCI_DEFAULT;
  2011. if (result) {
  2012. rlsMode |= OCI_SESSRLS_DROPSESS;
  2013. }
  2014. /* Sessions for non-persistent connections should be dropped. For 11 and above, the session
  2015. * pool has its own mechanism for doing so for purity NEW connections. We need to do so
  2016. * explicitly for 10.2 and earlier.
  2017. */
  2018. #if (!(OCI_MAJOR_VERSION >= 11))
  2019. if (!connection->is_persistent) {
  2020. rlsMode |= OCI_SESSRLS_DROPSESS;
  2021. }
  2022. #endif
  2023. if (connection->svc) {
  2024. PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
  2025. 0, rlsMode));
  2026. }
  2027. /* It no longer has relation with the database session. However authinfo and env are
  2028. * cached
  2029. */
  2030. connection->svc = NULL;
  2031. connection->server = NULL;
  2032. connection->session = NULL;
  2033. connection->is_attached = connection->is_open = connection->rb_on_disconnect = connection->used_this_request = 0;
  2034. connection->is_stub = 1;
  2035. /* Cut the link between the connection structure and the time_t structure allocated within
  2036. * the OCI session
  2037. */
  2038. connection->next_pingp = NULL;
  2039. #ifdef HAVE_OCI8_DTRACE
  2040. if (connection->client_id) {
  2041. pefree(connection->client_id, connection->is_persistent);
  2042. connection->client_id = NULL;
  2043. }
  2044. #endif /* HAVE_OCI8_DTRACE */
  2045. }
  2046. /* Always set id to null, so next time a new resource is being registered. */
  2047. connection->id = NULL;
  2048. OCI_G(in_call) = in_call_save;
  2049. return result;
  2050. }
  2051. /* }}} */
  2052. /* {{{ php_oci_password_change()
  2053. *
  2054. * Change password for the user with the username given
  2055. */
  2056. 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)
  2057. {
  2058. sword errstatus;
  2059. 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));
  2060. if (errstatus != OCI_SUCCESS) {
  2061. connection->errcode = php_oci_error(connection->err, errstatus);
  2062. PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
  2063. return 1;
  2064. }
  2065. connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
  2066. connection->passwd_changed = 1;
  2067. return 0;
  2068. }
  2069. /* }}} */
  2070. /* {{{ php_oci_client_get_version()
  2071. *
  2072. * Get Oracle client library version
  2073. */
  2074. void php_oci_client_get_version(char *version, size_t version_size)
  2075. {
  2076. #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIClientVersion only available 10.2 onwards */
  2077. sword major_version = 0;
  2078. sword minor_version = 0;
  2079. sword update_num = 0;
  2080. sword patch_num = 0;
  2081. sword port_update_num = 0;
  2082. PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num));
  2083. snprintf(version, version_size, "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num);
  2084. #else
  2085. memcpy(version, "Unknown", sizeof("Unknown"));
  2086. #endif
  2087. }
  2088. /* }}} */
  2089. /* {{{ php_oci_server_get_version()
  2090. *
  2091. * Get Oracle server version
  2092. */
  2093. int php_oci_server_get_version(php_oci_connection *connection, char *version, size_t version_size)
  2094. {
  2095. sword errstatus;
  2096. PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, connection->err, (text *)version, (ub4) version_size, OCI_HTYPE_SVCCTX));
  2097. if (errstatus != OCI_SUCCESS) {
  2098. connection->errcode = php_oci_error(connection->err, errstatus);
  2099. PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
  2100. return 1;
  2101. }
  2102. return 0;
  2103. }
  2104. /* }}} */
  2105. /* {{{ php_oci_column_to_zval()
  2106. *
  2107. * Convert php_oci_out_column struct into zval
  2108. */
  2109. int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode)
  2110. {
  2111. php_oci_descriptor *descriptor;
  2112. ub4 lob_length;
  2113. int column_size;
  2114. char *lob_buffer = (char *)0;
  2115. int lob_fetch_status;
  2116. if (column->indicator == -1) { /* column is NULL */
  2117. ZVAL_NULL(value);
  2118. return 0;
  2119. }
  2120. if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
  2121. ZVAL_RES(value, column->stmtid);
  2122. GC_ADDREF(column->stmtid);
  2123. } else if (column->is_descr) {
  2124. if (column->data_type != SQLT_RDD) {
  2125. /* reset descriptor's length */
  2126. descriptor = (php_oci_descriptor *) column->descid->ptr;
  2127. if (!descriptor) {
  2128. php_error_docref(NULL, E_WARNING, "Unable to find LOB descriptor #%d", column->descid->handle);
  2129. return 1;
  2130. }
  2131. descriptor->lob_size = -1;
  2132. descriptor->lob_current_position = 0;
  2133. descriptor->buffering = 0;
  2134. }
  2135. if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
  2136. /* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
  2137. if (column->chunk_size)
  2138. descriptor->chunk_size = column->chunk_size;
  2139. lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length);
  2140. if (descriptor->chunk_size) /* Cache the chunk_size to avoid recalling OCILobGetChunkSize */
  2141. column->chunk_size = descriptor->chunk_size;
  2142. php_oci_temp_lob_close(descriptor);
  2143. if (lob_fetch_status) {
  2144. ZVAL_FALSE(value);
  2145. return 1;
  2146. } else {
  2147. if (lob_length > 0) {
  2148. ZVAL_STRINGL(value, lob_buffer, lob_length);
  2149. } else {
  2150. ZVAL_EMPTY_STRING(value);
  2151. }
  2152. if (lob_buffer)
  2153. efree(lob_buffer);
  2154. return 0;
  2155. }
  2156. } else {
  2157. /* return the locator */
  2158. object_init_ex(value, oci_lob_class_entry_ptr);
  2159. add_property_resource(value, "descriptor", column->descid);
  2160. GC_ADDREF(column->descid);
  2161. }
  2162. } else {
  2163. switch (column->retcode) {
  2164. case 0:
  2165. /* intact value */
  2166. if (column->piecewise) {
  2167. column_size = column->retlen4;
  2168. } else {
  2169. column_size = column->retlen;
  2170. }
  2171. break;
  2172. default:
  2173. ZVAL_FALSE(value);
  2174. return 0;
  2175. }
  2176. ZVAL_STRINGL(value, column->data, column_size);
  2177. }
  2178. return 0;
  2179. }
  2180. /* }}} */
  2181. /* {{{ php_oci_fetch_row()
  2182. *
  2183. * Fetch the next row from the given statement
  2184. * Has logic for Oracle 12c Implicit Result Sets
  2185. */
  2186. void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
  2187. {
  2188. zval *z_statement, *array;
  2189. zval *placeholder = (zval*) NULL;
  2190. /* zend_array *temp_array = (zend_array *) NULL;*/
  2191. php_oci_statement *statement; /* statement that will be fetched from */
  2192. #if (OCI_MAJOR_VERSION >= 12)
  2193. php_oci_statement *invokedstatement; /* statement this function was invoked with */
  2194. #endif /* OCI_MAJOR_VERSION */
  2195. php_oci_out_column *column;
  2196. ub4 nrows = 1;
  2197. int i;
  2198. zend_long fetch_mode = 0;
  2199. if (expected_args > 2) {
  2200. /* only for ocifetchinto BC */
  2201. ZEND_PARSE_PARAMETERS_START(2, 3)
  2202. Z_PARAM_RESOURCE(z_statement)
  2203. Z_PARAM_ZVAL(array)
  2204. Z_PARAM_OPTIONAL
  2205. Z_PARAM_LONG(fetch_mode)
  2206. ZEND_PARSE_PARAMETERS_END();
  2207. if (ZEND_NUM_ARGS() == 2) {
  2208. fetch_mode = mode;
  2209. }
  2210. if (Z_ISREF_P(array))
  2211. placeholder = Z_REFVAL_P(array);
  2212. else
  2213. placeholder = array;
  2214. } else if (expected_args == 2) {
  2215. /* only for oci_fetch_array() */
  2216. ZEND_PARSE_PARAMETERS_START(1, 2)
  2217. Z_PARAM_RESOURCE(z_statement)
  2218. Z_PARAM_OPTIONAL
  2219. Z_PARAM_LONG(fetch_mode)
  2220. ZEND_PARSE_PARAMETERS_END();
  2221. if (ZEND_NUM_ARGS() == 1) {
  2222. fetch_mode = mode;
  2223. }
  2224. } else {
  2225. /* for all oci_fetch_*() */
  2226. ZEND_PARSE_PARAMETERS_START(1, 1)
  2227. Z_PARAM_RESOURCE(z_statement)
  2228. ZEND_PARSE_PARAMETERS_END();
  2229. fetch_mode = mode;
  2230. }
  2231. if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
  2232. /* none of the modes present, use the default one */
  2233. if (mode & PHP_OCI_ASSOC) {
  2234. fetch_mode |= PHP_OCI_ASSOC;
  2235. }
  2236. if (mode & PHP_OCI_NUM) {
  2237. fetch_mode |= PHP_OCI_NUM;
  2238. }
  2239. }
  2240. #if (OCI_MAJOR_VERSION < 12)
  2241. PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
  2242. if (php_oci_statement_fetch(statement, nrows)) {
  2243. RETURN_FALSE; /* end of fetch */
  2244. }
  2245. #else /* OCI_MAJOR_VERSION */
  2246. PHP_OCI_ZVAL_TO_STATEMENT(z_statement, invokedstatement);
  2247. if (invokedstatement->impres_flag == PHP_OCI_IMPRES_NO_CHILDREN ||
  2248. invokedstatement->impres_flag == PHP_OCI_IMPRES_IS_CHILD) {
  2249. /* Already know there are no Implicit Result Sets */
  2250. statement = invokedstatement;
  2251. } else if (invokedstatement->impres_flag == PHP_OCI_IMPRES_HAS_CHILDREN) {
  2252. /* Previously saw an Implicit Result Set in an earlier invocation of php_oci_fetch_row */
  2253. statement = (php_oci_statement *)invokedstatement->impres_child_stmt;
  2254. } else {
  2255. sword errstatus;
  2256. /* Check for an Implicit Result Set on this statement handle */
  2257. PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)invokedstatement->stmt, OCI_HTYPE_STMT,
  2258. (dvoid *) &invokedstatement->impres_count,
  2259. (ub4 *)NULL, OCI_ATTR_IMPLICIT_RESULT_COUNT, invokedstatement->err));
  2260. if (errstatus) {
  2261. RETURN_FALSE;
  2262. }
  2263. if (invokedstatement->impres_count > 0) {
  2264. /* Make it so the fetch occurs on the first Implicit Result Set */
  2265. statement = php_oci_get_implicit_resultset(invokedstatement);
  2266. if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT))
  2267. RETURN_FALSE;
  2268. invokedstatement->impres_count--;
  2269. invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement;
  2270. invokedstatement->impres_flag = PHP_OCI_IMPRES_HAS_CHILDREN;
  2271. } else {
  2272. statement = invokedstatement; /* didn't find Implicit Result Sets */
  2273. invokedstatement->impres_flag = PHP_OCI_IMPRES_NO_CHILDREN; /* Don't bother checking again */
  2274. }
  2275. }
  2276. if (php_oci_statement_fetch(statement, nrows)) {
  2277. /* End of fetch */
  2278. if (invokedstatement->impres_count > 0) {
  2279. /* Check next Implicit Result Set */
  2280. statement = php_oci_get_implicit_resultset(invokedstatement);
  2281. if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT))
  2282. RETURN_FALSE;
  2283. invokedstatement->impres_count--;
  2284. invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement;
  2285. if (php_oci_statement_fetch(statement, nrows)) {
  2286. /* End of all fetches */
  2287. RETURN_FALSE;
  2288. }
  2289. } else {
  2290. RETURN_FALSE;
  2291. }
  2292. }
  2293. #endif /* OCI_MAJOR_VERSION */
  2294. if (placeholder == NULL) {
  2295. placeholder = return_value;
  2296. } else {
  2297. zval_ptr_dtor(placeholder);
  2298. }
  2299. array_init(placeholder);
  2300. for (i = 0; i < statement->ncolumns; i++) {
  2301. column = php_oci_statement_get_column(statement, i + 1, NULL, 0);
  2302. if (column == NULL) {
  2303. continue;
  2304. }
  2305. if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
  2306. continue;
  2307. }
  2308. if (!(column->indicator == -1)) {
  2309. zval element;
  2310. php_oci_column_to_zval(column, &element, (int) fetch_mode);
  2311. if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
  2312. add_index_zval(placeholder, i, &element);
  2313. }
  2314. if (fetch_mode & PHP_OCI_ASSOC) {
  2315. if (fetch_mode & PHP_OCI_NUM) {
  2316. Z_TRY_ADDREF_P(&element);
  2317. }
  2318. add_assoc_zval(placeholder, column->name, &element);
  2319. }
  2320. } else {
  2321. if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
  2322. add_index_null(placeholder, i);
  2323. }
  2324. if (fetch_mode & PHP_OCI_ASSOC) {
  2325. add_assoc_null(placeholder, column->name);
  2326. }
  2327. }
  2328. }
  2329. if (expected_args > 2) {
  2330. RETURN_LONG(statement->ncolumns);
  2331. }
  2332. }
  2333. /* }}} */
  2334. /* {{{ php_oci_persistent_helper()
  2335. *
  2336. * Helper function to close/rollback persistent connections at the end of request. A return value of
  2337. * 1 indicates that the connection is to be destroyed
  2338. */
  2339. static int php_oci_persistent_helper(zval *zv)
  2340. {
  2341. zend_resource *le = Z_RES_P(zv);
  2342. time_t timestamp;
  2343. php_oci_connection *connection;
  2344. timestamp = time(NULL);
  2345. /* Persistent connection stubs are also counted as they have private session pools */
  2346. if (le->type == le_pconnection) {
  2347. connection = (php_oci_connection *)le->ptr;
  2348. /* Remove TAF callback function as it's bound to current request */
  2349. if (connection->used_this_request && !Z_ISUNDEF(connection->taf_callback) && !Z_ISNULL(connection->taf_callback)) {
  2350. php_oci_unregister_taf_callback(connection);
  2351. }
  2352. if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
  2353. #ifdef HAVE_OCI8_DTRACE
  2354. if (DTRACE_OCI8_CONNECT_EXPIRY_ENABLED()) {
  2355. DTRACE_OCI8_CONNECT_EXPIRY(connection, connection->is_stub ? 1 : 0, (long)connection->idle_expiry, (long)timestamp);
  2356. }
  2357. #endif /* HAVE_OCI8_DTRACE */
  2358. if (connection->idle_expiry < timestamp) {
  2359. /* connection has timed out */
  2360. return ZEND_HASH_APPLY_REMOVE;
  2361. }
  2362. }
  2363. }
  2364. return ZEND_HASH_APPLY_KEEP;
  2365. }
  2366. /* }}} */
  2367. /* {{{ php_oci_create_spool()
  2368. *
  2369. * Create(alloc + Init) Session pool for the given dbname and charsetid
  2370. */
  2371. 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)
  2372. {
  2373. php_oci_spool *session_pool = NULL;
  2374. zend_bool iserror = 0;
  2375. ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
  2376. OCIAuthInfo *spoolAuth = NULL;
  2377. sword errstatus;
  2378. /* Allocate sessionpool out of persistent memory */
  2379. session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
  2380. if (session_pool == NULL) {
  2381. iserror = 1;
  2382. goto exit_create_spool;
  2383. }
  2384. /* Populate key if passed */
  2385. if (hash_key && (ZSTR_LEN(hash_key) > 0)) {
  2386. session_pool->spool_hash_key = zend_string_dup(hash_key, 1);
  2387. if (session_pool->spool_hash_key == NULL) {
  2388. iserror = 1;
  2389. goto exit_create_spool;
  2390. }
  2391. }
  2392. /* Create the session pool's env */
  2393. if (!(session_pool->env = php_oci_create_env(charsetid))) {
  2394. iserror = 1;
  2395. goto exit_create_spool;
  2396. }
  2397. /* Allocate the pool handle */
  2398. PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
  2399. if (errstatus != OCI_SUCCESS) {
  2400. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2401. iserror = 1;
  2402. goto exit_create_spool;
  2403. }
  2404. /* Allocate the session pool error handle - This only for use in the destructor, as there is a
  2405. * generic bug which can free up the OCI_G(err) variable before destroying connections. We
  2406. * cannot use this for other roundtrip calls as there is no way the user can access this error
  2407. */
  2408. PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
  2409. if (errstatus != OCI_SUCCESS) {
  2410. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2411. iserror = 1;
  2412. goto exit_create_spool;
  2413. }
  2414. /* Disable RLB as we mostly have single-connection pools */
  2415. #if (OCI_MAJOR_VERSION > 10)
  2416. poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
  2417. #else
  2418. poolmode = OCI_SPC_HOMOGENEOUS;
  2419. #endif
  2420. #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
  2421. /* {{{ Allocate auth handle for session pool */
  2422. PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
  2423. if (errstatus != OCI_SUCCESS) {
  2424. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2425. iserror = 1;
  2426. goto exit_create_spool;
  2427. }
  2428. /* }}} */
  2429. /* {{{ Set the edition attribute on the auth handle */
  2430. if (OCI_G(edition)) {
  2431. 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)));
  2432. if (errstatus != OCI_SUCCESS) {
  2433. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2434. iserror = 1;
  2435. goto exit_create_spool;
  2436. }
  2437. }
  2438. /* }}} */
  2439. /* {{{ Set the driver name attribute on the auth handle */
  2440. 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)));
  2441. if (errstatus != OCI_SUCCESS) {
  2442. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2443. iserror = 1;
  2444. goto exit_create_spool;
  2445. }
  2446. /* }}} */
  2447. /* {{{ Set the auth handle on the session pool */
  2448. 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)));
  2449. if (errstatus != OCI_SUCCESS) {
  2450. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2451. iserror = 1;
  2452. goto exit_create_spool;
  2453. }
  2454. /* }}} */
  2455. #endif
  2456. /* Create the homogeneous session pool - We have different session pools for every different
  2457. * username, password, charset and dbname.
  2458. */
  2459. 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));
  2460. if (errstatus != OCI_SUCCESS) {
  2461. OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
  2462. iserror = 1;
  2463. }
  2464. exit_create_spool:
  2465. if (iserror && session_pool) {
  2466. php_oci_spool_close(session_pool);
  2467. session_pool = NULL;
  2468. }
  2469. if (spoolAuth) {
  2470. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
  2471. }
  2472. #ifdef HAVE_OCI8_DTRACE
  2473. if (DTRACE_OCI8_SESSPOOL_CREATE_ENABLED()) {
  2474. DTRACE_OCI8_SESSPOOL_CREATE(session_pool);
  2475. }
  2476. #endif /* HAVE_OCI8_DTRACE */
  2477. return session_pool;
  2478. }
  2479. /* }}} */
  2480. /* {{{ php_oci_get_spool()
  2481. *
  2482. * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
  2483. * non-persistent connections.
  2484. */
  2485. 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)
  2486. {
  2487. smart_str spool_hashed_details = {0};
  2488. php_oci_spool *session_pool = NULL;
  2489. #if PHP_VERSION_ID < 70300
  2490. zend_resource spool_le = {{0}};
  2491. #endif
  2492. zend_resource *spool_out_le = NULL;
  2493. zend_bool iserror = 0;
  2494. zval *spool_out_zv = NULL;
  2495. /* {{{ Create the spool hash key */
  2496. smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
  2497. smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
  2498. smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
  2499. /* Add edition attribute to the hash */
  2500. if (OCI_G(edition)){
  2501. smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
  2502. }
  2503. smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
  2504. if (password_len) {
  2505. zend_ulong password_hash;
  2506. password_hash = zend_inline_hash_func(password, password_len);
  2507. smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
  2508. }
  2509. smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
  2510. if (dbname_len) {
  2511. smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
  2512. }
  2513. smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
  2514. smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
  2515. /* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
  2516. smart_str_0(&spool_hashed_details);
  2517. php_strtolower(ZSTR_VAL(spool_hashed_details.s), ZSTR_LEN(spool_hashed_details.s));
  2518. /* }}} */
  2519. spool_out_zv = zend_hash_find(&EG(persistent_list), spool_hashed_details.s);
  2520. if (spool_out_zv != NULL) {
  2521. spool_out_le = Z_RES_P(spool_out_zv);
  2522. }
  2523. if (spool_out_le == NULL) {
  2524. session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.s, charsetid);
  2525. if (session_pool == NULL) {
  2526. iserror = 1;
  2527. goto exit_get_spool;
  2528. }
  2529. #if PHP_VERSION_ID < 70300
  2530. spool_le.ptr = session_pool;
  2531. spool_le.type = le_psessionpool;
  2532. PHP_OCI_REGISTER_RESOURCE(session_pool, le_psessionpool);
  2533. zend_hash_update_mem(&EG(persistent_list), session_pool->spool_hash_key, (void *)&spool_le, sizeof(zend_resource));
  2534. #else
  2535. zend_register_persistent_resource_ex(session_pool->spool_hash_key, session_pool, le_psessionpool);
  2536. #endif
  2537. } else if (spool_out_le->type == le_psessionpool &&
  2538. ZSTR_LEN(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == ZSTR_LEN(spool_hashed_details.s) &&
  2539. 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) {
  2540. /* retrieve the cached session pool */
  2541. session_pool = (php_oci_spool *)(spool_out_le->ptr);
  2542. }
  2543. exit_get_spool:
  2544. smart_str_free(&spool_hashed_details);
  2545. if (iserror && session_pool) {
  2546. php_oci_spool_close(session_pool);
  2547. session_pool = NULL;
  2548. }
  2549. return session_pool;
  2550. }
  2551. /* }}} */
  2552. /* {{{ php_oci_create_env()
  2553. *
  2554. * Create the OCI environment choosing the correct function for the OCI version
  2555. */
  2556. static OCIEnv *php_oci_create_env(ub2 charsetid)
  2557. {
  2558. OCIEnv *retenv = NULL;
  2559. /* create an environment using the character set id */
  2560. 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));
  2561. if (OCI_G(errcode) != OCI_SUCCESS) {
  2562. sb4 ora_error_code = 0;
  2563. text ora_msg_buf[PHP_OCI_ERRBUF_LEN]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
  2564. #ifdef HAVE_OCI_INSTANT_CLIENT
  2565. 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");
  2566. #else
  2567. 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");
  2568. #endif
  2569. if (retenv
  2570. && OCIErrorGet(retenv, (ub4)1, NULL, &ora_error_code, ora_msg_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
  2571. && *ora_msg_buf) {
  2572. php_error_docref(NULL, E_WARNING, "%s", ora_msg_buf);
  2573. }
  2574. return NULL;
  2575. }
  2576. return retenv;
  2577. }
  2578. /* }}} */
  2579. /* {{{ php_oci_old_create_session()
  2580. *
  2581. * This function is to be deprecated in future in favour of OCISessionGet which is used in
  2582. * php_oci_do_connect_ex
  2583. */
  2584. 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)
  2585. {
  2586. ub4 statement_cache_size = 0;
  2587. if (OCI_G(statement_cache_size) > 0) {
  2588. if (OCI_G(statement_cache_size) > SB4MAXVAL)
  2589. statement_cache_size = (ub4) SB4MAXVAL;
  2590. else
  2591. statement_cache_size = (ub4) OCI_G(statement_cache_size);
  2592. }
  2593. /* Create the OCI environment separate for each connection */
  2594. if (!(connection->env = php_oci_create_env(connection->charset))) {
  2595. return 1;
  2596. }
  2597. /* {{{ Allocate our server handle */
  2598. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
  2599. if (OCI_G(errcode) != OCI_SUCCESS) {
  2600. php_oci_error(OCI_G(err), OCI_G(errcode));
  2601. return 1;
  2602. }
  2603. /* }}} */
  2604. /* {{{ Attach to the server */
  2605. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
  2606. if (OCI_G(errcode) != OCI_SUCCESS) {
  2607. php_oci_error(OCI_G(err), OCI_G(errcode));
  2608. return 1;
  2609. }
  2610. /* }}} */
  2611. connection->is_attached = 1;
  2612. /* {{{ Allocate our session handle */
  2613. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
  2614. if (OCI_G(errcode) != OCI_SUCCESS) {
  2615. php_oci_error(OCI_G(err), OCI_G(errcode));
  2616. return 1;
  2617. }
  2618. /* }}} */
  2619. /* {{{ Allocate our private error-handle */
  2620. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
  2621. if (OCI_G(errcode) != OCI_SUCCESS) {
  2622. php_oci_error(OCI_G(err), OCI_G(errcode));
  2623. return 1;
  2624. }
  2625. /* }}} */
  2626. /* {{{ Allocate our service-context */
  2627. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
  2628. if (OCI_G(errcode) != OCI_SUCCESS) {
  2629. php_oci_error(OCI_G(err), OCI_G(errcode));
  2630. return 1;
  2631. }
  2632. /* }}} */
  2633. /* {{{ Set the username */
  2634. if (username) {
  2635. 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)));
  2636. if (OCI_G(errcode) != OCI_SUCCESS) {
  2637. php_oci_error(OCI_G(err), OCI_G(errcode));
  2638. return 1;
  2639. }
  2640. }
  2641. /* }}} */
  2642. /* {{{ Set the password */
  2643. if (password) {
  2644. 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)));
  2645. if (OCI_G(errcode) != OCI_SUCCESS) {
  2646. php_oci_error(OCI_G(err), OCI_G(errcode));
  2647. return 1;
  2648. }
  2649. }
  2650. /* }}} */
  2651. /* {{{ Set the edition attribute on the session handle */
  2652. #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
  2653. if (OCI_G(edition)) {
  2654. 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)));
  2655. if (OCI_G(errcode) != OCI_SUCCESS) {
  2656. php_oci_error(OCI_G(err), OCI_G(errcode));
  2657. return 1;
  2658. }
  2659. }
  2660. #endif
  2661. /* }}} */
  2662. /* {{{ Set the driver name attribute on the session handle */
  2663. #if (OCI_MAJOR_VERSION >= 11)
  2664. 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)));
  2665. if (OCI_G(errcode) != OCI_SUCCESS) {
  2666. php_oci_error(OCI_G(err), OCI_G(errcode));
  2667. return 1;
  2668. }
  2669. #endif
  2670. /* }}} */
  2671. /* {{{ Set the server handle in the service handle */
  2672. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
  2673. if (OCI_G(errcode) != OCI_SUCCESS) {
  2674. php_oci_error(OCI_G(err), OCI_G(errcode));
  2675. return 1;
  2676. }
  2677. /* }}} */
  2678. /* {{{ Set the authentication handle in the service handle */
  2679. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
  2680. if (OCI_G(errcode) != OCI_SUCCESS) {
  2681. php_oci_error(OCI_G(err), OCI_G(errcode));
  2682. return 1;
  2683. }
  2684. /* }}} */
  2685. if (new_password) {
  2686. /* {{{ Try to change password if new one was provided */
  2687. 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));
  2688. if (OCI_G(errcode) != OCI_SUCCESS) {
  2689. php_oci_error(OCI_G(err), OCI_G(errcode));
  2690. return 1;
  2691. }
  2692. 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)));
  2693. if (OCI_G(errcode) != OCI_SUCCESS) {
  2694. php_oci_error(OCI_G(err), OCI_G(errcode));
  2695. return 1;
  2696. }
  2697. /* }}} */
  2698. } else {
  2699. /* {{{ start the session */
  2700. ub4 cred_type = OCI_CRED_RDBMS;
  2701. /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
  2702. if (session_mode & PHP_OCI_CRED_EXT) {
  2703. cred_type = OCI_CRED_EXT;
  2704. session_mode ^= PHP_OCI_CRED_EXT;
  2705. }
  2706. session_mode |= OCI_STMT_CACHE;
  2707. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
  2708. if (OCI_G(errcode) != OCI_SUCCESS) {
  2709. php_oci_error(OCI_G(err), OCI_G(errcode));
  2710. /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
  2711. * user's password has expired, but is still usable.
  2712. */
  2713. if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
  2714. return 1;
  2715. }
  2716. }
  2717. /* }}} */
  2718. }
  2719. /* Brand new connection: Init and update the next_ping in the connection */
  2720. if (php_oci_ping_init(connection, OCI_G(err)) != OCI_SUCCESS) {
  2721. php_oci_error(OCI_G(err), OCI_G(errcode));
  2722. return 1;
  2723. }
  2724. 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)));
  2725. if (OCI_G(errcode) != OCI_SUCCESS) {
  2726. php_oci_error(OCI_G(err), OCI_G(errcode));
  2727. return 1;
  2728. }
  2729. /* Successfully created session */
  2730. return 0;
  2731. }
  2732. /* }}} */
  2733. /* {{{ php_oci_create_session()
  2734. *
  2735. * Create session using client-side session pool - new norm
  2736. */
  2737. 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)
  2738. {
  2739. php_oci_spool *actual_spool = NULL;
  2740. #if (OCI_MAJOR_VERSION > 10)
  2741. ub4 purity = -2; /* Illegal value to initialize */
  2742. #endif
  2743. time_t timestamp = time(NULL);
  2744. ub4 statement_cache_size = 0;
  2745. if (OCI_G(statement_cache_size) > 0) {
  2746. if (OCI_G(statement_cache_size) > SB4MAXVAL)
  2747. statement_cache_size = (ub4) SB4MAXVAL;
  2748. else
  2749. statement_cache_size = (ub4) OCI_G(statement_cache_size);
  2750. }
  2751. /* Persistent connections have private session pools */
  2752. if (connection->is_persistent && !connection->private_spool &&
  2753. !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, connection->charset))) {
  2754. return 1;
  2755. }
  2756. actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
  2757. connection->env = actual_spool->env;
  2758. /* Do this upfront so that connection close on an error would know that this is a session pool
  2759. * connection. Failure to do this would result in crashes in error scenarios
  2760. */
  2761. if (!connection->using_spool) {
  2762. connection->using_spool = 1;
  2763. }
  2764. #ifdef HAVE_OCI8_DTRACE
  2765. if (DTRACE_OCI8_SESSPOOL_TYPE_ENABLED()) {
  2766. DTRACE_OCI8_SESSPOOL_TYPE(session_pool ? 1 : 0, session_pool ? session_pool : connection->private_spool);
  2767. }
  2768. #endif /* HAVE_OCI8_DTRACE */
  2769. /* The passed in "connection" can be a cached stub from plist or freshly created. In the former
  2770. * case, we do not have to allocate any handles
  2771. */
  2772. if (!connection->err) {
  2773. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
  2774. if (OCI_G(errcode) != OCI_SUCCESS) {
  2775. php_oci_error(OCI_G(err), OCI_G(errcode));
  2776. return 1;
  2777. }
  2778. }
  2779. /* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
  2780. if (!connection->authinfo) {
  2781. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
  2782. if (OCI_G(errcode) != OCI_SUCCESS) {
  2783. php_oci_error(OCI_G(err), OCI_G(errcode));
  2784. return 1;
  2785. }
  2786. /* Set the Connection class and purity if OCI client version >= 11g */
  2787. #if (OCI_MAJOR_VERSION > 10)
  2788. 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)));
  2789. if (OCI_G(errcode) != OCI_SUCCESS) {
  2790. php_oci_error(OCI_G(err), OCI_G(errcode));
  2791. return 1;
  2792. }
  2793. if (connection->is_persistent)
  2794. purity = OCI_ATTR_PURITY_SELF;
  2795. else
  2796. purity = OCI_ATTR_PURITY_NEW;
  2797. 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)));
  2798. if (OCI_G(errcode) != OCI_SUCCESS) {
  2799. php_oci_error(OCI_G(err), OCI_G(errcode));
  2800. return 1;
  2801. }
  2802. #endif
  2803. }
  2804. /* }}} */
  2805. /* {{{ Debug statements */
  2806. #ifdef HAVE_OCI8_DTRACE
  2807. if (DTRACE_OCI8_SESSPOOL_STATS_ENABLED()) {
  2808. ub4 numfree = 0, numbusy = 0, numopen = 0;
  2809. 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)));
  2810. 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)));
  2811. numfree = numopen - numbusy; /* number of free connections in the pool */
  2812. DTRACE_OCI8_SESSPOOL_STATS(numfree, numbusy, numopen);
  2813. }
  2814. #endif /* HAVE_OCI8_DTRACE */
  2815. /* }}} */
  2816. /* Ping loop: Ping and loop till we get a good connection. When a database instance goes
  2817. * down, it can leave several bad connections that need to be flushed out before getting a
  2818. * good one. In non-RAC, we always get a brand new connection at the end of the loop and in
  2819. * RAC, we can get a good connection from a different instance before flushing out all bad
  2820. * ones. We do not need to ping brand new connections.
  2821. */
  2822. do {
  2823. /* Continue to use the global error handle as the connection is closed when an error occurs */
  2824. 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));
  2825. if (OCI_G(errcode) != OCI_SUCCESS) {
  2826. php_oci_error(OCI_G(err), OCI_G(errcode));
  2827. /* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
  2828. * is still usable.
  2829. */
  2830. if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
  2831. return 1;
  2832. }
  2833. }
  2834. /* {{{ Populate the session and server fields of the connection */
  2835. 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)));
  2836. 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)));
  2837. /* }}} */
  2838. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
  2839. if (OCI_G(errcode) != OCI_SUCCESS) {
  2840. php_oci_error(OCI_G(err), OCI_G(errcode));
  2841. return 1;
  2842. }
  2843. if (!(connection->next_pingp)){
  2844. /* This is a brand new connection, we need not ping, but have to initialize ping */
  2845. if (php_oci_ping_init(connection, OCI_G(err)) != OCI_SUCCESS) {
  2846. php_oci_error(OCI_G(err), OCI_G(errcode));
  2847. return 1;
  2848. }
  2849. } else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
  2850. if (php_oci_connection_ping(connection)) {
  2851. /* Got a good connection - update next_ping and get out of ping loop */
  2852. *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
  2853. } else {
  2854. /* Bad connection - remove from pool */
  2855. PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
  2856. connection->svc = NULL;
  2857. connection->server = NULL;
  2858. connection->session = NULL;
  2859. }
  2860. } /* If ping applicable */
  2861. } while (!(connection->svc));
  2862. 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)));
  2863. if (OCI_G(errcode) != OCI_SUCCESS) {
  2864. php_oci_error(OCI_G(err), OCI_G(errcode));
  2865. return 1;
  2866. }
  2867. /* Session is now taken from the session pool and attached and open */
  2868. connection->is_stub = 0;
  2869. connection->is_attached = connection->is_open = 1;
  2870. return 0;
  2871. }
  2872. /* }}} */
  2873. /* {{{ php_oci_spool_list_dtor()
  2874. *
  2875. * Session pool destructor function
  2876. */
  2877. static void php_oci_spool_list_dtor(zend_resource *entry)
  2878. {
  2879. php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
  2880. if (session_pool) {
  2881. php_oci_spool_close(session_pool);
  2882. }
  2883. return;
  2884. }
  2885. /* }}} */
  2886. /* {{{ php_oci_spool_close()
  2887. *
  2888. * Destroys the OCI Session Pool
  2889. */
  2890. static void php_oci_spool_close(php_oci_spool *session_pool)
  2891. {
  2892. if (session_pool->poolname_len) {
  2893. PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
  2894. (dvoid *) session_pool->err, OCI_SPD_FORCE));
  2895. }
  2896. if (session_pool->poolh) {
  2897. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
  2898. }
  2899. if (session_pool->err) {
  2900. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
  2901. }
  2902. if (session_pool->env) {
  2903. PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
  2904. }
  2905. if (session_pool->spool_hash_key) {
  2906. free(session_pool->spool_hash_key);
  2907. }
  2908. free(session_pool);
  2909. }
  2910. /* }}} */
  2911. /* {{{ php_oci_ping_init()
  2912. *
  2913. * Initializes the next_ping time as a context value in the connection. We now use
  2914. * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
  2915. * non-persistent DRCP connections
  2916. */
  2917. static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh)
  2918. {
  2919. time_t *next_pingp = NULL;
  2920. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
  2921. if (OCI_G(errcode) != OCI_SUCCESS) {
  2922. return OCI_G(errcode);
  2923. }
  2924. /* This must be a brand-new connection. Allocate memory for the ping */
  2925. if (!next_pingp) {
  2926. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
  2927. if (OCI_G(errcode) != OCI_SUCCESS) {
  2928. return OCI_G(errcode);
  2929. }
  2930. }
  2931. if (OCI_G(ping_interval) >= 0) {
  2932. time_t timestamp = time(NULL);
  2933. *next_pingp = timestamp + OCI_G(ping_interval);
  2934. } else {
  2935. *next_pingp = 0;
  2936. }
  2937. /* Set the new ping value into the connection */
  2938. PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
  2939. if (OCI_G(errcode) != OCI_SUCCESS) {
  2940. OCIMemoryFree(connection->session, errh, next_pingp);
  2941. return OCI_G(errcode);
  2942. }
  2943. /* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
  2944. connection->next_pingp = next_pingp;
  2945. return OCI_SUCCESS;
  2946. }
  2947. /* }}} */
  2948. /* {{{ php_oci_dtrace_check_connection()
  2949. *
  2950. * DTrace output for connections that may have become invalid and marked for reopening
  2951. */
  2952. void php_oci_dtrace_check_connection(php_oci_connection *connection, sb4 errcode, ub4 serverStatus)
  2953. {
  2954. #ifdef HAVE_OCI8_DTRACE
  2955. if (DTRACE_OCI8_CHECK_CONNECTION_ENABLED()) {
  2956. DTRACE_OCI8_CHECK_CONNECTION(connection, connection->client_id, connection->is_open ? 1 : 0, (long)errcode, (unsigned long)serverStatus);
  2957. }
  2958. #endif /* HAVE_OCI8_DTRACE */
  2959. }
  2960. /* }}} */
  2961. #endif /* HAVE_OCI8 */
  2962. /*
  2963. * Local variables:
  2964. * tab-width: 4
  2965. * c-basic-offset: 4
  2966. * End:
  2967. * vim600: noet sw=4 ts=4 fdm=marker
  2968. * vim<600: noet sw=4 ts=4
  2969. */