php_odbc.c 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893
  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. | Andreas Karajannis <Andreas.Karajannis@gmd.de> |
  17. | Frank M. Kromann <frank@kromann.info> Support for DB/2 CLI |
  18. | Kevin N. Shallow <kshallow@tampabay.rr.com> |
  19. | Daniel R. Kalowsky <kalowsky@php.net> |
  20. +----------------------------------------------------------------------+
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include "php.h"
  26. #include "php_globals.h"
  27. #include "ext/standard/info.h"
  28. #include "ext/standard/php_string.h"
  29. #include "ext/standard/php_standard.h"
  30. #include "php_odbc.h"
  31. #include "php_odbc_includes.h"
  32. #include "php_globals.h"
  33. #if HAVE_UODBC
  34. #include <fcntl.h>
  35. #include "ext/standard/head.h"
  36. #include "php_ini.h"
  37. #ifdef PHP_WIN32
  38. #include <winsock2.h>
  39. #define ODBC_TYPE "Win32"
  40. #define PHP_ODBC_TYPE ODBC_TYPE
  41. #endif
  42. /*
  43. * not defined elsewhere
  44. */
  45. #ifndef TRUE
  46. #define TRUE 1
  47. #define FALSE 0
  48. #endif
  49. void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent);
  50. static int le_result, le_conn, le_pconn;
  51. #define SAFE_SQL_NTS(n) ((SQLSMALLINT) ((n)?(SQL_NTS):0))
  52. /* {{{ arginfo */
  53. ZEND_BEGIN_ARG_INFO(arginfo_odbc_close_all, 0)
  54. ZEND_END_ARG_INFO()
  55. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_binmode, 0, 0, 2)
  56. ZEND_ARG_INFO(0, result_id)
  57. ZEND_ARG_INFO(0, mode)
  58. ZEND_END_ARG_INFO()
  59. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_longreadlen, 0, 0, 2)
  60. ZEND_ARG_INFO(0, result_id)
  61. ZEND_ARG_INFO(0, length)
  62. ZEND_END_ARG_INFO()
  63. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_prepare, 0, 0, 2)
  64. ZEND_ARG_INFO(0, connection_id)
  65. ZEND_ARG_INFO(0, query)
  66. ZEND_END_ARG_INFO()
  67. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_execute, 0, 0, 1)
  68. ZEND_ARG_INFO(0, result_id)
  69. ZEND_ARG_INFO(0, parameters_array)
  70. ZEND_END_ARG_INFO()
  71. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_cursor, 0, 0, 1)
  72. ZEND_ARG_INFO(0, result_id)
  73. ZEND_END_ARG_INFO()
  74. #ifdef HAVE_SQLDATASOURCES
  75. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_data_source, 0, 0, 2)
  76. ZEND_ARG_INFO(0, connection_id)
  77. ZEND_ARG_INFO(0, fetch_type)
  78. ZEND_END_ARG_INFO()
  79. #endif
  80. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_exec, 0, 0, 2)
  81. ZEND_ARG_INFO(0, connection_id)
  82. ZEND_ARG_INFO(0, query)
  83. ZEND_ARG_INFO(0, flags)
  84. ZEND_END_ARG_INFO()
  85. #ifdef PHP_ODBC_HAVE_FETCH_HASH
  86. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_object, 0, 0, 1)
  87. ZEND_ARG_INFO(0, result)
  88. ZEND_ARG_INFO(0, rownumber)
  89. ZEND_END_ARG_INFO()
  90. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_array, 0, 0, 1)
  91. ZEND_ARG_INFO(0, result)
  92. ZEND_ARG_INFO(0, rownumber)
  93. ZEND_END_ARG_INFO()
  94. #endif
  95. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_into, 0, 0, 2)
  96. ZEND_ARG_INFO(0, result_id)
  97. ZEND_ARG_INFO(1, result_array)
  98. ZEND_ARG_INFO(0, rownumber)
  99. ZEND_END_ARG_INFO()
  100. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_row, 0, 0, 1)
  101. ZEND_ARG_INFO(0, result_id)
  102. ZEND_ARG_INFO(0, row_number)
  103. ZEND_END_ARG_INFO()
  104. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result, 0, 0, 2)
  105. ZEND_ARG_INFO(0, result_id)
  106. ZEND_ARG_INFO(0, field)
  107. ZEND_END_ARG_INFO()
  108. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result_all, 0, 0, 1)
  109. ZEND_ARG_INFO(0, result_id)
  110. ZEND_ARG_INFO(0, format)
  111. ZEND_END_ARG_INFO()
  112. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_free_result, 0, 0, 1)
  113. ZEND_ARG_INFO(0, result_id)
  114. ZEND_END_ARG_INFO()
  115. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_connect, 0, 0, 3)
  116. ZEND_ARG_INFO(0, dsn)
  117. ZEND_ARG_INFO(0, user)
  118. ZEND_ARG_INFO(0, password)
  119. ZEND_ARG_INFO(0, cursor_option)
  120. ZEND_END_ARG_INFO()
  121. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_pconnect, 0, 0, 3)
  122. ZEND_ARG_INFO(0, dsn)
  123. ZEND_ARG_INFO(0, user)
  124. ZEND_ARG_INFO(0, password)
  125. ZEND_ARG_INFO(0, cursor_option)
  126. ZEND_END_ARG_INFO()
  127. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_close, 0, 0, 1)
  128. ZEND_ARG_INFO(0, connection_id)
  129. ZEND_END_ARG_INFO()
  130. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_rows, 0, 0, 1)
  131. ZEND_ARG_INFO(0, result_id)
  132. ZEND_END_ARG_INFO()
  133. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
  134. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_next_result, 0, 0, 1)
  135. ZEND_ARG_INFO(0, result_id)
  136. ZEND_END_ARG_INFO()
  137. #endif
  138. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_fields, 0, 0, 1)
  139. ZEND_ARG_INFO(0, result_id)
  140. ZEND_END_ARG_INFO()
  141. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_name, 0, 0, 2)
  142. ZEND_ARG_INFO(0, result_id)
  143. ZEND_ARG_INFO(0, field_number)
  144. ZEND_END_ARG_INFO()
  145. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_type, 0, 0, 2)
  146. ZEND_ARG_INFO(0, result_id)
  147. ZEND_ARG_INFO(0, field_number)
  148. ZEND_END_ARG_INFO()
  149. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_len, 0, 0, 2)
  150. ZEND_ARG_INFO(0, result_id)
  151. ZEND_ARG_INFO(0, field_number)
  152. ZEND_END_ARG_INFO()
  153. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_scale, 0, 0, 2)
  154. ZEND_ARG_INFO(0, result_id)
  155. ZEND_ARG_INFO(0, field_number)
  156. ZEND_END_ARG_INFO()
  157. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_num, 0, 0, 2)
  158. ZEND_ARG_INFO(0, result_id)
  159. ZEND_ARG_INFO(0, field_name)
  160. ZEND_END_ARG_INFO()
  161. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_autocommit, 0, 0, 1)
  162. ZEND_ARG_INFO(0, connection_id)
  163. ZEND_ARG_INFO(0, onoff)
  164. ZEND_END_ARG_INFO()
  165. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_commit, 0, 0, 1)
  166. ZEND_ARG_INFO(0, connection_id)
  167. ZEND_END_ARG_INFO()
  168. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_rollback, 0, 0, 1)
  169. ZEND_ARG_INFO(0, connection_id)
  170. ZEND_END_ARG_INFO()
  171. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_error, 0, 0, 0)
  172. ZEND_ARG_INFO(0, connection_id)
  173. ZEND_END_ARG_INFO()
  174. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_errormsg, 0, 0, 0)
  175. ZEND_ARG_INFO(0, connection_id)
  176. ZEND_END_ARG_INFO()
  177. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_setoption, 0, 0, 4)
  178. ZEND_ARG_INFO(0, conn_id)
  179. ZEND_ARG_INFO(0, which)
  180. ZEND_ARG_INFO(0, option)
  181. ZEND_ARG_INFO(0, value)
  182. ZEND_END_ARG_INFO()
  183. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_tables, 0, 0, 1)
  184. ZEND_ARG_INFO(0, connection_id)
  185. ZEND_ARG_INFO(0, qualifier)
  186. ZEND_ARG_INFO(0, owner)
  187. ZEND_ARG_INFO(0, name)
  188. ZEND_ARG_INFO(0, table_types)
  189. ZEND_END_ARG_INFO()
  190. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_columns, 0, 0, 1)
  191. ZEND_ARG_INFO(0, connection_id)
  192. ZEND_ARG_INFO(0, qualifier)
  193. ZEND_ARG_INFO(0, owner)
  194. ZEND_ARG_INFO(0, table_name)
  195. ZEND_ARG_INFO(0, column_name)
  196. ZEND_END_ARG_INFO()
  197. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_gettypeinfo, 0, 0, 1)
  198. ZEND_ARG_INFO(0, connection_id)
  199. ZEND_ARG_INFO(0, data_type)
  200. ZEND_END_ARG_INFO()
  201. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_primarykeys, 0, 0, 4)
  202. ZEND_ARG_INFO(0, connection_id)
  203. ZEND_ARG_INFO(0, qualifier)
  204. ZEND_ARG_INFO(0, owner)
  205. ZEND_ARG_INFO(0, table)
  206. ZEND_END_ARG_INFO()
  207. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  208. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_procedurecolumns, 0, 0, 1)
  209. ZEND_ARG_INFO(0, connection_id)
  210. ZEND_ARG_INFO(0, qualifier)
  211. ZEND_ARG_INFO(0, owner)
  212. ZEND_ARG_INFO(0, proc)
  213. ZEND_ARG_INFO(0, column)
  214. ZEND_END_ARG_INFO()
  215. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_procedures, 0, 0, 1)
  216. ZEND_ARG_INFO(0, connection_id)
  217. ZEND_ARG_INFO(0, qualifier)
  218. ZEND_ARG_INFO(0, owner)
  219. ZEND_ARG_INFO(0, name)
  220. ZEND_END_ARG_INFO()
  221. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_foreignkeys, 0, 0, 7)
  222. ZEND_ARG_INFO(0, connection_id)
  223. ZEND_ARG_INFO(0, pk_qualifier)
  224. ZEND_ARG_INFO(0, pk_owner)
  225. ZEND_ARG_INFO(0, pk_table)
  226. ZEND_ARG_INFO(0, fk_qualifier)
  227. ZEND_ARG_INFO(0, fk_owner)
  228. ZEND_ARG_INFO(0, fk_table)
  229. ZEND_END_ARG_INFO()
  230. #endif
  231. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_specialcolumns, 0, 0, 7)
  232. ZEND_ARG_INFO(0, connection_id)
  233. ZEND_ARG_INFO(0, type)
  234. ZEND_ARG_INFO(0, qualifier)
  235. ZEND_ARG_INFO(0, owner)
  236. ZEND_ARG_INFO(0, table)
  237. ZEND_ARG_INFO(0, scope)
  238. ZEND_ARG_INFO(0, nullable)
  239. ZEND_END_ARG_INFO()
  240. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_statistics, 0, 0, 6)
  241. ZEND_ARG_INFO(0, connection_id)
  242. ZEND_ARG_INFO(0, qualifier)
  243. ZEND_ARG_INFO(0, owner)
  244. ZEND_ARG_INFO(0, name)
  245. ZEND_ARG_INFO(0, unique)
  246. ZEND_ARG_INFO(0, accuracy)
  247. ZEND_END_ARG_INFO()
  248. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35)
  249. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_tableprivileges, 0, 0, 4)
  250. ZEND_ARG_INFO(0, connection_id)
  251. ZEND_ARG_INFO(0, qualifier)
  252. ZEND_ARG_INFO(0, owner)
  253. ZEND_ARG_INFO(0, name)
  254. ZEND_END_ARG_INFO()
  255. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_columnprivileges, 0, 0, 5)
  256. ZEND_ARG_INFO(0, connection_id)
  257. ZEND_ARG_INFO(0, catalog)
  258. ZEND_ARG_INFO(0, schema)
  259. ZEND_ARG_INFO(0, table)
  260. ZEND_ARG_INFO(0, column)
  261. ZEND_END_ARG_INFO()
  262. #endif
  263. /* }}} */
  264. /* {{{ odbc_functions[]
  265. */
  266. static const zend_function_entry odbc_functions[] = {
  267. PHP_FE(odbc_autocommit, arginfo_odbc_autocommit)
  268. PHP_FE(odbc_binmode, arginfo_odbc_binmode)
  269. PHP_FE(odbc_close, arginfo_odbc_close)
  270. PHP_FE(odbc_close_all, arginfo_odbc_close_all)
  271. PHP_FE(odbc_columns, arginfo_odbc_columns)
  272. PHP_FE(odbc_commit, arginfo_odbc_commit)
  273. PHP_FE(odbc_connect, arginfo_odbc_connect)
  274. PHP_FE(odbc_cursor, arginfo_odbc_cursor)
  275. #ifdef HAVE_SQLDATASOURCES
  276. PHP_FE(odbc_data_source, arginfo_odbc_data_source)
  277. #endif
  278. PHP_FE(odbc_execute, arginfo_odbc_execute)
  279. PHP_FE(odbc_error, arginfo_odbc_error)
  280. PHP_FE(odbc_errormsg, arginfo_odbc_errormsg)
  281. PHP_FE(odbc_exec, arginfo_odbc_exec)
  282. #ifdef PHP_ODBC_HAVE_FETCH_HASH
  283. PHP_FE(odbc_fetch_array, arginfo_odbc_fetch_array)
  284. PHP_FE(odbc_fetch_object, arginfo_odbc_fetch_object)
  285. #endif
  286. PHP_FE(odbc_fetch_row, arginfo_odbc_fetch_row)
  287. PHP_FE(odbc_fetch_into, arginfo_odbc_fetch_into)
  288. PHP_FE(odbc_field_len, arginfo_odbc_field_len)
  289. PHP_FE(odbc_field_scale, arginfo_odbc_field_scale)
  290. PHP_FE(odbc_field_name, arginfo_odbc_field_name)
  291. PHP_FE(odbc_field_type, arginfo_odbc_field_type)
  292. PHP_FE(odbc_field_num, arginfo_odbc_field_num)
  293. PHP_FE(odbc_free_result, arginfo_odbc_free_result)
  294. PHP_FE(odbc_gettypeinfo, arginfo_odbc_gettypeinfo)
  295. PHP_FE(odbc_longreadlen, arginfo_odbc_longreadlen)
  296. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
  297. PHP_FE(odbc_next_result, arginfo_odbc_next_result)
  298. #endif
  299. PHP_FE(odbc_num_fields, arginfo_odbc_num_fields)
  300. PHP_FE(odbc_num_rows, arginfo_odbc_num_rows)
  301. PHP_FE(odbc_pconnect, arginfo_odbc_pconnect)
  302. PHP_FE(odbc_prepare, arginfo_odbc_prepare)
  303. PHP_FE(odbc_result, arginfo_odbc_result)
  304. PHP_FE(odbc_result_all, arginfo_odbc_result_all)
  305. PHP_FE(odbc_rollback, arginfo_odbc_rollback)
  306. PHP_FE(odbc_setoption, arginfo_odbc_setoption)
  307. PHP_FE(odbc_specialcolumns, arginfo_odbc_specialcolumns)
  308. PHP_FE(odbc_statistics, arginfo_odbc_statistics)
  309. PHP_FE(odbc_tables, arginfo_odbc_tables)
  310. PHP_FE(odbc_primarykeys, arginfo_odbc_primarykeys)
  311. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) /* not supported now */
  312. PHP_FE(odbc_columnprivileges, arginfo_odbc_columnprivileges)
  313. PHP_FE(odbc_tableprivileges, arginfo_odbc_tableprivileges)
  314. #endif
  315. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* not supported */
  316. PHP_FE(odbc_foreignkeys, arginfo_odbc_foreignkeys)
  317. PHP_FE(odbc_procedures, arginfo_odbc_procedures)
  318. PHP_FE(odbc_procedurecolumns, arginfo_odbc_procedurecolumns)
  319. #endif
  320. PHP_FALIAS(odbc_do, odbc_exec, arginfo_odbc_exec)
  321. PHP_FALIAS(odbc_field_precision, odbc_field_len, arginfo_odbc_field_len)
  322. PHP_FE_END
  323. };
  324. /* }}} */
  325. PHP_ODBC_API ZEND_DECLARE_MODULE_GLOBALS(odbc)
  326. static PHP_GINIT_FUNCTION(odbc);
  327. /* {{{ odbc_module_entry
  328. */
  329. zend_module_entry odbc_module_entry = {
  330. STANDARD_MODULE_HEADER,
  331. "odbc",
  332. odbc_functions,
  333. PHP_MINIT(odbc),
  334. PHP_MSHUTDOWN(odbc),
  335. PHP_RINIT(odbc),
  336. PHP_RSHUTDOWN(odbc),
  337. PHP_MINFO(odbc),
  338. PHP_ODBC_VERSION,
  339. PHP_MODULE_GLOBALS(odbc),
  340. PHP_GINIT(odbc),
  341. NULL,
  342. NULL,
  343. STANDARD_MODULE_PROPERTIES_EX
  344. };
  345. /* }}} */
  346. #ifdef COMPILE_DL_ODBC
  347. #ifdef ZTS
  348. ZEND_TSRMLS_CACHE_DEFINE()
  349. #endif
  350. ZEND_GET_MODULE(odbc)
  351. #endif
  352. /* {{{ _free_odbc_result
  353. */
  354. static void _free_odbc_result(zend_resource *rsrc)
  355. {
  356. odbc_result *res = (odbc_result *)rsrc->ptr;
  357. int i;
  358. RETCODE rc;
  359. if (res) {
  360. if (res->values) {
  361. for(i = 0; i < res->numcols; i++) {
  362. if (res->values[i].value)
  363. efree(res->values[i].value);
  364. }
  365. efree(res->values);
  366. res->values = NULL;
  367. }
  368. /* If aborted via timer expiration, don't try to call any unixODBC function */
  369. if (res->stmt && !(PG(connection_status) & PHP_CONNECTION_TIMEOUT)) {
  370. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
  371. SQLTransact(res->conn_ptr->henv, res->conn_ptr->hdbc,
  372. (SQLUSMALLINT) SQL_COMMIT);
  373. #endif
  374. rc = SQLFreeStmt(res->stmt,SQL_DROP);
  375. /* We don't want the connection to be closed after the last statement has been closed
  376. * Connections will be closed on shutdown
  377. * zend_list_delete(res->conn_ptr->id);
  378. */
  379. }
  380. if (res->param_info) {
  381. efree(res->param_info);
  382. }
  383. efree(res);
  384. }
  385. }
  386. /* }}} */
  387. /* {{{ safe_odbc_disconnect
  388. * disconnect, and if it fails, then issue a rollback for any pending transaction (lurcher)
  389. */
  390. static void safe_odbc_disconnect( void *handle )
  391. {
  392. int ret;
  393. ret = SQLDisconnect( handle );
  394. if ( ret == SQL_ERROR )
  395. {
  396. SQLTransact( NULL, handle, SQL_ROLLBACK );
  397. SQLDisconnect( handle );
  398. }
  399. }
  400. /* }}} */
  401. /* {{{ _close_odbc_conn
  402. */
  403. static void _close_odbc_conn(zend_resource *rsrc)
  404. {
  405. zend_resource *p;
  406. odbc_result *res;
  407. odbc_connection *conn = (odbc_connection *)rsrc->ptr;
  408. ZEND_HASH_FOREACH_PTR(&EG(regular_list), p) {
  409. if (p->ptr && (p->type == le_result)) {
  410. res = (odbc_result *)p->ptr;
  411. if (res->conn_ptr == conn) {
  412. zend_list_close(p);
  413. }
  414. }
  415. } ZEND_HASH_FOREACH_END();
  416. /* If aborted via timer expiration, don't try to call any unixODBC function */
  417. if (!(PG(connection_status) & PHP_CONNECTION_TIMEOUT)) {
  418. safe_odbc_disconnect(conn->hdbc);
  419. SQLFreeConnect(conn->hdbc);
  420. SQLFreeEnv(conn->henv);
  421. }
  422. efree(conn);
  423. ODBCG(num_links)--;
  424. }
  425. /* }}} */
  426. /* {{{ void _close_odbc_pconn
  427. */
  428. static void _close_odbc_pconn(zend_resource *rsrc)
  429. {
  430. zend_resource *p;
  431. odbc_result *res;
  432. odbc_connection *conn = (odbc_connection *)rsrc->ptr;
  433. ZEND_HASH_FOREACH_PTR(&EG(regular_list), p) {
  434. if (p->ptr && (p->type == le_result)) {
  435. res = (odbc_result *)p->ptr;
  436. if (res->conn_ptr == conn) {
  437. zend_list_close(p);
  438. }
  439. }
  440. } ZEND_HASH_FOREACH_END();
  441. /* If aborted via timer expiration, don't try to call any unixODBC function */
  442. if (!(PG(connection_status) & PHP_CONNECTION_TIMEOUT)) {
  443. safe_odbc_disconnect(conn->hdbc);
  444. SQLFreeConnect(conn->hdbc);
  445. SQLFreeEnv(conn->henv);
  446. }
  447. free(conn);
  448. ODBCG(num_links)--;
  449. ODBCG(num_persistent)--;
  450. }
  451. /* }}} */
  452. /* {{{ PHP_INI_DISP(display_link_nums)
  453. */
  454. static PHP_INI_DISP(display_link_nums)
  455. {
  456. char *value;
  457. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  458. value = ZSTR_VAL(ini_entry->orig_value);
  459. } else if (ini_entry->value) {
  460. value = ZSTR_VAL(ini_entry->value);
  461. } else {
  462. value = NULL;
  463. }
  464. if (value) {
  465. if (atoi(value) == -1) {
  466. PUTS("Unlimited");
  467. } else {
  468. php_printf("%s", value);
  469. }
  470. }
  471. }
  472. /* }}} */
  473. /* {{{ PHP_INI_DISP(display_defPW)
  474. */
  475. static PHP_INI_DISP(display_defPW)
  476. {
  477. char *value;
  478. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  479. value = ZSTR_VAL(ini_entry->orig_value);
  480. } else if (ini_entry->value) {
  481. value = ZSTR_VAL(ini_entry->value);
  482. } else {
  483. value = NULL;
  484. }
  485. if (value) {
  486. #if PHP_DEBUG
  487. php_printf("%s", value);
  488. #else
  489. PUTS("********");
  490. #endif
  491. } else {
  492. if (PG(html_errors)) {
  493. PUTS("<i>no value</i>");
  494. } else {
  495. PUTS("no value");
  496. }
  497. }
  498. }
  499. /* }}} */
  500. /* {{{ PHP_INI_DISP(display_binmode)
  501. */
  502. static PHP_INI_DISP(display_binmode)
  503. {
  504. char *value;
  505. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  506. value = ZSTR_VAL(ini_entry->orig_value);
  507. } else if (ini_entry->value) {
  508. value = ZSTR_VAL(ini_entry->value);
  509. } else {
  510. value = NULL;
  511. }
  512. if (value) {
  513. switch(atoi(value)) {
  514. case 0:
  515. PUTS("passthru");
  516. break;
  517. case 1:
  518. PUTS("return as is");
  519. break;
  520. case 2:
  521. PUTS("return as char");
  522. break;
  523. }
  524. }
  525. }
  526. /* }}} */
  527. /* {{{ PHP_INI_DISP(display_lrl)
  528. */
  529. static PHP_INI_DISP(display_lrl)
  530. {
  531. char *value;
  532. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  533. value = ZSTR_VAL(ini_entry->orig_value);
  534. } else if (ini_entry->value) {
  535. value = ZSTR_VAL(ini_entry->value);
  536. } else {
  537. value = NULL;
  538. }
  539. if (value) {
  540. if (atoi(value) <= 0) {
  541. PUTS("Passthru");
  542. } else {
  543. php_printf("return up to %s bytes", value);
  544. }
  545. }
  546. }
  547. /* }}} */
  548. /* {{{ PHP_INI_DISP(display_cursortype)
  549. */
  550. static PHP_INI_DISP(display_cursortype)
  551. {
  552. char *value;
  553. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  554. value = ZSTR_VAL(ini_entry->orig_value);
  555. } else if (ini_entry->value) {
  556. value = ZSTR_VAL(ini_entry->value);
  557. } else {
  558. value = NULL;
  559. }
  560. if (value) {
  561. switch (atoi (value))
  562. {
  563. case SQL_CURSOR_FORWARD_ONLY:
  564. PUTS ("Forward Only cursor");
  565. break;
  566. case SQL_CURSOR_STATIC:
  567. PUTS ("Static cursor");
  568. break;
  569. case SQL_CURSOR_KEYSET_DRIVEN:
  570. PUTS ("Keyset driven cursor");
  571. break;
  572. case SQL_CURSOR_DYNAMIC:
  573. PUTS ("Dynamic cursor");
  574. break;
  575. default:
  576. php_printf("Unknown cursor model %s", value);
  577. break;
  578. }
  579. }
  580. }
  581. /* }}} */
  582. /* {{{ PHP_INI_BEGIN
  583. */
  584. PHP_INI_BEGIN()
  585. STD_PHP_INI_BOOLEAN("odbc.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong,
  586. allow_persistent, zend_odbc_globals, odbc_globals)
  587. STD_PHP_INI_ENTRY_EX("odbc.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong,
  588. max_persistent, zend_odbc_globals, odbc_globals, display_link_nums)
  589. STD_PHP_INI_ENTRY_EX("odbc.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong,
  590. max_links, zend_odbc_globals, odbc_globals, display_link_nums)
  591. STD_PHP_INI_ENTRY("odbc.default_db", NULL, PHP_INI_ALL, OnUpdateString,
  592. defDB, zend_odbc_globals, odbc_globals)
  593. STD_PHP_INI_ENTRY("odbc.default_user", NULL, PHP_INI_ALL, OnUpdateString,
  594. defUser, zend_odbc_globals, odbc_globals)
  595. STD_PHP_INI_ENTRY_EX("odbc.default_pw", NULL, PHP_INI_ALL, OnUpdateString,
  596. defPW, zend_odbc_globals, odbc_globals, display_defPW)
  597. STD_PHP_INI_ENTRY_EX("odbc.defaultlrl", "4096", PHP_INI_ALL, OnUpdateLong,
  598. defaultlrl, zend_odbc_globals, odbc_globals, display_lrl)
  599. STD_PHP_INI_ENTRY_EX("odbc.defaultbinmode", "1", PHP_INI_ALL, OnUpdateLong,
  600. defaultbinmode, zend_odbc_globals, odbc_globals, display_binmode)
  601. STD_PHP_INI_BOOLEAN("odbc.check_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong,
  602. check_persistent, zend_odbc_globals, odbc_globals)
  603. STD_PHP_INI_ENTRY_EX("odbc.default_cursortype", "3", PHP_INI_ALL, OnUpdateLong,
  604. default_cursortype, zend_odbc_globals, odbc_globals, display_cursortype)
  605. PHP_INI_END()
  606. /* }}} */
  607. static PHP_GINIT_FUNCTION(odbc)
  608. {
  609. #if defined(COMPILE_DL_ODBC) && defined(ZTS)
  610. ZEND_TSRMLS_CACHE_UPDATE();
  611. #endif
  612. odbc_globals->num_persistent = 0;
  613. }
  614. /* {{{ PHP_MINIT_FUNCTION */
  615. PHP_MINIT_FUNCTION(odbc)
  616. {
  617. #ifdef SQLANY_BUG
  618. ODBC_SQL_CONN_T foobar;
  619. RETCODE rc;
  620. #endif
  621. REGISTER_INI_ENTRIES();
  622. le_result = zend_register_list_destructors_ex(_free_odbc_result, NULL, "odbc result", module_number);
  623. le_conn = zend_register_list_destructors_ex(_close_odbc_conn, NULL, "odbc link", module_number);
  624. le_pconn = zend_register_list_destructors_ex(NULL, _close_odbc_pconn, "odbc link persistent", module_number);
  625. odbc_module_entry.type = type;
  626. REGISTER_STRING_CONSTANT("ODBC_TYPE", PHP_ODBC_TYPE, CONST_CS | CONST_PERSISTENT);
  627. REGISTER_LONG_CONSTANT("ODBC_BINMODE_PASSTHRU", 0, CONST_CS | CONST_PERSISTENT);
  628. REGISTER_LONG_CONSTANT("ODBC_BINMODE_RETURN", 1, CONST_CS | CONST_PERSISTENT);
  629. REGISTER_LONG_CONSTANT("ODBC_BINMODE_CONVERT", 2, CONST_CS | CONST_PERSISTENT);
  630. /* Define Constants for options
  631. these Constants are defined in <sqlext.h>
  632. */
  633. REGISTER_LONG_CONSTANT("SQL_ODBC_CURSORS", SQL_ODBC_CURSORS, CONST_PERSISTENT | CONST_CS);
  634. REGISTER_LONG_CONSTANT("SQL_CUR_USE_DRIVER", SQL_CUR_USE_DRIVER, CONST_PERSISTENT | CONST_CS);
  635. REGISTER_LONG_CONSTANT("SQL_CUR_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED, CONST_PERSISTENT | CONST_CS);
  636. REGISTER_LONG_CONSTANT("SQL_CUR_USE_ODBC", SQL_CUR_USE_ODBC, CONST_PERSISTENT | CONST_CS);
  637. REGISTER_LONG_CONSTANT("SQL_CONCURRENCY", SQL_CONCURRENCY, CONST_PERSISTENT | CONST_CS);
  638. REGISTER_LONG_CONSTANT("SQL_CONCUR_READ_ONLY", SQL_CONCUR_READ_ONLY, CONST_PERSISTENT | CONST_CS);
  639. REGISTER_LONG_CONSTANT("SQL_CONCUR_LOCK", SQL_CONCUR_LOCK, CONST_PERSISTENT | CONST_CS);
  640. REGISTER_LONG_CONSTANT("SQL_CONCUR_ROWVER", SQL_CONCUR_ROWVER, CONST_PERSISTENT | CONST_CS);
  641. REGISTER_LONG_CONSTANT("SQL_CONCUR_VALUES", SQL_CONCUR_VALUES, CONST_PERSISTENT | CONST_CS);
  642. REGISTER_LONG_CONSTANT("SQL_CURSOR_TYPE", SQL_CURSOR_TYPE, CONST_PERSISTENT | CONST_CS);
  643. REGISTER_LONG_CONSTANT("SQL_CURSOR_FORWARD_ONLY", SQL_CURSOR_FORWARD_ONLY, CONST_PERSISTENT | CONST_CS);
  644. REGISTER_LONG_CONSTANT("SQL_CURSOR_KEYSET_DRIVEN", SQL_CURSOR_KEYSET_DRIVEN, CONST_PERSISTENT | CONST_CS);
  645. REGISTER_LONG_CONSTANT("SQL_CURSOR_DYNAMIC", SQL_CURSOR_DYNAMIC, CONST_PERSISTENT | CONST_CS);
  646. REGISTER_LONG_CONSTANT("SQL_CURSOR_STATIC", SQL_CURSOR_STATIC, CONST_PERSISTENT | CONST_CS);
  647. REGISTER_LONG_CONSTANT("SQL_KEYSET_SIZE", SQL_KEYSET_SIZE, CONST_PERSISTENT | CONST_CS);
  648. /* these are for the Data Source type */
  649. REGISTER_LONG_CONSTANT("SQL_FETCH_FIRST", SQL_FETCH_FIRST, CONST_PERSISTENT | CONST_CS);
  650. REGISTER_LONG_CONSTANT("SQL_FETCH_NEXT", SQL_FETCH_NEXT, CONST_PERSISTENT | CONST_CS);
  651. /*
  652. * register the standard data types
  653. */
  654. REGISTER_LONG_CONSTANT("SQL_CHAR", SQL_CHAR, CONST_PERSISTENT | CONST_CS);
  655. REGISTER_LONG_CONSTANT("SQL_VARCHAR", SQL_VARCHAR, CONST_PERSISTENT | CONST_CS);
  656. REGISTER_LONG_CONSTANT("SQL_LONGVARCHAR", SQL_LONGVARCHAR, CONST_PERSISTENT | CONST_CS);
  657. REGISTER_LONG_CONSTANT("SQL_DECIMAL", SQL_DECIMAL, CONST_PERSISTENT | CONST_CS);
  658. REGISTER_LONG_CONSTANT("SQL_NUMERIC", SQL_NUMERIC, CONST_PERSISTENT | CONST_CS);
  659. REGISTER_LONG_CONSTANT("SQL_BIT", SQL_BIT, CONST_PERSISTENT | CONST_CS);
  660. REGISTER_LONG_CONSTANT("SQL_TINYINT", SQL_TINYINT, CONST_PERSISTENT | CONST_CS);
  661. REGISTER_LONG_CONSTANT("SQL_SMALLINT", SQL_SMALLINT, CONST_PERSISTENT | CONST_CS);
  662. REGISTER_LONG_CONSTANT("SQL_INTEGER", SQL_INTEGER, CONST_PERSISTENT | CONST_CS);
  663. REGISTER_LONG_CONSTANT("SQL_BIGINT", SQL_BIGINT, CONST_PERSISTENT | CONST_CS);
  664. REGISTER_LONG_CONSTANT("SQL_REAL", SQL_REAL, CONST_PERSISTENT | CONST_CS);
  665. REGISTER_LONG_CONSTANT("SQL_FLOAT", SQL_FLOAT, CONST_PERSISTENT | CONST_CS);
  666. REGISTER_LONG_CONSTANT("SQL_DOUBLE", SQL_DOUBLE, CONST_PERSISTENT | CONST_CS);
  667. REGISTER_LONG_CONSTANT("SQL_BINARY", SQL_BINARY, CONST_PERSISTENT | CONST_CS);
  668. REGISTER_LONG_CONSTANT("SQL_VARBINARY", SQL_VARBINARY, CONST_PERSISTENT | CONST_CS);
  669. REGISTER_LONG_CONSTANT("SQL_LONGVARBINARY", SQL_LONGVARBINARY, CONST_PERSISTENT | CONST_CS);
  670. REGISTER_LONG_CONSTANT("SQL_DATE", SQL_DATE, CONST_PERSISTENT | CONST_CS);
  671. REGISTER_LONG_CONSTANT("SQL_TIME", SQL_TIME, CONST_PERSISTENT | CONST_CS);
  672. REGISTER_LONG_CONSTANT("SQL_TIMESTAMP", SQL_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
  673. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  674. REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT | CONST_CS);
  675. REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT | CONST_CS);
  676. REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
  677. REGISTER_LONG_CONSTANT("SQL_WCHAR", SQL_WCHAR, CONST_PERSISTENT | CONST_CS);
  678. REGISTER_LONG_CONSTANT("SQL_WVARCHAR", SQL_WVARCHAR, CONST_PERSISTENT | CONST_CS);
  679. REGISTER_LONG_CONSTANT("SQL_WLONGVARCHAR", SQL_WLONGVARCHAR, CONST_PERSISTENT | CONST_CS);
  680. /*
  681. * SQLSpecialColumns values
  682. */
  683. REGISTER_LONG_CONSTANT("SQL_BEST_ROWID", SQL_BEST_ROWID, CONST_PERSISTENT | CONST_CS);
  684. REGISTER_LONG_CONSTANT("SQL_ROWVER", SQL_ROWVER, CONST_PERSISTENT | CONST_CS);
  685. REGISTER_LONG_CONSTANT("SQL_SCOPE_CURROW", SQL_SCOPE_CURROW, CONST_PERSISTENT | CONST_CS);
  686. REGISTER_LONG_CONSTANT("SQL_SCOPE_TRANSACTION", SQL_SCOPE_TRANSACTION, CONST_PERSISTENT | CONST_CS);
  687. REGISTER_LONG_CONSTANT("SQL_SCOPE_SESSION", SQL_SCOPE_SESSION, CONST_PERSISTENT | CONST_CS);
  688. REGISTER_LONG_CONSTANT("SQL_NO_NULLS", SQL_NO_NULLS, CONST_PERSISTENT | CONST_CS);
  689. REGISTER_LONG_CONSTANT("SQL_NULLABLE", SQL_NULLABLE, CONST_PERSISTENT | CONST_CS);
  690. /*
  691. * SQLStatistics values
  692. */
  693. REGISTER_LONG_CONSTANT("SQL_INDEX_UNIQUE", SQL_INDEX_UNIQUE, CONST_PERSISTENT | CONST_CS);
  694. REGISTER_LONG_CONSTANT("SQL_INDEX_ALL", SQL_INDEX_ALL, CONST_PERSISTENT | CONST_CS);
  695. REGISTER_LONG_CONSTANT("SQL_ENSURE", SQL_ENSURE, CONST_PERSISTENT | CONST_CS);
  696. REGISTER_LONG_CONSTANT("SQL_QUICK", SQL_QUICK, CONST_PERSISTENT | CONST_CS);
  697. #endif
  698. #if defined(HAVE_IBMDB2) && defined(_AIX)
  699. /* atexit() handler in the DB2/AIX library segfaults in PHP CLI */
  700. /* DB2NOEXITLIST env variable prevents DB2 from invoking atexit() */
  701. putenv("DB2NOEXITLIST=TRUE");
  702. #endif
  703. return SUCCESS;
  704. }
  705. /* }}} */
  706. /* {{{ PHP_RINIT_FUNCTION */
  707. PHP_RINIT_FUNCTION(odbc)
  708. {
  709. ODBCG(defConn) = -1;
  710. ODBCG(num_links) = ODBCG(num_persistent);
  711. memset(ODBCG(laststate), '\0', 6);
  712. memset(ODBCG(lasterrormsg), '\0', SQL_MAX_MESSAGE_LENGTH);
  713. return SUCCESS;
  714. }
  715. /* }}} */
  716. /* {{{ PHP_RSHUTDOWN_FUNCTION */
  717. PHP_RSHUTDOWN_FUNCTION(odbc)
  718. {
  719. return SUCCESS;
  720. }
  721. /* }}} */
  722. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  723. PHP_MSHUTDOWN_FUNCTION(odbc)
  724. {
  725. UNREGISTER_INI_ENTRIES();
  726. return SUCCESS;
  727. }
  728. /* }}} */
  729. /* {{{ PHP_MINFO_FUNCTION */
  730. PHP_MINFO_FUNCTION(odbc)
  731. {
  732. char buf[32];
  733. php_info_print_table_start();
  734. php_info_print_table_header(2, "ODBC Support", "enabled");
  735. snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ODBCG(num_persistent));
  736. php_info_print_table_row(2, "Active Persistent Links", buf);
  737. snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ODBCG(num_links));
  738. php_info_print_table_row(2, "Active Links", buf);
  739. php_info_print_table_row(2, "ODBC library", PHP_ODBC_TYPE);
  740. #ifdef ODBCVER
  741. snprintf(buf, sizeof(buf), "0x%0.4x", ODBCVER);
  742. php_info_print_table_row(2, "ODBCVER", buf);
  743. #endif
  744. #ifndef PHP_WIN32
  745. php_info_print_table_row(2, "ODBC_INCLUDE", PHP_ODBC_INCLUDE);
  746. php_info_print_table_row(2, "ODBC_LFLAGS", PHP_ODBC_LFLAGS);
  747. php_info_print_table_row(2, "ODBC_LIBS", PHP_ODBC_LIBS);
  748. #endif
  749. php_info_print_table_end();
  750. DISPLAY_INI_ENTRIES();
  751. }
  752. /* }}} */
  753. /* {{{ odbc_sql_error */
  754. void odbc_sql_error(ODBC_SQL_ERROR_PARAMS)
  755. {
  756. SQLINTEGER error; /* Not used */
  757. SQLSMALLINT errormsgsize; /* Not used */
  758. RETCODE rc;
  759. ODBC_SQL_ENV_T henv;
  760. ODBC_SQL_CONN_T conn;
  761. if (conn_resource) {
  762. henv = conn_resource->henv;
  763. conn = conn_resource->hdbc;
  764. } else {
  765. henv = SQL_NULL_HENV;
  766. conn = SQL_NULL_HDBC;
  767. }
  768. /* This leads to an endless loop in many drivers!
  769. *
  770. while(henv != SQL_NULL_HENV){
  771. do {
  772. */
  773. rc = SQLError(henv, conn, stmt, ODBCG(laststate), &error, ODBCG(lasterrormsg), sizeof(ODBCG(lasterrormsg))-1, &errormsgsize);
  774. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  775. snprintf(ODBCG(laststate), sizeof(ODBCG(laststate)), "HY000");
  776. snprintf(ODBCG(lasterrormsg), sizeof(ODBCG(lasterrormsg)), "Failed to fetch error message");
  777. }
  778. if (conn_resource) {
  779. memcpy(conn_resource->laststate, ODBCG(laststate), sizeof(ODBCG(laststate)));
  780. memcpy(conn_resource->lasterrormsg, ODBCG(lasterrormsg), sizeof(ODBCG(lasterrormsg)));
  781. }
  782. if (func) {
  783. php_error_docref(NULL, E_WARNING, "SQL error: %s, SQL state %s in %s", ODBCG(lasterrormsg), ODBCG(laststate), func);
  784. } else {
  785. php_error_docref(NULL, E_WARNING, "SQL error: %s, SQL state %s", ODBCG(lasterrormsg), ODBCG(laststate));
  786. }
  787. /*
  788. } while (SQL_SUCCEEDED(rc));
  789. }
  790. */
  791. }
  792. /* }}} */
  793. /* {{{ php_odbc_fetch_attribs */
  794. void php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode)
  795. {
  796. odbc_result *result;
  797. zval *pv_res;
  798. zend_long flag;
  799. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &pv_res, &flag) == FAILURE) {
  800. return;
  801. }
  802. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  803. RETURN_FALSE;
  804. }
  805. if (mode) {
  806. result->longreadlen = flag;
  807. } else {
  808. result->binmode = flag;
  809. }
  810. RETURN_TRUE;
  811. }
  812. /* }}} */
  813. /* {{{ odbc_bindcols */
  814. int odbc_bindcols(odbc_result *result)
  815. {
  816. RETCODE rc;
  817. int i;
  818. SQLSMALLINT colnamelen; /* Not used */
  819. SQLLEN displaysize;
  820. SQLUSMALLINT colfieldid;
  821. int charextraalloc;
  822. result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0);
  823. result->longreadlen = ODBCG(defaultlrl);
  824. result->binmode = ODBCG(defaultbinmode);
  825. for(i = 0; i < result->numcols; i++) {
  826. charextraalloc = 0;
  827. colfieldid = SQL_COLUMN_DISPLAY_SIZE;
  828. rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), PHP_ODBC_SQL_DESC_NAME,
  829. result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0);
  830. rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE,
  831. NULL, 0, NULL, &result->values[i].coltype);
  832. /* Don't bind LONG / BINARY columns, so that fetch behaviour can
  833. * be controlled by odbc_binmode() / odbc_longreadlen()
  834. */
  835. switch(result->values[i].coltype) {
  836. case SQL_BINARY:
  837. case SQL_VARBINARY:
  838. case SQL_LONGVARBINARY:
  839. case SQL_LONGVARCHAR:
  840. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  841. case SQL_WLONGVARCHAR:
  842. #endif
  843. result->values[i].value = NULL;
  844. break;
  845. #ifdef HAVE_ADABAS
  846. case SQL_TIMESTAMP:
  847. result->values[i].value = (char *)emalloc(27);
  848. SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
  849. 27, &result->values[i].vallen);
  850. break;
  851. #endif /* HAVE_ADABAS */
  852. case SQL_CHAR:
  853. case SQL_VARCHAR:
  854. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  855. case SQL_WCHAR:
  856. case SQL_WVARCHAR:
  857. colfieldid = SQL_DESC_OCTET_LENGTH;
  858. #else
  859. charextraalloc = 1;
  860. #endif
  861. default:
  862. rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), colfieldid,
  863. NULL, 0, NULL, &displaysize);
  864. if (rc != SQL_SUCCESS) {
  865. displaysize = 0;
  866. }
  867. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  868. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && colfieldid == SQL_DESC_OCTET_LENGTH) {
  869. SQLINTEGER err;
  870. SQLCHAR errtxt[128];
  871. SQLCHAR state[6];
  872. memset(errtxt, '\0', 128);
  873. memset(state, '\0', 6);
  874. if (SQL_SUCCESS == SQLGetDiagRec(SQL_HANDLE_STMT, result->stmt, 1, state, &err, errtxt, 128, NULL)) {
  875. errtxt[127] = '\0';
  876. state[5] = '\0';
  877. php_error_docref(NULL, E_WARNING, "SQLColAttribute can't handle SQL_DESC_OCTET_LENGTH: [%s] %s", state, errtxt);
  878. }
  879. /* This is a quirk for ODBC 2.0 compatibility for broken driver implementations.
  880. */
  881. charextraalloc = 1;
  882. rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_DISPLAY_SIZE,
  883. NULL, 0, NULL, &displaysize);
  884. if (rc != SQL_SUCCESS) {
  885. displaysize = 0;
  886. }
  887. }
  888. /* Workaround for drivers that report NVARCHAR(MAX) columns as SQL_WVARCHAR with size 0 (bug #69975) */
  889. if (result->values[i].coltype == SQL_WVARCHAR && displaysize == 0) {
  890. result->values[i].coltype = SQL_WLONGVARCHAR;
  891. result->values[i].value = NULL;
  892. break;
  893. }
  894. #endif
  895. /* Workaround for drivers that report VARCHAR(MAX) columns as SQL_VARCHAR (bug #73725) */
  896. if (SQL_VARCHAR == result->values[i].coltype && displaysize == 0) {
  897. result->values[i].coltype = SQL_LONGVARCHAR;
  898. result->values[i].value = NULL;
  899. break;
  900. }
  901. /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
  902. if (result->values[i].coltype == SQL_TIMESTAMP) {
  903. displaysize += 3;
  904. }
  905. if (charextraalloc) {
  906. /* Since we don't know the exact # of bytes, allocate extra */
  907. displaysize *= 4;
  908. }
  909. result->values[i].value = (char *)emalloc(displaysize + 1);
  910. rc = SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
  911. displaysize + 1, &result->values[i].vallen);
  912. break;
  913. }
  914. }
  915. return 1;
  916. }
  917. /* }}} */
  918. /* {{{ odbc_transact */
  919. void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
  920. {
  921. odbc_connection *conn;
  922. RETCODE rc;
  923. zval *pv_conn;
  924. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_conn) == FAILURE) {
  925. return;
  926. }
  927. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  928. RETURN_FALSE;
  929. }
  930. rc = SQLTransact(conn->henv, conn->hdbc, (SQLUSMALLINT)((type)?SQL_COMMIT:SQL_ROLLBACK));
  931. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  932. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTransact");
  933. RETURN_FALSE;
  934. }
  935. RETURN_TRUE;
  936. }
  937. /* }}} */
  938. /* {{{ _close_pconn_with_res */
  939. static int _close_pconn_with_res(zend_resource *le, zend_resource *res)
  940. {
  941. if (le->type == le_pconn && (((odbc_connection *)(le->ptr))->res == res)){
  942. return 1;
  943. }else{
  944. return 0;
  945. }
  946. }
  947. /* }}} */
  948. /* {{{ odbc_column_lengths */
  949. void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
  950. {
  951. odbc_result *result;
  952. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
  953. /* this seems to be necessary for Solid2.3 ( tested by
  954. * tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl)
  955. * Solid does not seem to declare a SQLINTEGER, but it does declare a
  956. * SQL_INTEGER which does not work (despite being the same type as a SDWORD.
  957. * Solid 3.5 does not have this issue.
  958. */
  959. SDWORD len;
  960. #else
  961. SQLLEN len;
  962. #endif
  963. zval *pv_res;
  964. zend_long pv_num;
  965. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &pv_res, &pv_num) == FAILURE) {
  966. return;
  967. }
  968. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  969. RETURN_FALSE;
  970. }
  971. if (result->numcols == 0) {
  972. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  973. RETURN_FALSE;
  974. }
  975. if (pv_num > result->numcols) {
  976. php_error_docref(NULL, E_WARNING, "Field index larger than number of fields");
  977. RETURN_FALSE;
  978. }
  979. if (pv_num < 1) {
  980. php_error_docref(NULL, E_WARNING, "Field numbering starts at 1");
  981. RETURN_FALSE;
  982. }
  983. PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
  984. RETURN_LONG(len);
  985. }
  986. /* }}} */
  987. /* Main User Functions */
  988. /* {{{ proto void odbc_close_all(void)
  989. Close all ODBC connections */
  990. PHP_FUNCTION(odbc_close_all)
  991. {
  992. zend_resource *p;
  993. if (zend_parse_parameters_none() == FAILURE) {
  994. return;
  995. }
  996. /* Loop through list and close all statements */
  997. ZEND_HASH_FOREACH_PTR(&EG(regular_list), p) {
  998. if (p->ptr && (p->type == le_result)) {
  999. zend_list_close(p);
  1000. }
  1001. } ZEND_HASH_FOREACH_END();
  1002. /* Second loop through list, now close all connections */
  1003. ZEND_HASH_FOREACH_PTR(&EG(regular_list), p) {
  1004. if (p->ptr) {
  1005. if (p->type == le_conn){
  1006. zend_list_close(p);
  1007. } else if (p->type == le_pconn){
  1008. zend_list_close(p);
  1009. /* Delete the persistent connection */
  1010. zend_hash_apply_with_argument(&EG(persistent_list),
  1011. (apply_func_arg_t) _close_pconn_with_res, (void *)p);
  1012. }
  1013. }
  1014. } ZEND_HASH_FOREACH_END();
  1015. }
  1016. /* }}} */
  1017. /* {{{ proto bool odbc_binmode(int result_id, int mode)
  1018. Handle binary column data */
  1019. PHP_FUNCTION(odbc_binmode)
  1020. {
  1021. php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  1022. }
  1023. /* }}} */
  1024. /* {{{ proto bool odbc_longreadlen(int result_id, int length)
  1025. Handle LONG columns */
  1026. PHP_FUNCTION(odbc_longreadlen)
  1027. {
  1028. php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1029. }
  1030. /* }}} */
  1031. /* {{{ proto resource odbc_prepare(resource connection_id, string query)
  1032. Prepares a statement for execution */
  1033. PHP_FUNCTION(odbc_prepare)
  1034. {
  1035. zval *pv_conn;
  1036. char *query;
  1037. size_t query_len;
  1038. odbc_result *result = NULL;
  1039. odbc_connection *conn;
  1040. RETCODE rc;
  1041. int i;
  1042. #ifdef HAVE_SQL_EXTENDED_FETCH
  1043. SQLUINTEGER scrollopts;
  1044. #endif
  1045. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &pv_conn, &query, &query_len) == FAILURE) {
  1046. return;
  1047. }
  1048. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  1049. RETURN_FALSE;
  1050. }
  1051. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  1052. result->numparams = 0;
  1053. result->param_info = NULL;
  1054. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  1055. if (rc == SQL_INVALID_HANDLE) {
  1056. efree(result);
  1057. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  1058. RETURN_FALSE;
  1059. }
  1060. if (rc == SQL_ERROR) {
  1061. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  1062. efree(result);
  1063. RETURN_FALSE;
  1064. }
  1065. #ifdef HAVE_SQL_EXTENDED_FETCH
  1066. /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
  1067. whether Driver supports ExtendedFetch */
  1068. rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
  1069. if (rc == SQL_SUCCESS) {
  1070. if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
  1071. /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
  1072. type if not possible.
  1073. */
  1074. SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
  1075. }
  1076. } else {
  1077. result->fetch_abs = 0;
  1078. }
  1079. #endif
  1080. rc = SQLPrepare(result->stmt, query, SQL_NTS);
  1081. switch (rc) {
  1082. case SQL_SUCCESS:
  1083. break;
  1084. case SQL_SUCCESS_WITH_INFO:
  1085. odbc_sql_error(conn, result->stmt, "SQLPrepare");
  1086. break;
  1087. default:
  1088. odbc_sql_error(conn, result->stmt, "SQLPrepare");
  1089. RETURN_FALSE;
  1090. }
  1091. SQLNumParams(result->stmt, &(result->numparams));
  1092. SQLNumResultCols(result->stmt, &(result->numcols));
  1093. if (result->numcols > 0) {
  1094. if (!odbc_bindcols(result)) {
  1095. efree(result);
  1096. RETURN_FALSE;
  1097. }
  1098. } else {
  1099. result->values = NULL;
  1100. }
  1101. Z_ADDREF_P(pv_conn);
  1102. result->conn_ptr = conn;
  1103. result->fetched = 0;
  1104. result->param_info = (odbc_param_info *) safe_emalloc(sizeof(odbc_param_info), result->numparams, 0);
  1105. for (i=0;i<result->numparams;i++) {
  1106. rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)(i+1), &result->param_info[i].sqltype, &result->param_info[i].precision,
  1107. &result->param_info[i].scale, &result->param_info[i].nullable);
  1108. if (rc == SQL_ERROR) {
  1109. odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter");
  1110. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1111. efree(result->param_info);
  1112. efree(result);
  1113. RETURN_FALSE;
  1114. }
  1115. }
  1116. RETURN_RES(zend_register_resource(result, le_result));
  1117. }
  1118. /* }}} */
  1119. /*
  1120. * Execute prepared SQL statement. Supports only input parameters.
  1121. */
  1122. /* {{{ proto bool odbc_execute(resource result_id [, array parameters_array])
  1123. Execute a prepared statement */
  1124. PHP_FUNCTION(odbc_execute)
  1125. {
  1126. zval *pv_res, *pv_param_arr, *tmp;
  1127. typedef struct params_t {
  1128. SQLLEN vallen;
  1129. int fp;
  1130. } params_t;
  1131. params_t *params = NULL;
  1132. char *filename;
  1133. unsigned char otype;
  1134. SQLSMALLINT ctype;
  1135. odbc_result *result;
  1136. int numArgs = ZEND_NUM_ARGS(), i, ne;
  1137. RETCODE rc;
  1138. if (zend_parse_parameters(numArgs, "r|a/", &pv_res, &pv_param_arr) == FAILURE) {
  1139. return;
  1140. }
  1141. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1142. RETURN_FALSE;
  1143. }
  1144. /* XXX check for already bound parameters*/
  1145. if (result->numparams > 0 && numArgs == 1) {
  1146. php_error_docref(NULL, E_WARNING, "No parameters to SQL statement given");
  1147. RETURN_FALSE;
  1148. }
  1149. if (result->numparams > 0) {
  1150. if ((ne = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr))) < result->numparams) {
  1151. php_error_docref(NULL, E_WARNING,"Not enough parameters (%d should be %d) given", ne, result->numparams);
  1152. RETURN_FALSE;
  1153. }
  1154. zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
  1155. params = (params_t *)safe_emalloc(sizeof(params_t), result->numparams, 0);
  1156. for(i = 0; i < result->numparams; i++) {
  1157. params[i].fp = -1;
  1158. }
  1159. for(i = 1; i <= result->numparams; i++) {
  1160. if ((tmp = zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr))) == NULL) {
  1161. php_error_docref(NULL, E_WARNING,"Error getting parameter");
  1162. SQLFreeStmt(result->stmt,SQL_RESET_PARAMS);
  1163. for (i = 0; i < result->numparams; i++) {
  1164. if (params[i].fp != -1) {
  1165. close(params[i].fp);
  1166. }
  1167. }
  1168. efree(params);
  1169. RETURN_FALSE;
  1170. }
  1171. otype = Z_TYPE_P(tmp);
  1172. convert_to_string_ex(tmp);
  1173. if (Z_TYPE_P(tmp) != IS_STRING) {
  1174. php_error_docref(NULL, E_WARNING,"Error converting parameter");
  1175. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1176. for (i = 0; i < result->numparams; i++) {
  1177. if (params[i].fp != -1) {
  1178. close(params[i].fp);
  1179. }
  1180. }
  1181. efree(params);
  1182. RETURN_FALSE;
  1183. }
  1184. params[i-1].vallen = Z_STRLEN_P(tmp);
  1185. params[i-1].fp = -1;
  1186. if (IS_SQL_BINARY(result->param_info[i-1].sqltype)) {
  1187. ctype = SQL_C_BINARY;
  1188. } else {
  1189. ctype = SQL_C_CHAR;
  1190. }
  1191. if (Z_STRLEN_P(tmp) > 2 &&
  1192. Z_STRVAL_P(tmp)[0] == '\'' &&
  1193. Z_STRVAL_P(tmp)[Z_STRLEN_P(tmp) - 1] == '\'') {
  1194. if (CHECK_ZVAL_NULL_PATH(tmp)) {
  1195. RETURN_FALSE;
  1196. }
  1197. filename = estrndup(&Z_STRVAL_P(tmp)[1], Z_STRLEN_P(tmp) - 2);
  1198. filename[strlen(filename)] = '\0';
  1199. /* Check the basedir */
  1200. if (php_check_open_basedir(filename)) {
  1201. efree(filename);
  1202. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1203. for (i = 0; i < result->numparams; i++) {
  1204. if (params[i].fp != -1) {
  1205. close(params[i].fp);
  1206. }
  1207. }
  1208. efree(params);
  1209. RETURN_FALSE;
  1210. }
  1211. if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) {
  1212. php_error_docref(NULL, E_WARNING,"Can't open file %s", filename);
  1213. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1214. for (i = 0; i < result->numparams; i++) {
  1215. if (params[i].fp != -1) {
  1216. close(params[i].fp);
  1217. }
  1218. }
  1219. efree(params);
  1220. efree(filename);
  1221. RETURN_FALSE;
  1222. }
  1223. efree(filename);
  1224. params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0);
  1225. rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
  1226. ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale,
  1227. (void *)(intptr_t)params[i-1].fp, 0,
  1228. &params[i-1].vallen);
  1229. } else {
  1230. #ifdef HAVE_DBMAKER
  1231. precision = params[i-1].vallen;
  1232. #endif
  1233. if (otype == IS_NULL) {
  1234. params[i-1].vallen = SQL_NULL_DATA;
  1235. }
  1236. rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
  1237. ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale,
  1238. Z_STRVAL_P(tmp), 0,
  1239. &params[i-1].vallen);
  1240. }
  1241. if (rc == SQL_ERROR) {
  1242. odbc_sql_error(result->conn_ptr, result->stmt, "SQLBindParameter");
  1243. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1244. for (i = 0; i < result->numparams; i++) {
  1245. if (params[i].fp != -1) {
  1246. close(params[i].fp);
  1247. }
  1248. }
  1249. efree(params);
  1250. RETURN_FALSE;
  1251. }
  1252. zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
  1253. }
  1254. }
  1255. /* Close cursor, needed for doing multiple selects */
  1256. rc = SQLFreeStmt(result->stmt, SQL_CLOSE);
  1257. if (rc == SQL_ERROR) {
  1258. odbc_sql_error(result->conn_ptr, result->stmt, "SQLFreeStmt");
  1259. }
  1260. rc = SQLExecute(result->stmt);
  1261. result->fetched = 0;
  1262. if (rc == SQL_NEED_DATA) {
  1263. char buf[4096];
  1264. int fp, nbytes;
  1265. while (rc == SQL_NEED_DATA) {
  1266. rc = SQLParamData(result->stmt, (void*)&fp);
  1267. if (rc == SQL_NEED_DATA) {
  1268. while ((nbytes = read(fp, &buf, 4096)) > 0) {
  1269. SQLPutData(result->stmt, (void*)&buf, nbytes);
  1270. }
  1271. }
  1272. }
  1273. } else {
  1274. switch (rc) {
  1275. case SQL_SUCCESS:
  1276. break;
  1277. case SQL_NO_DATA_FOUND:
  1278. case SQL_SUCCESS_WITH_INFO:
  1279. odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
  1280. break;
  1281. default:
  1282. odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
  1283. RETVAL_FALSE;
  1284. }
  1285. }
  1286. if (result->numparams > 0) {
  1287. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1288. for(i = 0; i < result->numparams; i++) {
  1289. if (params[i].fp != -1) {
  1290. close(params[i].fp);
  1291. }
  1292. }
  1293. efree(params);
  1294. }
  1295. if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA_FOUND) {
  1296. RETVAL_TRUE;
  1297. }
  1298. if (result->numcols == 0) {
  1299. SQLNumResultCols(result->stmt, &(result->numcols));
  1300. if (result->numcols > 0) {
  1301. if (!odbc_bindcols(result)) {
  1302. efree(result);
  1303. RETVAL_FALSE;
  1304. }
  1305. } else {
  1306. result->values = NULL;
  1307. }
  1308. }
  1309. }
  1310. /* }}} */
  1311. /* {{{ proto string odbc_cursor(resource result_id)
  1312. Get cursor name */
  1313. PHP_FUNCTION(odbc_cursor)
  1314. {
  1315. zval *pv_res;
  1316. SQLUSMALLINT max_len;
  1317. SQLSMALLINT len;
  1318. char *cursorname;
  1319. odbc_result *result;
  1320. RETCODE rc;
  1321. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  1322. return;
  1323. }
  1324. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1325. RETURN_FALSE;
  1326. }
  1327. rc = SQLGetInfo(result->conn_ptr->hdbc,SQL_MAX_CURSOR_NAME_LEN, (void *)&max_len,sizeof(max_len),&len);
  1328. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1329. RETURN_FALSE;
  1330. }
  1331. if (max_len > 0) {
  1332. cursorname = emalloc(max_len + 1);
  1333. rc = SQLGetCursorName(result->stmt,cursorname,(SQLSMALLINT)max_len,&len);
  1334. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1335. char state[6]; /* Not used */
  1336. SQLINTEGER error; /* Not used */
  1337. char errormsg[SQL_MAX_MESSAGE_LENGTH];
  1338. SQLSMALLINT errormsgsize; /* Not used */
  1339. SQLError( result->conn_ptr->henv, result->conn_ptr->hdbc,
  1340. result->stmt, state, &error, errormsg,
  1341. sizeof(errormsg)-1, &errormsgsize);
  1342. if (!strncmp(state,"S1015",5)) {
  1343. snprintf(cursorname, max_len+1, "php_curs_" ZEND_ULONG_FMT, (zend_ulong)result->stmt);
  1344. if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS) {
  1345. odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName");
  1346. RETVAL_FALSE;
  1347. } else {
  1348. RETVAL_STRING(cursorname);
  1349. }
  1350. } else {
  1351. php_error_docref(NULL, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
  1352. RETVAL_FALSE;
  1353. }
  1354. } else {
  1355. RETVAL_STRING(cursorname);
  1356. }
  1357. efree(cursorname);
  1358. } else {
  1359. RETVAL_FALSE;
  1360. }
  1361. }
  1362. /* }}} */
  1363. #ifdef HAVE_SQLDATASOURCES
  1364. /* {{{ proto array odbc_data_source(resource connection_id, int fetch_type)
  1365. Return information about the currently connected data source */
  1366. PHP_FUNCTION(odbc_data_source)
  1367. {
  1368. zval *zv_conn;
  1369. zend_long zv_fetch_type;
  1370. RETCODE rc = 0; /* assume all is good */
  1371. odbc_connection *conn;
  1372. UCHAR server_name[100], desc[200];
  1373. SQLSMALLINT len1=0, len2=0, fetch_type;
  1374. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &zv_conn, &zv_fetch_type) == FAILURE) {
  1375. return;
  1376. }
  1377. fetch_type = (SQLSMALLINT) zv_fetch_type;
  1378. if (!(fetch_type == SQL_FETCH_FIRST || fetch_type == SQL_FETCH_NEXT)) {
  1379. php_error_docref(NULL, E_WARNING, "Invalid fetch type (%d)", fetch_type);
  1380. RETURN_FALSE;
  1381. }
  1382. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(zv_conn), "ODBC-Link", le_conn, le_pconn))) {
  1383. RETURN_FALSE;
  1384. }
  1385. /* now we have the "connection" lets call the DataSource object */
  1386. rc = SQLDataSources(conn->henv,
  1387. fetch_type,
  1388. server_name,
  1389. (SQLSMALLINT)sizeof(server_name),
  1390. &len1,
  1391. desc,
  1392. (SQLSMALLINT)sizeof(desc),
  1393. &len2);
  1394. if (SQL_NO_DATA == rc) {
  1395. /* System has no data sources, no error. Signal it by returning NULL,
  1396. not false. */
  1397. RETURN_NULL();
  1398. } else if (rc != SQL_SUCCESS) {
  1399. /* ummm.... he did it */
  1400. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLDataSources");
  1401. RETURN_FALSE;
  1402. }
  1403. if (len1 == 0 || len2 == 0) {
  1404. /* we have a non-valid entry... so stop the looping */
  1405. RETURN_FALSE;
  1406. }
  1407. array_init(return_value);
  1408. add_assoc_string_ex(return_value, "server", sizeof("server")-1, server_name);
  1409. add_assoc_string_ex(return_value, "description", sizeof("description")-1, desc);
  1410. }
  1411. /* }}} */
  1412. #endif /* HAVE_SQLDATASOURCES */
  1413. /* {{{ proto resource odbc_exec(resource connection_id, string query [, int flags])
  1414. Prepare and execute an SQL statement */
  1415. /* XXX Use flags */
  1416. PHP_FUNCTION(odbc_exec)
  1417. {
  1418. zval *pv_conn;
  1419. zend_long pv_flags;
  1420. char *query;
  1421. size_t query_len;
  1422. odbc_result *result = NULL;
  1423. odbc_connection *conn;
  1424. RETCODE rc;
  1425. #ifdef HAVE_SQL_EXTENDED_FETCH
  1426. SQLUINTEGER scrollopts;
  1427. #endif
  1428. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &pv_conn, &query, &query_len, &pv_flags) == FAILURE) {
  1429. return;
  1430. }
  1431. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  1432. RETURN_FALSE;
  1433. }
  1434. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  1435. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  1436. if (rc == SQL_INVALID_HANDLE) {
  1437. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  1438. efree(result);
  1439. RETURN_FALSE;
  1440. }
  1441. if (rc == SQL_ERROR) {
  1442. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  1443. efree(result);
  1444. RETURN_FALSE;
  1445. }
  1446. #ifdef HAVE_SQL_EXTENDED_FETCH
  1447. /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
  1448. whether Driver supports ExtendedFetch */
  1449. rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
  1450. if (rc == SQL_SUCCESS) {
  1451. if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
  1452. /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
  1453. type if not possible.
  1454. */
  1455. SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
  1456. }
  1457. } else {
  1458. result->fetch_abs = 0;
  1459. }
  1460. #endif
  1461. rc = SQLExecDirect(result->stmt, query, SQL_NTS);
  1462. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) {
  1463. /* XXX FIXME we should really check out SQLSTATE with SQLError
  1464. * in case rc is SQL_SUCCESS_WITH_INFO here.
  1465. */
  1466. odbc_sql_error(conn, result->stmt, "SQLExecDirect");
  1467. SQLFreeStmt(result->stmt, SQL_DROP);
  1468. efree(result);
  1469. RETURN_FALSE;
  1470. }
  1471. SQLNumResultCols(result->stmt, &(result->numcols));
  1472. /* For insert, update etc. cols == 0 */
  1473. if (result->numcols > 0) {
  1474. if (!odbc_bindcols(result)) {
  1475. efree(result);
  1476. RETURN_FALSE;
  1477. }
  1478. } else {
  1479. result->values = NULL;
  1480. }
  1481. Z_ADDREF_P(pv_conn);
  1482. result->conn_ptr = conn;
  1483. result->fetched = 0;
  1484. RETURN_RES(zend_register_resource(result, le_result));
  1485. }
  1486. /* }}} */
  1487. #ifdef PHP_ODBC_HAVE_FETCH_HASH
  1488. #define ODBC_NUM 1
  1489. #define ODBC_OBJECT 2
  1490. /* {{{ php_odbc_fetch_hash */
  1491. static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
  1492. {
  1493. int i;
  1494. odbc_result *result;
  1495. RETCODE rc;
  1496. SQLSMALLINT sql_c_type;
  1497. char *buf = NULL;
  1498. #ifdef HAVE_SQL_EXTENDED_FETCH
  1499. SQLULEN crow;
  1500. SQLUSMALLINT RowStatus[1];
  1501. SQLLEN rownum;
  1502. zval *pv_res, tmp;
  1503. zend_long pv_row = -1;
  1504. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &pv_res, &pv_row) == FAILURE) {
  1505. return;
  1506. }
  1507. rownum = pv_row;
  1508. #else
  1509. zval *pv_res, tmp;
  1510. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  1511. return;
  1512. }
  1513. #endif
  1514. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1515. RETURN_FALSE;
  1516. }
  1517. if (result->numcols == 0) {
  1518. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  1519. RETURN_FALSE;
  1520. }
  1521. #ifdef HAVE_SQL_EXTENDED_FETCH
  1522. if (result->fetch_abs) {
  1523. if (rownum > 0) {
  1524. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
  1525. } else {
  1526. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1527. }
  1528. } else
  1529. #endif
  1530. rc = SQLFetch(result->stmt);
  1531. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1532. RETURN_FALSE;
  1533. }
  1534. array_init(return_value);
  1535. #ifdef HAVE_SQL_EXTENDED_FETCH
  1536. if (rownum > 0 && result->fetch_abs)
  1537. result->fetched = rownum;
  1538. else
  1539. #endif
  1540. result->fetched++;
  1541. for(i = 0; i < result->numcols; i++) {
  1542. sql_c_type = SQL_C_CHAR;
  1543. switch(result->values[i].coltype) {
  1544. case SQL_BINARY:
  1545. case SQL_VARBINARY:
  1546. case SQL_LONGVARBINARY:
  1547. if (result->binmode <= 0) {
  1548. ZVAL_EMPTY_STRING(&tmp);
  1549. break;
  1550. }
  1551. if (result->binmode == 1) {
  1552. sql_c_type = SQL_C_BINARY;
  1553. }
  1554. case SQL_LONGVARCHAR:
  1555. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  1556. case SQL_WLONGVARCHAR:
  1557. #endif
  1558. if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
  1559. ZVAL_EMPTY_STRING(&tmp);
  1560. break;
  1561. }
  1562. if (buf == NULL) {
  1563. buf = emalloc(result->longreadlen + 1);
  1564. }
  1565. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1), sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
  1566. if (rc == SQL_ERROR) {
  1567. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1568. efree(buf);
  1569. RETURN_FALSE;
  1570. }
  1571. if (rc == SQL_SUCCESS_WITH_INFO) {
  1572. ZVAL_STRINGL(&tmp, buf, result->longreadlen);
  1573. } else if (rc != SQL_SUCCESS) {
  1574. php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
  1575. ZVAL_FALSE(&tmp);
  1576. } else if (result->values[i].vallen == SQL_NULL_DATA) {
  1577. ZVAL_NULL(&tmp);
  1578. break;
  1579. } else {
  1580. ZVAL_STRINGL(&tmp, buf, result->values[i].vallen);
  1581. }
  1582. break;
  1583. default:
  1584. if (result->values[i].vallen == SQL_NULL_DATA) {
  1585. ZVAL_NULL(&tmp);
  1586. break;
  1587. }
  1588. ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen);
  1589. break;
  1590. }
  1591. if (result_type & ODBC_NUM) {
  1592. zend_hash_index_update(Z_ARRVAL_P(return_value), i, &tmp);
  1593. } else {
  1594. if (!*(result->values[i].name) && Z_TYPE(tmp) == IS_STRING) {
  1595. zend_hash_update(Z_ARRVAL_P(return_value), Z_STR(tmp), &tmp);
  1596. } else {
  1597. zend_hash_str_update(Z_ARRVAL_P(return_value), result->values[i].name, strlen(result->values[i].name), &tmp);
  1598. }
  1599. }
  1600. }
  1601. if (buf) {
  1602. efree(buf);
  1603. }
  1604. }
  1605. /* }}} */
  1606. /* {{{ proto object odbc_fetch_object(resource result [, int rownumber])
  1607. Fetch a result row as an object */
  1608. PHP_FUNCTION(odbc_fetch_object)
  1609. {
  1610. php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
  1611. if (Z_TYPE_P(return_value) == IS_ARRAY) {
  1612. object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
  1613. }
  1614. }
  1615. /* }}} */
  1616. /* {{{ proto array odbc_fetch_array(resource result [, int rownumber])
  1617. Fetch a result row as an associative array */
  1618. PHP_FUNCTION(odbc_fetch_array)
  1619. {
  1620. php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
  1621. }
  1622. /* }}} */
  1623. #endif
  1624. /* {{{ proto int odbc_fetch_into(resource result_id, array &result_array [, int rownumber])
  1625. Fetch one result row into an array */
  1626. PHP_FUNCTION(odbc_fetch_into)
  1627. {
  1628. int i;
  1629. odbc_result *result;
  1630. RETCODE rc;
  1631. SQLSMALLINT sql_c_type;
  1632. char *buf = NULL;
  1633. zval *pv_res, *pv_res_arr, tmp;
  1634. #ifdef HAVE_SQL_EXTENDED_FETCH
  1635. zend_long pv_row = 0;
  1636. SQLULEN crow;
  1637. SQLUSMALLINT RowStatus[1];
  1638. SQLLEN rownum = -1;
  1639. #endif /* HAVE_SQL_EXTENDED_FETCH */
  1640. #ifdef HAVE_SQL_EXTENDED_FETCH
  1641. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) {
  1642. return;
  1643. }
  1644. rownum = pv_row;
  1645. #else
  1646. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/", &pv_res, &pv_res_arr) == FAILURE) {
  1647. return;
  1648. }
  1649. #endif /* HAVE_SQL_EXTENDED_FETCH */
  1650. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1651. RETURN_FALSE;
  1652. }
  1653. if (result->numcols == 0) {
  1654. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  1655. RETURN_FALSE;
  1656. }
  1657. if (Z_TYPE_P(pv_res_arr) != IS_ARRAY) {
  1658. array_init(pv_res_arr);
  1659. }
  1660. #ifdef HAVE_SQL_EXTENDED_FETCH
  1661. if (result->fetch_abs) {
  1662. if (rownum > 0) {
  1663. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
  1664. } else {
  1665. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1666. }
  1667. } else
  1668. #endif
  1669. rc = SQLFetch(result->stmt);
  1670. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1671. RETURN_FALSE;
  1672. }
  1673. #ifdef HAVE_SQL_EXTENDED_FETCH
  1674. if (rownum > 0 && result->fetch_abs)
  1675. result->fetched = rownum;
  1676. else
  1677. #endif
  1678. result->fetched++;
  1679. for(i = 0; i < result->numcols; i++) {
  1680. sql_c_type = SQL_C_CHAR;
  1681. switch(result->values[i].coltype) {
  1682. case SQL_BINARY:
  1683. case SQL_VARBINARY:
  1684. case SQL_LONGVARBINARY:
  1685. if (result->binmode <= 0) {
  1686. ZVAL_EMPTY_STRING(&tmp);
  1687. break;
  1688. }
  1689. if (result->binmode == 1) sql_c_type = SQL_C_BINARY;
  1690. case SQL_LONGVARCHAR:
  1691. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  1692. case SQL_WLONGVARCHAR:
  1693. #endif
  1694. if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
  1695. ZVAL_EMPTY_STRING(&tmp);
  1696. break;
  1697. }
  1698. if (buf == NULL) {
  1699. buf = emalloc(result->longreadlen + 1);
  1700. }
  1701. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
  1702. if (rc == SQL_ERROR) {
  1703. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1704. efree(buf);
  1705. RETURN_FALSE;
  1706. }
  1707. if (rc == SQL_SUCCESS_WITH_INFO) {
  1708. ZVAL_STRINGL(&tmp, buf, result->longreadlen);
  1709. } else if (rc != SQL_SUCCESS) {
  1710. php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
  1711. ZVAL_FALSE(&tmp);
  1712. } else if (result->values[i].vallen == SQL_NULL_DATA) {
  1713. ZVAL_NULL(&tmp);
  1714. break;
  1715. } else {
  1716. ZVAL_STRINGL(&tmp, buf, result->values[i].vallen);
  1717. }
  1718. break;
  1719. default:
  1720. if (result->values[i].vallen == SQL_NULL_DATA) {
  1721. ZVAL_NULL(&tmp);
  1722. break;
  1723. }
  1724. ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen);
  1725. break;
  1726. }
  1727. zend_hash_index_update(Z_ARRVAL_P(pv_res_arr), i, &tmp);
  1728. }
  1729. if (buf) efree(buf);
  1730. RETURN_LONG(result->numcols);
  1731. }
  1732. /* }}} */
  1733. /* {{{ proto bool solid_fetch_prev(resource result_id)
  1734. */
  1735. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
  1736. PHP_FUNCTION(solid_fetch_prev)
  1737. {
  1738. odbc_result *result;
  1739. RETCODE rc;
  1740. zval *pv_res;
  1741. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  1742. return;
  1743. }
  1744. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1745. RETURN_FALSE;
  1746. }
  1747. if (result->numcols == 0) {
  1748. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  1749. RETURN_FALSE;
  1750. }
  1751. rc = SQLFetchPrev(result->stmt);
  1752. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1753. RETURN_FALSE;
  1754. }
  1755. if (result->fetched > 1) {
  1756. result->fetched--;
  1757. }
  1758. RETURN_TRUE;
  1759. }
  1760. #endif
  1761. /* }}} */
  1762. /* {{{ proto bool odbc_fetch_row(resource result_id [, int row_number])
  1763. Fetch a row */
  1764. PHP_FUNCTION(odbc_fetch_row)
  1765. {
  1766. SQLLEN rownum;
  1767. odbc_result *result;
  1768. RETCODE rc;
  1769. zval *pv_res;
  1770. zend_long pv_row = 1;
  1771. #ifdef HAVE_SQL_EXTENDED_FETCH
  1772. SQLULEN crow;
  1773. SQLUSMALLINT RowStatus[1];
  1774. #endif
  1775. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &pv_res, &pv_row) == FAILURE) {
  1776. return;
  1777. }
  1778. rownum = pv_row;
  1779. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1780. RETURN_FALSE;
  1781. }
  1782. if (result->numcols == 0) {
  1783. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  1784. RETURN_FALSE;
  1785. }
  1786. #ifdef HAVE_SQL_EXTENDED_FETCH
  1787. if (result->fetch_abs) {
  1788. if (ZEND_NUM_ARGS() > 1) {
  1789. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
  1790. } else {
  1791. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1792. }
  1793. } else
  1794. #endif
  1795. rc = SQLFetch(result->stmt);
  1796. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1797. RETURN_FALSE;
  1798. }
  1799. if (ZEND_NUM_ARGS() > 1) {
  1800. result->fetched = rownum;
  1801. } else {
  1802. result->fetched++;
  1803. }
  1804. RETURN_TRUE;
  1805. }
  1806. /* }}} */
  1807. /* {{{ proto mixed odbc_result(resource result_id, mixed field)
  1808. Get result data */
  1809. PHP_FUNCTION(odbc_result)
  1810. {
  1811. char *field;
  1812. zend_string *field_str;
  1813. int field_ind;
  1814. SQLSMALLINT sql_c_type = SQL_C_CHAR;
  1815. odbc_result *result;
  1816. int i = 0;
  1817. RETCODE rc;
  1818. SQLLEN fieldsize;
  1819. zval *pv_res, *pv_field;
  1820. #ifdef HAVE_SQL_EXTENDED_FETCH
  1821. SQLULEN crow;
  1822. SQLUSMALLINT RowStatus[1];
  1823. #endif
  1824. field_ind = -1;
  1825. field = NULL;
  1826. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &pv_res, &pv_field) == FAILURE) {
  1827. return;
  1828. }
  1829. if (Z_TYPE_P(pv_field) == IS_STRING) {
  1830. field = Z_STRVAL_P(pv_field);
  1831. } else {
  1832. convert_to_long_ex(pv_field);
  1833. field_ind = Z_LVAL_P(pv_field) - 1;
  1834. }
  1835. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  1836. RETURN_FALSE;
  1837. }
  1838. if ((result->numcols == 0)) {
  1839. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  1840. RETURN_FALSE;
  1841. }
  1842. /* get field index if the field parameter was a string */
  1843. if (field != NULL) {
  1844. if (result->values == NULL) {
  1845. php_error_docref(NULL, E_WARNING, "Result set contains no data");
  1846. RETURN_FALSE;
  1847. }
  1848. for(i = 0; i < result->numcols; i++) {
  1849. if (!strcasecmp(result->values[i].name, field)) {
  1850. field_ind = i;
  1851. break;
  1852. }
  1853. }
  1854. if (field_ind < 0) {
  1855. php_error_docref(NULL, E_WARNING, "Field %s not found", field);
  1856. RETURN_FALSE;
  1857. }
  1858. } else {
  1859. /* check for limits of field_ind if the field parameter was an int */
  1860. if (field_ind >= result->numcols || field_ind < 0) {
  1861. php_error_docref(NULL, E_WARNING, "Field index is larger than the number of fields");
  1862. RETURN_FALSE;
  1863. }
  1864. }
  1865. if (result->fetched == 0) {
  1866. /* User forgot to call odbc_fetch_row(), or wants to reload the results, do it now */
  1867. #ifdef HAVE_SQL_EXTENDED_FETCH
  1868. if (result->fetch_abs)
  1869. rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus);
  1870. else
  1871. #endif
  1872. rc = SQLFetch(result->stmt);
  1873. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1874. RETURN_FALSE;
  1875. }
  1876. result->fetched++;
  1877. }
  1878. switch(result->values[field_ind].coltype) {
  1879. case SQL_BINARY:
  1880. case SQL_VARBINARY:
  1881. case SQL_LONGVARBINARY:
  1882. if (result->binmode <= 1) {
  1883. sql_c_type = SQL_C_BINARY;
  1884. }
  1885. if (result->binmode <= 0) {
  1886. break;
  1887. }
  1888. case SQL_LONGVARCHAR:
  1889. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  1890. case SQL_WLONGVARCHAR:
  1891. #endif
  1892. if (IS_SQL_LONG(result->values[field_ind].coltype)) {
  1893. if (result->longreadlen <= 0) {
  1894. break;
  1895. } else {
  1896. fieldsize = result->longreadlen;
  1897. }
  1898. } else {
  1899. PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(field_ind + 1),
  1900. (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH :
  1901. SQL_COLUMN_DISPLAY_SIZE),
  1902. NULL, 0, NULL, &fieldsize);
  1903. }
  1904. /* For char data, the length of the returned string will be longreadlen - 1 */
  1905. fieldsize = (result->longreadlen <= 0) ? 4096 : result->longreadlen;
  1906. field_str = zend_string_alloc(fieldsize, 0);
  1907. /* SQLGetData will truncate CHAR data to fieldsize - 1 bytes and append \0.
  1908. * For binary data it is truncated to fieldsize bytes.
  1909. */
  1910. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1), sql_c_type,
  1911. ZSTR_VAL(field_str), fieldsize, &result->values[field_ind].vallen);
  1912. if (rc == SQL_ERROR) {
  1913. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1914. zend_string_efree(field_str);
  1915. RETURN_FALSE;
  1916. }
  1917. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1918. zend_string_efree(field_str);
  1919. php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc);
  1920. RETURN_FALSE;
  1921. } else if (result->values[field_ind].vallen == SQL_NULL_DATA) {
  1922. zend_string_efree(field_str);
  1923. RETURN_NULL();
  1924. }
  1925. /* Reduce fieldlen by 1 if we have char data. One day we might
  1926. have binary strings... */
  1927. if ((result->values[field_ind].coltype == SQL_LONGVARCHAR)
  1928. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  1929. || (result->values[field_ind].coltype == SQL_WLONGVARCHAR)
  1930. #endif
  1931. ) {
  1932. fieldsize -= 1;
  1933. }
  1934. /* Don't duplicate result, saves one emalloc.
  1935. For SQL_SUCCESS, the length is in vallen.
  1936. */
  1937. if (rc != SQL_SUCCESS_WITH_INFO) {
  1938. field_str = zend_string_truncate(field_str, result->values[field_ind].vallen, 0);
  1939. }
  1940. ZSTR_VAL(field_str)[ZSTR_LEN(field_str)] = '\0';
  1941. RETURN_NEW_STR(field_str);
  1942. break;
  1943. default:
  1944. if (result->values[field_ind].vallen == SQL_NULL_DATA) {
  1945. RETURN_NULL();
  1946. } else {
  1947. RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen);
  1948. }
  1949. break;
  1950. }
  1951. /* If we come here, output unbound LONG and/or BINARY column data to the client */
  1952. /* We emalloc 1 byte more for SQL_C_CHAR (trailing \0) */
  1953. fieldsize = (sql_c_type == SQL_C_CHAR) ? 4096 : 4095;
  1954. field = emalloc(fieldsize);
  1955. /* Call SQLGetData() until SQL_SUCCESS is returned */
  1956. while(1) {
  1957. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1),sql_c_type, field, fieldsize, &result->values[field_ind].vallen);
  1958. if (rc == SQL_ERROR) {
  1959. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1960. efree(field);
  1961. RETURN_FALSE;
  1962. }
  1963. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1964. php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc);
  1965. efree(field);
  1966. RETURN_FALSE;
  1967. }
  1968. if (result->values[field_ind].vallen == SQL_NULL_DATA) {
  1969. efree(field);
  1970. RETURN_NULL();
  1971. }
  1972. /* chop the trailing \0 by outputing only 4095 bytes */
  1973. PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen);
  1974. if (rc == SQL_SUCCESS) { /* no more data avail */
  1975. efree(field);
  1976. RETURN_TRUE;
  1977. }
  1978. }
  1979. RETURN_TRUE;
  1980. }
  1981. /* }}} */
  1982. /* {{{ proto int odbc_result_all(resource result_id [, string format])
  1983. Print result as HTML table */
  1984. PHP_FUNCTION(odbc_result_all)
  1985. {
  1986. char *buf = NULL;
  1987. odbc_result *result;
  1988. RETCODE rc;
  1989. zval *pv_res;
  1990. char *pv_format = NULL;
  1991. size_t i, pv_format_len = 0;
  1992. SQLSMALLINT sql_c_type;
  1993. #ifdef HAVE_SQL_EXTENDED_FETCH
  1994. SQLULEN crow;
  1995. SQLUSMALLINT RowStatus[1];
  1996. #endif
  1997. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|s", &pv_res, &pv_format, &pv_format_len) == FAILURE) {
  1998. return;
  1999. }
  2000. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2001. RETURN_FALSE;
  2002. }
  2003. if (result->numcols == 0) {
  2004. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  2005. RETURN_FALSE;
  2006. }
  2007. #ifdef HAVE_SQL_EXTENDED_FETCH
  2008. if (result->fetch_abs)
  2009. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  2010. else
  2011. #endif
  2012. rc = SQLFetch(result->stmt);
  2013. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2014. php_printf("<h2>No rows found</h2>\n");
  2015. RETURN_LONG(0);
  2016. }
  2017. /* Start table tag */
  2018. if (ZEND_NUM_ARGS() == 1) {
  2019. php_printf("<table><tr>");
  2020. } else {
  2021. php_printf("<table %s ><tr>", pv_format);
  2022. }
  2023. for (i = 0; i < result->numcols; i++) {
  2024. php_printf("<th>%s</th>", result->values[i].name);
  2025. }
  2026. php_printf("</tr>\n");
  2027. while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
  2028. result->fetched++;
  2029. php_printf("<tr>");
  2030. for(i = 0; i < result->numcols; i++) {
  2031. sql_c_type = SQL_C_CHAR;
  2032. switch(result->values[i].coltype) {
  2033. case SQL_BINARY:
  2034. case SQL_VARBINARY:
  2035. case SQL_LONGVARBINARY:
  2036. if (result->binmode <= 0) {
  2037. php_printf("<td>Not printable</td>");
  2038. break;
  2039. }
  2040. if (result->binmode <= 1) sql_c_type = SQL_C_BINARY;
  2041. case SQL_LONGVARCHAR:
  2042. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  2043. case SQL_WLONGVARCHAR:
  2044. #endif
  2045. if (IS_SQL_LONG(result->values[i].coltype) &&
  2046. result->longreadlen <= 0) {
  2047. php_printf("<td>Not printable</td>");
  2048. break;
  2049. }
  2050. if (buf == NULL) {
  2051. buf = emalloc(result->longreadlen);
  2052. }
  2053. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen, &result->values[i].vallen);
  2054. php_printf("<td>");
  2055. if (rc == SQL_ERROR) {
  2056. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  2057. php_printf("</td></tr></table>");
  2058. efree(buf);
  2059. RETURN_FALSE;
  2060. }
  2061. if (rc == SQL_SUCCESS_WITH_INFO) {
  2062. PHPWRITE(buf, result->longreadlen);
  2063. } else if (rc != SQL_SUCCESS) {
  2064. php_printf("</td></tr></table>");
  2065. php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (retcode %u)", i + 1, rc);
  2066. efree(buf);
  2067. RETURN_FALSE;
  2068. } else if (result->values[i].vallen == SQL_NULL_DATA) {
  2069. php_printf("<td>NULL</td>");
  2070. break;
  2071. } else {
  2072. PHPWRITE(buf, result->values[i].vallen);
  2073. }
  2074. php_printf("</td>");
  2075. break;
  2076. default:
  2077. if (result->values[i].vallen == SQL_NULL_DATA) {
  2078. php_printf("<td>NULL</td>");
  2079. } else {
  2080. php_printf("<td>%s</td>", result->values[i].value);
  2081. }
  2082. break;
  2083. }
  2084. }
  2085. php_printf("</tr>\n");
  2086. #ifdef HAVE_SQL_EXTENDED_FETCH
  2087. if (result->fetch_abs)
  2088. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  2089. else
  2090. #endif
  2091. rc = SQLFetch(result->stmt);
  2092. }
  2093. php_printf("</table>\n");
  2094. if (buf) efree(buf);
  2095. RETURN_LONG(result->fetched);
  2096. }
  2097. /* }}} */
  2098. /* {{{ proto bool odbc_free_result(resource result_id)
  2099. Free resources associated with a result */
  2100. PHP_FUNCTION(odbc_free_result)
  2101. {
  2102. zval *pv_res;
  2103. odbc_result *result;
  2104. int i;
  2105. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  2106. return;
  2107. }
  2108. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2109. RETURN_FALSE;
  2110. }
  2111. if (result->values) {
  2112. for (i = 0; i < result->numcols; i++) {
  2113. if (result->values[i].value) {
  2114. efree(result->values[i].value);
  2115. }
  2116. }
  2117. efree(result->values);
  2118. result->values = NULL;
  2119. }
  2120. zend_list_close(Z_RES_P(pv_res));
  2121. RETURN_TRUE;
  2122. }
  2123. /* }}} */
  2124. /* {{{ proto resource odbc_connect(string DSN, string user, string password [, int cursor_option])
  2125. Connect to a datasource */
  2126. PHP_FUNCTION(odbc_connect)
  2127. {
  2128. odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2129. }
  2130. /* }}} */
  2131. /* {{{ proto resource odbc_pconnect(string DSN, string user, string password [, int cursor_option])
  2132. Establish a persistent connection to a datasource */
  2133. PHP_FUNCTION(odbc_pconnect)
  2134. {
  2135. odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2136. }
  2137. /* }}} */
  2138. /* {{{ odbc_sqlconnect */
  2139. int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int cur_opt, int persistent)
  2140. {
  2141. RETCODE rc;
  2142. *conn = (odbc_connection *)pemalloc(sizeof(odbc_connection), persistent);
  2143. memset(*conn, 0, sizeof(odbc_connection));
  2144. (*conn)->persistent = persistent;
  2145. SQLAllocEnv(&((*conn)->henv));
  2146. SQLAllocConnect((*conn)->henv, &((*conn)->hdbc));
  2147. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
  2148. SQLSetConnectOption((*conn)->hdbc, SQL_TRANSLATE_OPTION,
  2149. SQL_SOLID_XLATOPT_NOCNV);
  2150. #endif
  2151. #ifdef HAVE_OPENLINK
  2152. {
  2153. char dsnbuf[1024];
  2154. short dsnbuflen;
  2155. rc = SQLDriverConnect((*conn)->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
  2156. }
  2157. #else
  2158. if (cur_opt != SQL_CUR_DEFAULT) {
  2159. rc = SQLSetConnectOption((*conn)->hdbc, SQL_ODBC_CURSORS, cur_opt);
  2160. if (rc != SQL_SUCCESS) { /* && rc != SQL_SUCCESS_WITH_INFO ? */
  2161. odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLSetConnectOption");
  2162. SQLFreeConnect((*conn)->hdbc);
  2163. pefree(*conn, persistent);
  2164. return FALSE;
  2165. }
  2166. }
  2167. /* Possible fix for bug #10250
  2168. * Needs testing on UnixODBC < 2.0.5 though. */
  2169. #if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC)
  2170. /* * Uncomment the line above, and comment line below to fully test
  2171. * #ifdef HAVE_EMPRESS */
  2172. {
  2173. int direct = 0;
  2174. char dsnbuf[1024];
  2175. short dsnbuflen;
  2176. char *ldb = 0;
  2177. int ldb_len = 0;
  2178. if (strstr((char*)db, ";")) {
  2179. direct = 1;
  2180. if (uid && !strstr ((char*)db, "uid") && !strstr((char*)db, "UID")) {
  2181. spprintf(&ldb, 0, "%s;UID=%s;PWD=%s", db, uid, pwd);
  2182. } else {
  2183. ldb_len = strlen(db)+1;
  2184. ldb = (char*) emalloc(ldb_len);
  2185. memcpy(ldb, db, ldb_len);
  2186. }
  2187. }
  2188. if (direct) {
  2189. rc = SQLDriverConnect((*conn)->hdbc, NULL, ldb, strlen(ldb), dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
  2190. } else {
  2191. rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
  2192. }
  2193. if (ldb) {
  2194. efree(ldb);
  2195. }
  2196. }
  2197. #else
  2198. rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
  2199. #endif
  2200. #endif
  2201. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2202. odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLConnect");
  2203. SQLFreeConnect((*conn)->hdbc);
  2204. pefree((*conn), persistent);
  2205. return FALSE;
  2206. }
  2207. /* (*conn)->open = 1;*/
  2208. return TRUE;
  2209. }
  2210. /* }}} */
  2211. /* Persistent connections: two list-types le_pconn, le_conn and a plist
  2212. * where hashed connection info is stored together with index pointer to
  2213. * the actual link of type le_pconn in the list. Only persistent
  2214. * connections get hashed up. Normal connections use existing pconnections.
  2215. * Maybe this has to change with regard to transactions on pconnections?
  2216. * Possibly set autocommit to on on request shutdown.
  2217. *
  2218. * We do have to hash non-persistent connections, and reuse connections.
  2219. * In the case where two connects were being made, without closing the first
  2220. * connect, access violations were occurring. This is because some of the
  2221. * "globals" in this module should actually be per-connection variables. I
  2222. * simply fixed things to get them working for now. Shane
  2223. */
  2224. /* {{{ odbc_do_connect */
  2225. void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
  2226. {
  2227. char *db, *uid, *pwd;
  2228. size_t db_len, uid_len, pwd_len;
  2229. zend_long pv_opt = SQL_CUR_DEFAULT;
  2230. odbc_connection *db_conn;
  2231. char *hashed_details;
  2232. int hashed_len, cur_opt;
  2233. /* Now an optional 4th parameter specifying the cursor type
  2234. * defaulting to the cursors default
  2235. */
  2236. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|l", &db, &db_len, &uid, &uid_len, &pwd, &pwd_len, &pv_opt) == FAILURE) {
  2237. return;
  2238. }
  2239. cur_opt = pv_opt;
  2240. if (ZEND_NUM_ARGS() > 3) {
  2241. /* Confirm the cur_opt range */
  2242. if (! (cur_opt == SQL_CUR_USE_IF_NEEDED ||
  2243. cur_opt == SQL_CUR_USE_ODBC ||
  2244. cur_opt == SQL_CUR_USE_DRIVER ||
  2245. cur_opt == SQL_CUR_DEFAULT) ) {
  2246. php_error_docref(NULL, E_WARNING, "Invalid Cursor type (%d)", cur_opt);
  2247. RETURN_FALSE;
  2248. }
  2249. }
  2250. if (ODBCG(allow_persistent) <= 0) {
  2251. persistent = 0;
  2252. }
  2253. hashed_len = spprintf(&hashed_details, 0, "%s_%s_%s_%s_%d", ODBC_TYPE, db, uid, pwd, cur_opt);
  2254. /* FIXME the idea of checking to see if our connection is already persistent
  2255. is good, but it adds a lot of overhead to non-persistent connections. We
  2256. should look and see if we can fix that somehow */
  2257. /* try to find if we already have this link in our persistent list,
  2258. * no matter if it is to be persistent or not
  2259. */
  2260. try_and_get_another_connection:
  2261. if (persistent) {
  2262. zend_resource *le;
  2263. /* the link is not in the persistent list */
  2264. if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_len)) == NULL) {
  2265. if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
  2266. php_error_docref(NULL, E_WARNING, "Too many open links (%ld)", ODBCG(num_links));
  2267. efree(hashed_details);
  2268. RETURN_FALSE;
  2269. }
  2270. if (ODBCG(max_persistent) != -1 && ODBCG(num_persistent) >= ODBCG(max_persistent)) {
  2271. php_error_docref(NULL, E_WARNING,"Too many open persistent links (%ld)", ODBCG(num_persistent));
  2272. efree(hashed_details);
  2273. RETURN_FALSE;
  2274. }
  2275. if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 1)) {
  2276. efree(hashed_details);
  2277. RETURN_FALSE;
  2278. }
  2279. if (zend_register_persistent_resource(hashed_details, hashed_len, db_conn, le_pconn) == NULL) {
  2280. free(db_conn);
  2281. efree(hashed_details);
  2282. RETURN_FALSE;
  2283. }
  2284. ODBCG(num_persistent)++;
  2285. ODBCG(num_links)++;
  2286. db_conn->res = zend_register_resource(db_conn, le_pconn);
  2287. RETVAL_RES(db_conn->res);
  2288. } else { /* found connection */
  2289. if (le->type != le_pconn) {
  2290. RETURN_FALSE;
  2291. }
  2292. /*
  2293. * check to see if the connection is still valid
  2294. */
  2295. db_conn = (odbc_connection *)le->ptr;
  2296. /*
  2297. * check to see if the connection is still in place (lurcher)
  2298. */
  2299. if(ODBCG(check_persistent)){
  2300. RETCODE ret;
  2301. UCHAR d_name[32];
  2302. SQLSMALLINT len;
  2303. ret = SQLGetInfo(db_conn->hdbc,
  2304. SQL_DATA_SOURCE_READ_ONLY,
  2305. d_name, sizeof(d_name), &len);
  2306. if(ret != SQL_SUCCESS || len == 0) {
  2307. zend_hash_str_del(&EG(persistent_list), hashed_details, hashed_len);
  2308. /* Commented out to fix a possible double closure error
  2309. * when working with persistent connections as submitted by
  2310. * bug #15758
  2311. *
  2312. * safe_odbc_disconnect(db_conn->hdbc);
  2313. * SQLFreeConnect(db_conn->hdbc);
  2314. */
  2315. goto try_and_get_another_connection;
  2316. }
  2317. }
  2318. }
  2319. db_conn->res = zend_register_resource(db_conn, le_pconn);
  2320. RETVAL_RES(db_conn->res);
  2321. } else { /* non persistent */
  2322. zend_resource *index_ptr, new_index_ptr;
  2323. if ((index_ptr = zend_hash_str_find_ptr(&EG(regular_list), hashed_details, hashed_len)) != NULL) {
  2324. zend_ulong conn_id;
  2325. zend_resource *p;
  2326. if (index_ptr->type != le_index_ptr) {
  2327. RETURN_FALSE;
  2328. }
  2329. conn_id = (zend_ulong)index_ptr->ptr;
  2330. p = zend_hash_index_find_ptr(&EG(regular_list), conn_id); /* check if the connection is still there */
  2331. if (p && p->ptr && (p->type == le_conn || p->type == le_pconn)) {
  2332. GC_ADDREF(p);
  2333. RETVAL_RES(p);
  2334. efree(hashed_details);
  2335. return;
  2336. } else {
  2337. zend_hash_str_del(&EG(regular_list), hashed_details, hashed_len);
  2338. }
  2339. }
  2340. if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
  2341. php_error_docref(NULL, E_WARNING,"Too many open connections (%ld)",ODBCG(num_links));
  2342. efree(hashed_details);
  2343. RETURN_FALSE;
  2344. }
  2345. if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 0)) {
  2346. efree(hashed_details);
  2347. RETURN_FALSE;
  2348. }
  2349. db_conn->res = zend_register_resource(db_conn, le_conn);
  2350. RETVAL_RES(db_conn->res);
  2351. new_index_ptr.ptr = (void *)(zend_uintptr_t)Z_RES_HANDLE_P(return_value);
  2352. new_index_ptr.type = le_index_ptr;
  2353. zend_hash_str_update_mem(&EG(regular_list), hashed_details, hashed_len, (void *) &new_index_ptr,
  2354. sizeof(zend_resource));
  2355. ODBCG(num_links)++;
  2356. }
  2357. efree(hashed_details);
  2358. }
  2359. /* }}} */
  2360. /* {{{ proto void odbc_close(resource connection_id)
  2361. Close an ODBC connection */
  2362. PHP_FUNCTION(odbc_close)
  2363. {
  2364. zval *pv_conn;
  2365. zend_resource *p;
  2366. odbc_connection *conn;
  2367. odbc_result *res;
  2368. int is_pconn = 0;
  2369. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_conn) == FAILURE) {
  2370. return;
  2371. }
  2372. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2373. RETURN_FALSE;
  2374. }
  2375. if (Z_RES_P(pv_conn)->type == le_pconn) {
  2376. is_pconn = 1;
  2377. }
  2378. ZEND_HASH_FOREACH_PTR(&EG(regular_list), p) {
  2379. if (p->ptr && (p->type == le_result)) {
  2380. res = (odbc_result *)p->ptr;
  2381. if (res->conn_ptr == conn) {
  2382. zend_list_close(p);
  2383. }
  2384. }
  2385. } ZEND_HASH_FOREACH_END();
  2386. zend_list_close(Z_RES_P(pv_conn));
  2387. if(is_pconn){
  2388. zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) _close_pconn_with_res, (void *) Z_RES_P(pv_conn));
  2389. }
  2390. }
  2391. /* }}} */
  2392. /* {{{ proto int odbc_num_rows(resource result_id)
  2393. Get number of rows in a result */
  2394. PHP_FUNCTION(odbc_num_rows)
  2395. {
  2396. odbc_result *result;
  2397. SQLLEN rows;
  2398. zval *pv_res;
  2399. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  2400. return;
  2401. }
  2402. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2403. RETURN_FALSE;
  2404. }
  2405. SQLRowCount(result->stmt, &rows);
  2406. RETURN_LONG(rows);
  2407. }
  2408. /* }}} */
  2409. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
  2410. /* {{{ proto bool odbc_next_result(resource result_id)
  2411. Checks if multiple results are available */
  2412. PHP_FUNCTION(odbc_next_result)
  2413. {
  2414. odbc_result *result;
  2415. zval *pv_res;
  2416. int rc, i;
  2417. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  2418. return;
  2419. }
  2420. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2421. RETURN_FALSE;
  2422. }
  2423. if (result->values) {
  2424. for(i = 0; i < result->numcols; i++) {
  2425. if (result->values[i].value) {
  2426. efree(result->values[i].value);
  2427. }
  2428. }
  2429. efree(result->values);
  2430. result->values = NULL;
  2431. result->numcols = 0;
  2432. }
  2433. result->fetched = 0;
  2434. rc = SQLMoreResults(result->stmt);
  2435. if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) {
  2436. rc = SQLFreeStmt(result->stmt, SQL_UNBIND);
  2437. SQLNumParams(result->stmt, &(result->numparams));
  2438. SQLNumResultCols(result->stmt, &(result->numcols));
  2439. if (result->numcols > 0) {
  2440. if (!odbc_bindcols(result)) {
  2441. efree(result);
  2442. RETVAL_FALSE;
  2443. }
  2444. } else {
  2445. result->values = NULL;
  2446. }
  2447. RETURN_TRUE;
  2448. } else if (rc == SQL_NO_DATA_FOUND) {
  2449. RETURN_FALSE;
  2450. } else {
  2451. odbc_sql_error(result->conn_ptr, result->stmt, "SQLMoreResults");
  2452. RETURN_FALSE;
  2453. }
  2454. }
  2455. /* }}} */
  2456. #endif
  2457. /* {{{ proto int odbc_num_fields(resource result_id)
  2458. Get number of columns in a result */
  2459. PHP_FUNCTION(odbc_num_fields)
  2460. {
  2461. odbc_result *result;
  2462. zval *pv_res;
  2463. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
  2464. return;
  2465. }
  2466. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2467. RETURN_FALSE;
  2468. }
  2469. RETURN_LONG(result->numcols);
  2470. }
  2471. /* }}} */
  2472. /* {{{ proto string odbc_field_name(resource result_id, int field_number)
  2473. Get a column name */
  2474. PHP_FUNCTION(odbc_field_name)
  2475. {
  2476. odbc_result *result;
  2477. zval *pv_res;
  2478. zend_long pv_num;
  2479. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &pv_res, &pv_num) == FAILURE) {
  2480. return;
  2481. }
  2482. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2483. RETURN_FALSE;
  2484. }
  2485. if (result->numcols == 0) {
  2486. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  2487. RETURN_FALSE;
  2488. }
  2489. if (pv_num > result->numcols) {
  2490. php_error_docref(NULL, E_WARNING, "Field index larger than number of fields");
  2491. RETURN_FALSE;
  2492. }
  2493. if (pv_num < 1) {
  2494. php_error_docref(NULL, E_WARNING, "Field numbering starts at 1");
  2495. RETURN_FALSE;
  2496. }
  2497. RETURN_STRING(result->values[pv_num - 1].name);
  2498. }
  2499. /* }}} */
  2500. /* {{{ proto string odbc_field_type(resource result_id, int field_number)
  2501. Get the datatype of a column */
  2502. PHP_FUNCTION(odbc_field_type)
  2503. {
  2504. odbc_result *result;
  2505. char tmp[32];
  2506. SQLSMALLINT tmplen;
  2507. zval *pv_res;
  2508. zend_long pv_num;
  2509. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &pv_res, &pv_num) == FAILURE) {
  2510. return;
  2511. }
  2512. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2513. RETURN_FALSE;
  2514. }
  2515. if (result->numcols == 0) {
  2516. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  2517. RETURN_FALSE;
  2518. }
  2519. if (pv_num > result->numcols) {
  2520. php_error_docref(NULL, E_WARNING, "Field index larger than number of fields");
  2521. RETURN_FALSE;
  2522. }
  2523. if (pv_num < 1) {
  2524. php_error_docref(NULL, E_WARNING, "Field numbering starts at 1");
  2525. RETURN_FALSE;
  2526. }
  2527. PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
  2528. RETURN_STRING(tmp)
  2529. }
  2530. /* }}} */
  2531. /* {{{ proto int odbc_field_len(resource result_id, int field_number)
  2532. Get the length (precision) of a column */
  2533. PHP_FUNCTION(odbc_field_len)
  2534. {
  2535. odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2536. }
  2537. /* }}} */
  2538. /* {{{ proto int odbc_field_scale(resource result_id, int field_number)
  2539. Get the scale of a column */
  2540. PHP_FUNCTION(odbc_field_scale)
  2541. {
  2542. odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2543. }
  2544. /* }}} */
  2545. /* {{{ proto int odbc_field_num(resource result_id, string field_name)
  2546. Return column number */
  2547. PHP_FUNCTION(odbc_field_num)
  2548. {
  2549. char *fname;
  2550. size_t i, field_ind, fname_len;
  2551. odbc_result *result;
  2552. zval *pv_res;
  2553. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &pv_res, &fname, &fname_len) == FAILURE) {
  2554. return;
  2555. }
  2556. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
  2557. RETURN_FALSE;
  2558. }
  2559. if (result->numcols == 0) {
  2560. php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
  2561. RETURN_FALSE;
  2562. }
  2563. field_ind = -1;
  2564. for(i = 0; i < result->numcols; i++) {
  2565. if (strcasecmp(result->values[i].name, fname) == 0) {
  2566. field_ind = i + 1;
  2567. }
  2568. }
  2569. if (field_ind == -1) {
  2570. RETURN_FALSE;
  2571. }
  2572. RETURN_LONG(field_ind);
  2573. }
  2574. /* }}} */
  2575. /* {{{ proto mixed odbc_autocommit(resource connection_id [, int OnOff])
  2576. Toggle autocommit mode or get status */
  2577. /* There can be problems with pconnections!*/
  2578. PHP_FUNCTION(odbc_autocommit)
  2579. {
  2580. odbc_connection *conn;
  2581. RETCODE rc;
  2582. zval *pv_conn;
  2583. zend_long pv_onoff = 0;
  2584. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &pv_conn, &pv_onoff) == FAILURE) {
  2585. return;
  2586. }
  2587. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2588. RETURN_FALSE;
  2589. }
  2590. if (ZEND_NUM_ARGS() > 1) {
  2591. rc = SQLSetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (pv_onoff) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
  2592. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2593. odbc_sql_error(conn, SQL_NULL_HSTMT, "Set autocommit");
  2594. RETURN_FALSE;
  2595. }
  2596. RETVAL_TRUE;
  2597. } else {
  2598. SQLINTEGER status;
  2599. rc = SQLGetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status);
  2600. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2601. odbc_sql_error(conn, SQL_NULL_HSTMT, "Get commit status");
  2602. RETURN_FALSE;
  2603. }
  2604. RETVAL_LONG((zend_long)status);
  2605. }
  2606. }
  2607. /* }}} */
  2608. /* {{{ proto bool odbc_commit(resource connection_id)
  2609. Commit an ODBC transaction */
  2610. PHP_FUNCTION(odbc_commit)
  2611. {
  2612. odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2613. }
  2614. /* }}} */
  2615. /* {{{ proto bool odbc_rollback(resource connection_id)
  2616. Rollback a transaction */
  2617. PHP_FUNCTION(odbc_rollback)
  2618. {
  2619. odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2620. }
  2621. /* }}} */
  2622. /* {{{ php_odbc_lasterror */
  2623. static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode)
  2624. {
  2625. odbc_connection *conn;
  2626. zval *pv_handle;
  2627. char *ret;
  2628. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &pv_handle) == FAILURE) {
  2629. return;
  2630. }
  2631. if (ZEND_NUM_ARGS() == 1) {
  2632. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_handle), "ODBC-Link", le_conn, le_pconn))) {
  2633. RETURN_FALSE;
  2634. }
  2635. if (mode == 0) {
  2636. ret = conn->laststate;
  2637. } else {
  2638. ret = conn->lasterrormsg;
  2639. }
  2640. } else {
  2641. if (mode == 0) {
  2642. ret = ODBCG(laststate);
  2643. } else {
  2644. ret = ODBCG(lasterrormsg);
  2645. }
  2646. }
  2647. RETURN_STRING(ret);
  2648. }
  2649. /* }}} */
  2650. /* {{{ proto string odbc_error([resource connection_id])
  2651. Get the last error code */
  2652. PHP_FUNCTION(odbc_error)
  2653. {
  2654. php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2655. }
  2656. /* }}} */
  2657. /* {{{ proto string odbc_errormsg([resource connection_id])
  2658. Get the last error message */
  2659. PHP_FUNCTION(odbc_errormsg)
  2660. {
  2661. php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2662. }
  2663. /* }}} */
  2664. /* {{{ proto bool odbc_setoption(resource conn_id|result_id, int which, int option, int value)
  2665. Sets connection or statement options */
  2666. /* This one has to be used carefully. We can't allow to set connection options for
  2667. persistent connections. I think that SetStmtOption is of little use, since most
  2668. of those can only be specified before preparing/executing statements.
  2669. On the other hand, they can be made connection wide default through SetConnectOption
  2670. - but will be overidden by calls to SetStmtOption() in odbc_prepare/odbc_do
  2671. */
  2672. PHP_FUNCTION(odbc_setoption)
  2673. {
  2674. odbc_connection *conn;
  2675. odbc_result *result;
  2676. RETCODE rc;
  2677. zval *pv_handle;
  2678. zend_long pv_which, pv_opt, pv_val;
  2679. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &pv_handle, &pv_which, &pv_opt, &pv_val) == FAILURE) {
  2680. return;
  2681. }
  2682. switch (pv_which) {
  2683. case 1: /* SQLSetConnectOption */
  2684. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_handle), "ODBC-Link", le_conn, le_pconn))) {
  2685. RETURN_FALSE;
  2686. }
  2687. if (conn->persistent) {
  2688. php_error_docref(NULL, E_WARNING, "Unable to set option for persistent connection");
  2689. RETURN_FALSE;
  2690. }
  2691. rc = SQLSetConnectOption(conn->hdbc, (unsigned short) pv_opt, pv_val);
  2692. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2693. odbc_sql_error(conn, SQL_NULL_HSTMT, "SetConnectOption");
  2694. RETURN_FALSE;
  2695. }
  2696. break;
  2697. case 2: /* SQLSetStmtOption */
  2698. if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_handle), "ODBC result", le_result)) == NULL) {
  2699. RETURN_FALSE;
  2700. }
  2701. rc = SQLSetStmtOption(result->stmt, (unsigned short) pv_opt, pv_val);
  2702. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2703. odbc_sql_error(result->conn_ptr, result->stmt, "SetStmtOption");
  2704. RETURN_FALSE;
  2705. }
  2706. break;
  2707. default:
  2708. php_error_docref(NULL, E_WARNING, "Unknown option type");
  2709. RETURN_FALSE;
  2710. break;
  2711. }
  2712. RETURN_TRUE;
  2713. }
  2714. /* }}} */
  2715. /*
  2716. * metadata functions
  2717. */
  2718. /* {{{ proto resource odbc_tables(resource connection_id [, string qualifier [, string owner [, string name [, string table_types]]]])
  2719. Call the SQLTables function */
  2720. PHP_FUNCTION(odbc_tables)
  2721. {
  2722. zval *pv_conn;
  2723. odbc_result *result = NULL;
  2724. odbc_connection *conn;
  2725. char *cat = NULL, *schema = NULL, *table = NULL, *type = NULL;
  2726. size_t cat_len = 0, schema_len = 0, table_len = 0, type_len = 0;
  2727. RETCODE rc;
  2728. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  2729. &table, &table_len, &type, &type_len) == FAILURE) {
  2730. return;
  2731. }
  2732. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2733. RETURN_FALSE;
  2734. }
  2735. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2736. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  2737. if (rc == SQL_INVALID_HANDLE) {
  2738. efree(result);
  2739. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2740. RETURN_FALSE;
  2741. }
  2742. if (rc == SQL_ERROR) {
  2743. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2744. efree(result);
  2745. RETURN_FALSE;
  2746. }
  2747. /* This hack is needed to access table information in Access databases (fmk) */
  2748. if (table && table_len && schema && schema_len == 0) {
  2749. schema = NULL;
  2750. }
  2751. rc = SQLTables(result->stmt,
  2752. cat, SAFE_SQL_NTS(cat),
  2753. schema, SAFE_SQL_NTS(schema),
  2754. table, SAFE_SQL_NTS(table),
  2755. type, SAFE_SQL_NTS(type));
  2756. if (rc == SQL_ERROR) {
  2757. odbc_sql_error(conn, result->stmt, "SQLTables");
  2758. efree(result);
  2759. RETURN_FALSE;
  2760. }
  2761. result->numparams = 0;
  2762. SQLNumResultCols(result->stmt, &(result->numcols));
  2763. if (result->numcols > 0) {
  2764. if (!odbc_bindcols(result)) {
  2765. efree(result);
  2766. RETURN_FALSE;
  2767. }
  2768. } else {
  2769. result->values = NULL;
  2770. }
  2771. result->conn_ptr = conn;
  2772. result->fetched = 0;
  2773. RETURN_RES(zend_register_resource(result, le_result));
  2774. }
  2775. /* }}} */
  2776. /* {{{ proto resource odbc_columns(resource connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]])
  2777. Returns a result identifier that can be used to fetch a list of column names in specified tables */
  2778. PHP_FUNCTION(odbc_columns)
  2779. {
  2780. zval *pv_conn;
  2781. odbc_result *result = NULL;
  2782. odbc_connection *conn;
  2783. char *cat = NULL, *schema = NULL, *table = NULL, *column = NULL;
  2784. size_t cat_len = 0, schema_len = 0, table_len = 0, column_len = 0;
  2785. RETCODE rc;
  2786. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  2787. &table, &table_len, &column, &column_len) == FAILURE) {
  2788. return;
  2789. }
  2790. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2791. RETURN_FALSE;
  2792. }
  2793. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2794. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  2795. if (rc == SQL_INVALID_HANDLE) {
  2796. efree(result);
  2797. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2798. RETURN_FALSE;
  2799. }
  2800. if (rc == SQL_ERROR) {
  2801. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2802. efree(result);
  2803. RETURN_FALSE;
  2804. }
  2805. /*
  2806. * Needed to make MS Access happy
  2807. */
  2808. if (table && table_len && schema && schema_len == 0) {
  2809. schema = NULL;
  2810. }
  2811. rc = SQLColumns(result->stmt,
  2812. cat, (SQLSMALLINT) cat_len,
  2813. schema, (SQLSMALLINT) schema_len,
  2814. table, (SQLSMALLINT) table_len,
  2815. column, (SQLSMALLINT) column_len);
  2816. if (rc == SQL_ERROR) {
  2817. odbc_sql_error(conn, result->stmt, "SQLColumns");
  2818. efree(result);
  2819. RETURN_FALSE;
  2820. }
  2821. result->numparams = 0;
  2822. SQLNumResultCols(result->stmt, &(result->numcols));
  2823. if (result->numcols > 0) {
  2824. if (!odbc_bindcols(result)) {
  2825. efree(result);
  2826. RETURN_FALSE;
  2827. }
  2828. } else {
  2829. result->values = NULL;
  2830. }
  2831. result->conn_ptr = conn;
  2832. result->fetched = 0;
  2833. RETURN_RES(zend_register_resource(result, le_result));
  2834. }
  2835. /* }}} */
  2836. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  2837. /* {{{ proto resource odbc_columnprivileges(resource connection_id, string catalog, string schema, string table, string column)
  2838. Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table */
  2839. PHP_FUNCTION(odbc_columnprivileges)
  2840. {
  2841. zval *pv_conn;
  2842. odbc_result *result = NULL;
  2843. odbc_connection *conn;
  2844. char *cat = NULL, *schema, *table, *column;
  2845. size_t cat_len = 0, schema_len, table_len, column_len;
  2846. RETCODE rc;
  2847. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  2848. &table, &table_len, &column, &column_len) == FAILURE) {
  2849. return;
  2850. }
  2851. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2852. RETURN_FALSE;
  2853. }
  2854. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2855. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  2856. if (rc == SQL_INVALID_HANDLE) {
  2857. efree(result);
  2858. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2859. RETURN_FALSE;
  2860. }
  2861. if (rc == SQL_ERROR) {
  2862. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2863. efree(result);
  2864. RETURN_FALSE;
  2865. }
  2866. rc = SQLColumnPrivileges(result->stmt,
  2867. cat, SAFE_SQL_NTS(cat),
  2868. schema, SAFE_SQL_NTS(schema),
  2869. table, SAFE_SQL_NTS(table),
  2870. column, SAFE_SQL_NTS(column));
  2871. if (rc == SQL_ERROR) {
  2872. odbc_sql_error(conn, result->stmt, "SQLColumnPrivileges");
  2873. efree(result);
  2874. RETURN_FALSE;
  2875. }
  2876. result->numparams = 0;
  2877. SQLNumResultCols(result->stmt, &(result->numcols));
  2878. if (result->numcols > 0) {
  2879. if (!odbc_bindcols(result)) {
  2880. efree(result);
  2881. RETURN_FALSE;
  2882. }
  2883. } else {
  2884. result->values = NULL;
  2885. }
  2886. result->conn_ptr = conn;
  2887. result->fetched = 0;
  2888. RETURN_RES(zend_register_resource(result, le_result));
  2889. }
  2890. /* }}} */
  2891. #endif /* HAVE_DBMAKER || HAVE_SOLID*/
  2892. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  2893. /* {{{ proto resource odbc_foreignkeys(resource connection_id, string pk_qualifier, string pk_owner, string pk_table, string fk_qualifier, string fk_owner, string fk_table)
  2894. Returns a result identifier to either a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table */
  2895. PHP_FUNCTION(odbc_foreignkeys)
  2896. {
  2897. zval *pv_conn;
  2898. odbc_result *result = NULL;
  2899. odbc_connection *conn;
  2900. char *pcat = NULL, *pschema, *ptable, *fcat, *fschema, *ftable;
  2901. size_t pcat_len = 0, pschema_len, ptable_len, fcat_len, fschema_len, ftable_len;
  2902. RETCODE rc;
  2903. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs!sssss", &pv_conn, &pcat, &pcat_len, &pschema, &pschema_len,
  2904. &ptable, &ptable_len, &fcat, &fcat_len, &fschema, &fschema_len, &ftable, &ftable_len) == FAILURE) {
  2905. return;
  2906. }
  2907. #if defined(HAVE_DBMAKER) || defined(HAVE_IBMDB2)
  2908. #define EMPTY_TO_NULL(xstr) \
  2909. if ((int)strlen((xstr)) == 0) (xstr) = NULL
  2910. EMPTY_TO_NULL(pcat);
  2911. EMPTY_TO_NULL(pschema);
  2912. EMPTY_TO_NULL(ptable);
  2913. EMPTY_TO_NULL(fcat);
  2914. EMPTY_TO_NULL(fschema);
  2915. EMPTY_TO_NULL(ftable);
  2916. #endif
  2917. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2918. RETURN_FALSE;
  2919. }
  2920. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2921. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  2922. if (rc == SQL_INVALID_HANDLE) {
  2923. efree(result);
  2924. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2925. RETURN_FALSE;
  2926. }
  2927. if (rc == SQL_ERROR) {
  2928. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2929. efree(result);
  2930. RETURN_FALSE;
  2931. }
  2932. rc = SQLForeignKeys(result->stmt,
  2933. pcat, SAFE_SQL_NTS(pcat),
  2934. pschema, SAFE_SQL_NTS(pschema),
  2935. ptable, SAFE_SQL_NTS(ptable),
  2936. fcat, SAFE_SQL_NTS(fcat),
  2937. fschema, SAFE_SQL_NTS(fschema),
  2938. ftable, SAFE_SQL_NTS(ftable) );
  2939. if (rc == SQL_ERROR) {
  2940. odbc_sql_error(conn, result->stmt, "SQLForeignKeys");
  2941. efree(result);
  2942. RETURN_FALSE;
  2943. }
  2944. result->numparams = 0;
  2945. SQLNumResultCols(result->stmt, &(result->numcols));
  2946. if (result->numcols > 0) {
  2947. if (!odbc_bindcols(result)) {
  2948. efree(result);
  2949. RETURN_FALSE;
  2950. }
  2951. } else {
  2952. result->values = NULL;
  2953. }
  2954. result->conn_ptr = conn;
  2955. result->fetched = 0;
  2956. RETURN_RES(zend_register_resource(result, le_result));
  2957. }
  2958. /* }}} */
  2959. #endif /* HAVE_SOLID */
  2960. /* {{{ proto resource odbc_gettypeinfo(resource connection_id [, int data_type])
  2961. Returns a result identifier containing information about data types supported by the data source */
  2962. PHP_FUNCTION(odbc_gettypeinfo)
  2963. {
  2964. zval *pv_conn;
  2965. zend_long pv_data_type = SQL_ALL_TYPES;
  2966. odbc_result *result = NULL;
  2967. odbc_connection *conn;
  2968. RETCODE rc;
  2969. SQLSMALLINT data_type;
  2970. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &pv_conn, &pv_data_type) == FAILURE) {
  2971. return;
  2972. }
  2973. data_type = (SQLSMALLINT) pv_data_type;
  2974. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  2975. RETURN_FALSE;
  2976. }
  2977. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2978. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  2979. if (rc == SQL_INVALID_HANDLE) {
  2980. efree(result);
  2981. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2982. RETURN_FALSE;
  2983. }
  2984. if (rc == SQL_ERROR) {
  2985. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2986. efree(result);
  2987. RETURN_FALSE;
  2988. }
  2989. rc = SQLGetTypeInfo(result->stmt, data_type );
  2990. if (rc == SQL_ERROR) {
  2991. odbc_sql_error(conn, result->stmt, "SQLGetTypeInfo");
  2992. efree(result);
  2993. RETURN_FALSE;
  2994. }
  2995. result->numparams = 0;
  2996. SQLNumResultCols(result->stmt, &(result->numcols));
  2997. if (result->numcols > 0) {
  2998. if (!odbc_bindcols(result)) {
  2999. efree(result);
  3000. RETURN_FALSE;
  3001. }
  3002. } else {
  3003. result->values = NULL;
  3004. }
  3005. result->conn_ptr = conn;
  3006. result->fetched = 0;
  3007. RETURN_RES(zend_register_resource(result, le_result));
  3008. }
  3009. /* }}} */
  3010. /* {{{ proto resource odbc_primarykeys(resource connection_id, string qualifier, string owner, string table)
  3011. Returns a result identifier listing the column names that comprise the primary key for a table */
  3012. PHP_FUNCTION(odbc_primarykeys)
  3013. {
  3014. zval *pv_conn;
  3015. odbc_result *result = NULL;
  3016. odbc_connection *conn;
  3017. char *cat = NULL, *schema = NULL, *table = NULL;
  3018. size_t cat_len = 0, schema_len, table_len;
  3019. RETCODE rc;
  3020. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
  3021. return;
  3022. }
  3023. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  3024. RETURN_FALSE;
  3025. }
  3026. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3027. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  3028. if (rc == SQL_INVALID_HANDLE) {
  3029. efree(result);
  3030. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3031. RETURN_FALSE;
  3032. }
  3033. if (rc == SQL_ERROR) {
  3034. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3035. efree(result);
  3036. RETURN_FALSE;
  3037. }
  3038. rc = SQLPrimaryKeys(result->stmt,
  3039. cat, SAFE_SQL_NTS(cat),
  3040. schema, SAFE_SQL_NTS(schema),
  3041. table, SAFE_SQL_NTS(table) );
  3042. if (rc == SQL_ERROR) {
  3043. odbc_sql_error(conn, result->stmt, "SQLPrimaryKeys");
  3044. efree(result);
  3045. RETURN_FALSE;
  3046. }
  3047. result->numparams = 0;
  3048. SQLNumResultCols(result->stmt, &(result->numcols));
  3049. if (result->numcols > 0) {
  3050. if (!odbc_bindcols(result)) {
  3051. efree(result);
  3052. RETURN_FALSE;
  3053. }
  3054. } else {
  3055. result->values = NULL;
  3056. }
  3057. result->conn_ptr = conn;
  3058. result->fetched = 0;
  3059. RETURN_RES(zend_register_resource(result, le_result));
  3060. }
  3061. /* }}} */
  3062. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  3063. /* {{{ proto resource odbc_procedurecolumns(resource connection_id [, string qualifier, string owner, string proc, string column])
  3064. Returns a result identifier containing the list of input and output parameters, as well as the columns that make up the result set for the specified procedures */
  3065. PHP_FUNCTION(odbc_procedurecolumns)
  3066. {
  3067. zval *pv_conn;
  3068. odbc_result *result = NULL;
  3069. odbc_connection *conn;
  3070. char *cat = NULL, *schema = NULL, *proc = NULL, *col = NULL;
  3071. size_t cat_len = 0, schema_len = 0, proc_len = 0, col_len = 0;
  3072. RETCODE rc;
  3073. if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 5) {
  3074. WRONG_PARAM_COUNT;
  3075. }
  3076. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  3077. &proc, &proc_len, &col, &col_len) == FAILURE) {
  3078. return;
  3079. }
  3080. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  3081. RETURN_FALSE;
  3082. }
  3083. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3084. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  3085. if (rc == SQL_INVALID_HANDLE) {
  3086. efree(result);
  3087. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3088. RETURN_FALSE;
  3089. }
  3090. if (rc == SQL_ERROR) {
  3091. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3092. efree(result);
  3093. RETURN_FALSE;
  3094. }
  3095. rc = SQLProcedureColumns(result->stmt,
  3096. cat, SAFE_SQL_NTS(cat),
  3097. schema, SAFE_SQL_NTS(schema),
  3098. proc, SAFE_SQL_NTS(proc),
  3099. col, SAFE_SQL_NTS(col) );
  3100. if (rc == SQL_ERROR) {
  3101. odbc_sql_error(conn, result->stmt, "SQLProcedureColumns");
  3102. efree(result);
  3103. RETURN_FALSE;
  3104. }
  3105. result->numparams = 0;
  3106. SQLNumResultCols(result->stmt, &(result->numcols));
  3107. if (result->numcols > 0) {
  3108. if (!odbc_bindcols(result)) {
  3109. efree(result);
  3110. RETURN_FALSE;
  3111. }
  3112. } else {
  3113. result->values = NULL;
  3114. }
  3115. result->conn_ptr = conn;
  3116. result->fetched = 0;
  3117. RETURN_RES(zend_register_resource(result, le_result));
  3118. }
  3119. /* }}} */
  3120. #endif /* HAVE_SOLID */
  3121. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  3122. /* {{{ proto resource odbc_procedures(resource connection_id [, string qualifier, string owner, string name])
  3123. Returns a result identifier containg the list of procedure names in a datasource */
  3124. PHP_FUNCTION(odbc_procedures)
  3125. {
  3126. zval *pv_conn;
  3127. odbc_result *result = NULL;
  3128. odbc_connection *conn;
  3129. char *cat = NULL, *schema = NULL, *proc = NULL;
  3130. size_t cat_len = 0, schema_len = 0, proc_len = 0;
  3131. RETCODE rc;
  3132. if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 4) {
  3133. WRONG_PARAM_COUNT;
  3134. }
  3135. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|s!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &proc, &proc_len) == FAILURE) {
  3136. return;
  3137. }
  3138. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  3139. RETURN_FALSE;
  3140. }
  3141. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3142. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  3143. if (rc == SQL_INVALID_HANDLE) {
  3144. efree(result);
  3145. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3146. RETURN_FALSE;
  3147. }
  3148. if (rc == SQL_ERROR) {
  3149. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3150. efree(result);
  3151. RETURN_FALSE;
  3152. }
  3153. rc = SQLProcedures(result->stmt,
  3154. cat, SAFE_SQL_NTS(cat),
  3155. schema, SAFE_SQL_NTS(schema),
  3156. proc, SAFE_SQL_NTS(proc) );
  3157. if (rc == SQL_ERROR) {
  3158. odbc_sql_error(conn, result->stmt, "SQLProcedures");
  3159. efree(result);
  3160. RETURN_FALSE;
  3161. }
  3162. result->numparams = 0;
  3163. SQLNumResultCols(result->stmt, &(result->numcols));
  3164. if (result->numcols > 0) {
  3165. if (!odbc_bindcols(result)) {
  3166. efree(result);
  3167. RETURN_FALSE;
  3168. }
  3169. } else {
  3170. result->values = NULL;
  3171. }
  3172. result->conn_ptr = conn;
  3173. result->fetched = 0;
  3174. RETURN_RES(zend_register_resource(result, le_result));
  3175. }
  3176. /* }}} */
  3177. #endif /* HAVE_SOLID */
  3178. /* {{{ proto resource odbc_specialcolumns(resource connection_id, int type, string qualifier, string owner, string table, int scope, int nullable)
  3179. Returns a result identifier containing either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction */
  3180. PHP_FUNCTION(odbc_specialcolumns)
  3181. {
  3182. zval *pv_conn;
  3183. zend_long vtype, vscope, vnullable;
  3184. odbc_result *result = NULL;
  3185. odbc_connection *conn;
  3186. char *cat = NULL, *schema = NULL, *name = NULL;
  3187. size_t cat_len = 0, schema_len, name_len;
  3188. SQLUSMALLINT type, scope, nullable;
  3189. RETCODE rc;
  3190. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rls!ssll", &pv_conn, &vtype, &cat, &cat_len, &schema, &schema_len,
  3191. &name, &name_len, &vscope, &vnullable) == FAILURE) {
  3192. return;
  3193. }
  3194. type = (SQLUSMALLINT) vtype;
  3195. scope = (SQLUSMALLINT) vscope;
  3196. nullable = (SQLUSMALLINT) vnullable;
  3197. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  3198. RETURN_FALSE;
  3199. }
  3200. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3201. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  3202. if (rc == SQL_INVALID_HANDLE) {
  3203. efree(result);
  3204. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3205. RETURN_FALSE;
  3206. }
  3207. if (rc == SQL_ERROR) {
  3208. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3209. efree(result);
  3210. RETURN_FALSE;
  3211. }
  3212. rc = SQLSpecialColumns(result->stmt,
  3213. type,
  3214. cat, SAFE_SQL_NTS(cat),
  3215. schema, SAFE_SQL_NTS(schema),
  3216. name, SAFE_SQL_NTS(name),
  3217. scope,
  3218. nullable);
  3219. if (rc == SQL_ERROR) {
  3220. odbc_sql_error(conn, result->stmt, "SQLSpecialColumns");
  3221. efree(result);
  3222. RETURN_FALSE;
  3223. }
  3224. result->numparams = 0;
  3225. SQLNumResultCols(result->stmt, &(result->numcols));
  3226. if (result->numcols > 0) {
  3227. if (!odbc_bindcols(result)) {
  3228. efree(result);
  3229. RETURN_FALSE;
  3230. }
  3231. } else {
  3232. result->values = NULL;
  3233. }
  3234. result->conn_ptr = conn;
  3235. result->fetched = 0;
  3236. RETURN_RES(zend_register_resource(result, le_result));
  3237. }
  3238. /* }}} */
  3239. /* {{{ proto resource odbc_statistics(resource connection_id, string qualifier, string owner, string name, int unique, int accuracy)
  3240. Returns a result identifier that contains statistics about a single table and the indexes associated with the table */
  3241. PHP_FUNCTION(odbc_statistics)
  3242. {
  3243. zval *pv_conn;
  3244. zend_long vunique, vreserved;
  3245. odbc_result *result = NULL;
  3246. odbc_connection *conn;
  3247. char *cat = NULL, *schema, *name;
  3248. size_t cat_len = 0, schema_len, name_len;
  3249. SQLUSMALLINT unique, reserved;
  3250. RETCODE rc;
  3251. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs!ssll", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  3252. &name, &name_len, &vunique, &vreserved) == FAILURE) {
  3253. return;
  3254. }
  3255. unique = (SQLUSMALLINT) vunique;
  3256. reserved = (SQLUSMALLINT) vreserved;
  3257. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  3258. RETURN_FALSE;
  3259. }
  3260. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3261. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  3262. if (rc == SQL_INVALID_HANDLE) {
  3263. efree(result);
  3264. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3265. RETURN_FALSE;
  3266. }
  3267. if (rc == SQL_ERROR) {
  3268. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3269. efree(result);
  3270. RETURN_FALSE;
  3271. }
  3272. rc = SQLStatistics(result->stmt,
  3273. cat, SAFE_SQL_NTS(cat),
  3274. schema, SAFE_SQL_NTS(schema),
  3275. name, SAFE_SQL_NTS(name),
  3276. unique,
  3277. reserved);
  3278. if (rc == SQL_ERROR) {
  3279. odbc_sql_error(conn, result->stmt, "SQLStatistics");
  3280. efree(result);
  3281. RETURN_FALSE;
  3282. }
  3283. result->numparams = 0;
  3284. SQLNumResultCols(result->stmt, &(result->numcols));
  3285. if (result->numcols > 0) {
  3286. if (!odbc_bindcols(result)) {
  3287. efree(result);
  3288. RETURN_FALSE;
  3289. }
  3290. } else {
  3291. result->values = NULL;
  3292. }
  3293. result->conn_ptr = conn;
  3294. result->fetched = 0;
  3295. RETURN_RES(zend_register_resource(result, le_result));
  3296. }
  3297. /* }}} */
  3298. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  3299. /* {{{ proto resource odbc_tableprivileges(resource connection_id, string qualifier, string owner, string name)
  3300. Returns a result identifier containing a list of tables and the privileges associated with each table */
  3301. PHP_FUNCTION(odbc_tableprivileges)
  3302. {
  3303. zval *pv_conn;
  3304. odbc_result *result = NULL;
  3305. odbc_connection *conn;
  3306. char *cat = NULL, *schema = NULL, *table = NULL;
  3307. size_t cat_len = 0, schema_len, table_len;
  3308. RETCODE rc;
  3309. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
  3310. return;
  3311. }
  3312. if (!(conn = (odbc_connection *)zend_fetch_resource2(Z_RES_P(pv_conn), "ODBC-Link", le_conn, le_pconn))) {
  3313. RETURN_FALSE;
  3314. }
  3315. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3316. rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
  3317. if (rc == SQL_INVALID_HANDLE) {
  3318. efree(result);
  3319. php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3320. RETURN_FALSE;
  3321. }
  3322. if (rc == SQL_ERROR) {
  3323. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3324. efree(result);
  3325. RETURN_FALSE;
  3326. }
  3327. rc = SQLTablePrivileges(result->stmt,
  3328. cat, SAFE_SQL_NTS(cat),
  3329. schema, SAFE_SQL_NTS(schema),
  3330. table, SAFE_SQL_NTS(table));
  3331. if (rc == SQL_ERROR) {
  3332. odbc_sql_error(conn, result->stmt, "SQLTablePrivileges");
  3333. efree(result);
  3334. RETURN_FALSE;
  3335. }
  3336. result->numparams = 0;
  3337. SQLNumResultCols(result->stmt, &(result->numcols));
  3338. if (result->numcols > 0) {
  3339. if (!odbc_bindcols(result)) {
  3340. efree(result);
  3341. RETURN_FALSE;
  3342. }
  3343. } else {
  3344. result->values = NULL;
  3345. }
  3346. result->conn_ptr = conn;
  3347. result->fetched = 0;
  3348. RETURN_RES(zend_register_resource(result, le_result));
  3349. }
  3350. /* }}} */
  3351. #endif /* HAVE_DBMAKER */
  3352. #endif /* HAVE_UODBC */
  3353. /*
  3354. * Local variables:
  3355. * tab-width: 4
  3356. * c-basic-offset: 4
  3357. * End:
  3358. * vim600: sw=4 ts=4 fdm=marker
  3359. * vim<600: sw=4 ts=4
  3360. */