PageRenderTime 142ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/concrete/libraries/3rdparty/adodb/drivers/adodb-mysqli.inc.php

https://bitbucket.org/selfeky/xclusivescardwebsite
PHP | 1269 lines | 917 code | 188 blank | 164 comment | 146 complexity | b5aa97d6867d2b4e67a9b2629fc5fe42 MD5 | raw file
  1. <?php
  2. /*
  3. V5.18 3 Sep 2012 (c) 2000-2012 John Lim (jlim#natsoft.com). All rights reserved.
  4. Released under both BSD license and Lesser GPL library license.
  5. Whenever there is any discrepancy between the two licenses,
  6. the BSD license will take precedence.
  7. Set tabs to 8.
  8. MySQL code that does not support transactions. Use mysqlt if you need transactions.
  9. Requires mysql client. Works on Windows and Unix.
  10. 21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
  11. Based on adodb 3.40
  12. */
  13. // security - hide paths
  14. if (!defined('ADODB_DIR')) die();
  15. if (! defined("_ADODB_MYSQLI_LAYER")) {
  16. define("_ADODB_MYSQLI_LAYER", 1 );
  17. // PHP5 compat...
  18. if (! defined("MYSQLI_BINARY_FLAG")) define("MYSQLI_BINARY_FLAG", 128);
  19. if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
  20. // disable adodb extension - currently incompatible.
  21. global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
  22. class ADODB_mysqli extends ADOConnection {
  23. var $databaseType = 'mysqli';
  24. var $dataProvider = 'mysql';
  25. var $hasInsertID = true;
  26. var $hasAffectedRows = true;
  27. var $metaTablesSQL = "SELECT TABLE_NAME, CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=SCHEMA()";
  28. var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
  29. var $fmtTimeStamp = "'Y-m-d H:i:s'";
  30. var $hasLimit = true;
  31. var $hasMoveFirst = true;
  32. var $hasGenID = true;
  33. var $isoDates = true; // accepts dates in ISO format
  34. var $sysDate = 'CURDATE()';
  35. var $sysTimeStamp = 'NOW()';
  36. var $hasTransactions = true;
  37. var $forceNewConnect = false;
  38. var $poorAffectedRows = true;
  39. var $clientFlags = 0;
  40. var $substr = "substring";
  41. var $port = false;
  42. var $socket = false;
  43. var $_bindInputArray = false;
  44. var $nameQuote = '`'; /// string to use to quote identifiers and names
  45. var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0));
  46. var $arrayClass = 'ADORecordSet_array_mysqli';
  47. var $multiQuery = false;
  48. function ADODB_mysqli()
  49. {
  50. // if(!extension_loaded("mysqli"))
  51. ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
  52. }
  53. function SetTransactionMode( $transaction_mode )
  54. {
  55. $this->_transmode = $transaction_mode;
  56. if (empty($transaction_mode)) {
  57. $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
  58. return;
  59. }
  60. if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
  61. $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
  62. }
  63. // returns true or false
  64. // To add: parameter int $port,
  65. // parameter string $socket
  66. function _connect($argHostname = NULL,
  67. $argUsername = NULL,
  68. $argPassword = NULL,
  69. $argDatabasename = NULL, $persist=false)
  70. {
  71. if(!extension_loaded("mysqli")) {
  72. return null;
  73. }
  74. $this->_connectionID = @mysqli_init();
  75. if (is_null($this->_connectionID)) {
  76. // mysqli_init only fails if insufficient memory
  77. if ($this->debug)
  78. ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg());
  79. return false;
  80. }
  81. /*
  82. I suggest a simple fix which would enable adodb and mysqli driver to
  83. read connection options from the standard mysql configuration file
  84. /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
  85. */
  86. foreach($this->optionFlags as $arr) {
  87. mysqli_options($this->_connectionID,$arr[0],$arr[1]);
  88. }
  89. //http ://php.net/manual/en/mysqli.persistconns.php
  90. if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname;
  91. #if (!empty($this->port)) $argHostname .= ":".$this->port;
  92. $ok = mysqli_real_connect($this->_connectionID,
  93. $argHostname,
  94. $argUsername,
  95. $argPassword,
  96. $argDatabasename,
  97. $this->port,
  98. $this->socket,
  99. $this->clientFlags);
  100. if ($ok) {
  101. if ($argDatabasename) return $this->SelectDB($argDatabasename);
  102. return true;
  103. } else {
  104. if ($this->debug)
  105. ADOConnection::outp("Could't connect : " . $this->ErrorMsg());
  106. $this->_connectionID = null;
  107. return false;
  108. }
  109. }
  110. // returns true or false
  111. // How to force a persistent connection
  112. function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
  113. {
  114. return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
  115. }
  116. // When is this used? Close old connection first?
  117. // In _connect(), check $this->forceNewConnect?
  118. function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
  119. {
  120. $this->forceNewConnect = true;
  121. return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
  122. }
  123. function IfNull( $field, $ifNull )
  124. {
  125. return " IFNULL($field, $ifNull) "; // if MySQL
  126. }
  127. // do not use $ADODB_COUNTRECS
  128. function GetOne($sql,$inputarr=false)
  129. {
  130. global $ADODB_GETONE_EOF;
  131. $ret = false;
  132. $rs = $this->Execute($sql,$inputarr);
  133. if ($rs) {
  134. if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
  135. else $ret = reset($rs->fields);
  136. $rs->Close();
  137. }
  138. return $ret;
  139. }
  140. function ServerInfo()
  141. {
  142. $arr['description'] = $this->GetOne("select version()");
  143. $arr['version'] = ADOConnection::_findvers($arr['description']);
  144. return $arr;
  145. }
  146. function BeginTrans()
  147. {
  148. if ($this->transOff) return true;
  149. $this->transCnt += 1;
  150. //$this->Execute('SET AUTOCOMMIT=0');
  151. mysqli_autocommit($this->_connectionID, false);
  152. $this->Execute('BEGIN');
  153. return true;
  154. }
  155. function CommitTrans($ok=true)
  156. {
  157. if ($this->transOff) return true;
  158. if (!$ok) return $this->RollbackTrans();
  159. if ($this->transCnt) $this->transCnt -= 1;
  160. $this->Execute('COMMIT');
  161. //$this->Execute('SET AUTOCOMMIT=1');
  162. mysqli_autocommit($this->_connectionID, true);
  163. return true;
  164. }
  165. function RollbackTrans()
  166. {
  167. if ($this->transOff) return true;
  168. if ($this->transCnt) $this->transCnt -= 1;
  169. $this->Execute('ROLLBACK');
  170. //$this->Execute('SET AUTOCOMMIT=1');
  171. mysqli_autocommit($this->_connectionID, true);
  172. return true;
  173. }
  174. function RowLock($tables,$where='',$col='1 as adodbignore')
  175. {
  176. if ($this->transCnt==0) $this->BeginTrans();
  177. if ($where) $where = ' where '.$where;
  178. $rs = $this->Execute("select $col from $tables $where for update");
  179. return !empty($rs);
  180. }
  181. // if magic quotes disabled, use mysql_real_escape_string()
  182. // From readme.htm:
  183. // Quotes a string to be sent to the database. The $magic_quotes_enabled
  184. // parameter may look funny, but the idea is if you are quoting a
  185. // string extracted from a POST/GET variable, then
  186. // pass get_magic_quotes_gpc() as the second parameter. This will
  187. // ensure that the variable is not quoted twice, once by qstr and once
  188. // by the magic_quotes_gpc.
  189. //
  190. //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
  191. function qstr($s, $magic_quotes = false)
  192. {
  193. if (is_null($s)) return 'NULL';
  194. if (!$magic_quotes) {
  195. if (PHP_VERSION >= 5)
  196. return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
  197. if ($this->replaceQuote[0] == '\\')
  198. $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
  199. return "'".str_replace("'",$this->replaceQuote,$s)."'";
  200. }
  201. // undo magic quotes for "
  202. $s = str_replace('\\"','"',$s);
  203. return "'$s'";
  204. }
  205. function _insertid()
  206. {
  207. $result = @mysqli_insert_id($this->_connectionID);
  208. if ($result == -1){
  209. if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg());
  210. }
  211. return $result;
  212. }
  213. // Only works for INSERT, UPDATE and DELETE query's
  214. function _affectedrows()
  215. {
  216. $result = @mysqli_affected_rows($this->_connectionID);
  217. if ($result == -1) {
  218. if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg());
  219. }
  220. return $result;
  221. }
  222. // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
  223. // Reference on Last_Insert_ID on the recommended way to simulate sequences
  224. var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
  225. var $_genSeqSQL = "create table %s (id int not null)";
  226. var $_genSeqCountSQL = "select count(*) from %s";
  227. var $_genSeq2SQL = "insert into %s values (%s)";
  228. var $_dropSeqSQL = "drop table %s";
  229. function CreateSequence($seqname='adodbseq',$startID=1)
  230. {
  231. if (empty($this->_genSeqSQL)) return false;
  232. $u = strtoupper($seqname);
  233. $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
  234. if (!$ok) return false;
  235. return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
  236. }
  237. function GenID($seqname='adodbseq',$startID=1)
  238. {
  239. // post-nuke sets hasGenID to false
  240. if (!$this->hasGenID) return false;
  241. $getnext = sprintf($this->_genIDSQL,$seqname);
  242. $holdtransOK = $this->_transOK; // save the current status
  243. $rs = @$this->Execute($getnext);
  244. if (!$rs) {
  245. if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
  246. $u = strtoupper($seqname);
  247. $this->Execute(sprintf($this->_genSeqSQL,$seqname));
  248. $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
  249. if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
  250. $rs = $this->Execute($getnext);
  251. }
  252. if ($rs) {
  253. $this->genID = mysqli_insert_id($this->_connectionID);
  254. $rs->Close();
  255. } else
  256. $this->genID = 0;
  257. return $this->genID;
  258. }
  259. function MetaDatabases()
  260. {
  261. $query = "SHOW DATABASES";
  262. $ret = $this->Execute($query);
  263. if ($ret && is_object($ret)){
  264. $arr = array();
  265. while (!$ret->EOF){
  266. $db = $ret->Fields('Database');
  267. if ($db != 'mysql') $arr[] = $db;
  268. $ret->MoveNext();
  269. }
  270. return $arr;
  271. }
  272. return $ret;
  273. }
  274. function MetaIndexes ($table, $primary = FALSE, $owner = false)
  275. {
  276. // save old fetch mode
  277. global $ADODB_FETCH_MODE;
  278. $false = false;
  279. $save = $ADODB_FETCH_MODE;
  280. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  281. if ($this->fetchMode !== FALSE) {
  282. $savem = $this->SetFetchMode(FALSE);
  283. }
  284. // get index details
  285. $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
  286. // restore fetchmode
  287. if (isset($savem)) {
  288. $this->SetFetchMode($savem);
  289. }
  290. $ADODB_FETCH_MODE = $save;
  291. if (!is_object($rs)) {
  292. return $false;
  293. }
  294. $indexes = array ();
  295. // parse index data into array
  296. while ($row = $rs->FetchRow()) {
  297. if ($primary == FALSE AND $row[2] == 'PRIMARY') {
  298. continue;
  299. }
  300. if (!isset($indexes[$row[2]])) {
  301. $indexes[$row[2]] = array(
  302. 'unique' => ($row[1] == 0),
  303. 'columns' => array()
  304. );
  305. }
  306. $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
  307. }
  308. // sort columns by order in the index
  309. foreach ( array_keys ($indexes) as $index )
  310. {
  311. ksort ($indexes[$index]['columns']);
  312. }
  313. return $indexes;
  314. }
  315. // Format date column in sql string given an input format that understands Y M D
  316. function SQLDate($fmt, $col=false)
  317. {
  318. if (!$col) $col = $this->sysTimeStamp;
  319. $s = 'DATE_FORMAT('.$col.",'";
  320. $concat = false;
  321. $len = strlen($fmt);
  322. for ($i=0; $i < $len; $i++) {
  323. $ch = $fmt[$i];
  324. switch($ch) {
  325. case 'Y':
  326. case 'y':
  327. $s .= '%Y';
  328. break;
  329. case 'Q':
  330. case 'q':
  331. $s .= "'),Quarter($col)";
  332. if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
  333. else $s .= ",('";
  334. $concat = true;
  335. break;
  336. case 'M':
  337. $s .= '%b';
  338. break;
  339. case 'm':
  340. $s .= '%m';
  341. break;
  342. case 'D':
  343. case 'd':
  344. $s .= '%d';
  345. break;
  346. case 'H':
  347. $s .= '%H';
  348. break;
  349. case 'h':
  350. $s .= '%I';
  351. break;
  352. case 'i':
  353. $s .= '%i';
  354. break;
  355. case 's':
  356. $s .= '%s';
  357. break;
  358. case 'a':
  359. case 'A':
  360. $s .= '%p';
  361. break;
  362. case 'w':
  363. $s .= '%w';
  364. break;
  365. case 'l':
  366. $s .= '%W';
  367. break;
  368. default:
  369. if ($ch == '\\') {
  370. $i++;
  371. $ch = substr($fmt,$i,1);
  372. }
  373. $s .= $ch;
  374. break;
  375. }
  376. }
  377. $s.="')";
  378. if ($concat) $s = "CONCAT($s)";
  379. return $s;
  380. }
  381. // returns concatenated string
  382. // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
  383. function Concat()
  384. {
  385. $s = "";
  386. $arr = func_get_args();
  387. // suggestion by andrew005@mnogo.ru
  388. $s = implode(',',$arr);
  389. if (strlen($s) > 0) return "CONCAT($s)";
  390. else return '';
  391. }
  392. // dayFraction is a day in floating point
  393. function OffsetDate($dayFraction,$date=false)
  394. {
  395. if (!$date) $date = $this->sysDate;
  396. $fraction = $dayFraction * 24 * 3600;
  397. return $date . ' + INTERVAL ' . $fraction.' SECOND';
  398. // return "from_unixtime(unix_timestamp($date)+$fraction)";
  399. }
  400. function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
  401. {
  402. // save old fetch mode
  403. global $ADODB_FETCH_MODE;
  404. $false = false;
  405. $save = $ADODB_FETCH_MODE;
  406. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  407. if ($this->fetchMode !== FALSE) {
  408. $savem = $this->SetFetchMode(FALSE);
  409. }
  410. $procedures = array ();
  411. // get index details
  412. $likepattern = '';
  413. if ($NamePattern) {
  414. $likepattern = " LIKE '".$NamePattern."'";
  415. }
  416. $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
  417. if (is_object($rs)) {
  418. // parse index data into array
  419. while ($row = $rs->FetchRow()) {
  420. $procedures[$row[1]] = array(
  421. 'type' => 'PROCEDURE',
  422. 'catalog' => '',
  423. 'schema' => '',
  424. 'remarks' => $row[7],
  425. );
  426. }
  427. }
  428. $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
  429. if (is_object($rs)) {
  430. // parse index data into array
  431. while ($row = $rs->FetchRow()) {
  432. $procedures[$row[1]] = array(
  433. 'type' => 'FUNCTION',
  434. 'catalog' => '',
  435. 'schema' => '',
  436. 'remarks' => $row[7]
  437. );
  438. }
  439. }
  440. // restore fetchmode
  441. if (isset($savem)) {
  442. $this->SetFetchMode($savem);
  443. }
  444. $ADODB_FETCH_MODE = $save;
  445. return $procedures;
  446. }
  447. function MetaTables($ttype=false,$showSchema=false,$mask=false)
  448. {
  449. $save = $this->metaTablesSQL;
  450. if ($showSchema && is_string($showSchema)) {
  451. $this->metaTablesSQL .= " from $showSchema";
  452. }
  453. if ($mask) {
  454. $mask = $this->qstr($mask);
  455. $this->metaTablesSQL .= " like $mask";
  456. }
  457. $ret = ADOConnection::MetaTables($ttype,$showSchema);
  458. $this->metaTablesSQL = $save;
  459. return $ret;
  460. }
  461. // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
  462. function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
  463. {
  464. global $ADODB_FETCH_MODE;
  465. if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
  466. if ( !empty($owner) ) {
  467. $table = "$owner.$table";
  468. }
  469. $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
  470. if ($associative) {
  471. $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
  472. } else $create_sql = $a_create_table[1];
  473. $matches = array();
  474. if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
  475. $foreign_keys = array();
  476. $num_keys = count($matches[0]);
  477. for ( $i = 0; $i < $num_keys; $i ++ ) {
  478. $my_field = explode('`, `', $matches[1][$i]);
  479. $ref_table = $matches[2][$i];
  480. $ref_field = explode('`, `', $matches[3][$i]);
  481. if ( $upper ) {
  482. $ref_table = strtoupper($ref_table);
  483. }
  484. // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976
  485. if (!isset($foreign_keys[$ref_table])) {
  486. $foreign_keys[$ref_table] = array();
  487. }
  488. $num_fields = count($my_field);
  489. for ( $j = 0; $j < $num_fields; $j ++ ) {
  490. if ( $associative ) {
  491. $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
  492. } else {
  493. $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
  494. }
  495. }
  496. }
  497. return $foreign_keys;
  498. }
  499. function MetaColumns($table, $normalize=true)
  500. {
  501. $false = false;
  502. if (!$this->metaColumnsSQL)
  503. return $false;
  504. global $ADODB_FETCH_MODE;
  505. $save = $ADODB_FETCH_MODE;
  506. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  507. if ($this->fetchMode !== false)
  508. $savem = $this->SetFetchMode(false);
  509. $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
  510. if (isset($savem)) $this->SetFetchMode($savem);
  511. $ADODB_FETCH_MODE = $save;
  512. if (!is_object($rs))
  513. return $false;
  514. $retarr = array();
  515. while (!$rs->EOF) {
  516. $fld = new ADOFieldObject();
  517. $fld->name = $rs->fields[0];
  518. $type = $rs->fields[1];
  519. // split type into type(length):
  520. $fld->scale = null;
  521. if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
  522. $fld->type = $query_array[1];
  523. $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
  524. $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
  525. } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
  526. $fld->type = $query_array[1];
  527. $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
  528. } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
  529. $fld->type = $query_array[1];
  530. $arr = explode(",",$query_array[2]);
  531. $fld->enums = $arr;
  532. $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
  533. $fld->max_length = ($zlen > 0) ? $zlen : 1;
  534. } else {
  535. $fld->type = $type;
  536. $fld->max_length = -1;
  537. }
  538. $fld->not_null = ($rs->fields[2] != 'YES');
  539. $fld->primary_key = ($rs->fields[3] == 'PRI');
  540. $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
  541. $fld->binary = (strpos($type,'blob') !== false);
  542. $fld->unsigned = (strpos($type,'unsigned') !== false);
  543. $fld->zerofill = (strpos($type,'zerofill') !== false);
  544. if (!$fld->binary) {
  545. $d = $rs->fields[4];
  546. if ($d != '' && $d != 'NULL') {
  547. $fld->has_default = true;
  548. $fld->default_value = $d;
  549. } else {
  550. $fld->has_default = false;
  551. }
  552. }
  553. if ($save == ADODB_FETCH_NUM) {
  554. $retarr[] = $fld;
  555. } else {
  556. $retarr[strtoupper($fld->name)] = $fld;
  557. }
  558. $rs->MoveNext();
  559. }
  560. $rs->Close();
  561. return $retarr;
  562. }
  563. // returns true or false
  564. function SelectDB($dbName)
  565. {
  566. // $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
  567. $this->database = $dbName;
  568. $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
  569. if ($this->_connectionID) {
  570. $result = @mysqli_select_db($this->_connectionID, $dbName);
  571. if (!$result) {
  572. ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
  573. }
  574. return $result;
  575. }
  576. return false;
  577. }
  578. // parameters use PostgreSQL convention, not MySQL
  579. function SelectLimit($sql,
  580. $nrows = -1,
  581. $offset = -1,
  582. $inputarr = false,
  583. $secs = 0)
  584. {
  585. $offsetStr = ($offset >= 0) ? "$offset," : '';
  586. if ($nrows < 0) $nrows = '18446744073709551615';
  587. if ($secs)
  588. $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
  589. else
  590. $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
  591. return $rs;
  592. }
  593. function Prepare($sql)
  594. {
  595. return $sql;
  596. $stmt = $this->_connectionID->prepare($sql);
  597. if (!$stmt) {
  598. echo $this->ErrorMsg();
  599. return $sql;
  600. }
  601. return array($sql,$stmt);
  602. }
  603. // returns queryID or false
  604. function _query($sql, $inputarr)
  605. {
  606. global $ADODB_COUNTRECS;
  607. // Move to the next recordset, or return false if there is none. In a stored proc
  608. // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
  609. // returns false. I think this is because the last "recordset" is actually just the
  610. // return value of the stored proc (ie the number of rows affected).
  611. // Commented out for reasons of performance. You should retrieve every recordset yourself.
  612. // if (!mysqli_next_result($this->connection->_connectionID)) return false;
  613. if (is_array($sql)) {
  614. // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
  615. // returns as bound variables.
  616. $stmt = $sql[1];
  617. $a = '';
  618. foreach($inputarr as $k => $v) {
  619. if (is_string($v)) $a .= 's';
  620. else if (is_integer($v)) $a .= 'i';
  621. else $a .= 'd';
  622. }
  623. $fnarr = array_merge( array($stmt,$a) , $inputarr);
  624. $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
  625. $ret = mysqli_stmt_execute($stmt);
  626. return $ret;
  627. }
  628. /*
  629. if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
  630. if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
  631. return false;
  632. }
  633. return $mysql_res;
  634. */
  635. if ($this->multiQuery) {
  636. $rs = mysqli_multi_query($this->_connectionID, $sql.';');
  637. if ($rs) {
  638. $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
  639. return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
  640. }
  641. } else {
  642. $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
  643. if ($rs) return $rs;
  644. }
  645. if($this->debug)
  646. ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
  647. return false;
  648. }
  649. /* Returns: the last error message from previous database operation */
  650. function ErrorMsg()
  651. {
  652. if (empty($this->_connectionID))
  653. $this->_errorMsg = @mysqli_connect_error();
  654. else
  655. $this->_errorMsg = @mysqli_error($this->_connectionID);
  656. return $this->_errorMsg;
  657. }
  658. /* Returns: the last error number from previous database operation */
  659. function ErrorNo()
  660. {
  661. if (empty($this->_connectionID))
  662. return @mysqli_connect_errno();
  663. else
  664. return @mysqli_errno($this->_connectionID);
  665. }
  666. // returns true or false
  667. function _close()
  668. {
  669. @mysqli_close($this->_connectionID);
  670. $this->_connectionID = false;
  671. }
  672. /*
  673. * Maximum size of C field
  674. */
  675. function CharMax()
  676. {
  677. return 255;
  678. }
  679. /*
  680. * Maximum size of X field
  681. */
  682. function TextMax()
  683. {
  684. return 4294967295;
  685. }
  686. // this is a set of functions for managing client encoding - very important if the encodings
  687. // of your database and your output target (i.e. HTML) don't match
  688. // for instance, you may have UTF8 database and server it on-site as latin1 etc.
  689. // GetCharSet - get the name of the character set the client is using now
  690. // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported
  691. // depends on compile flags of mysql distribution
  692. function GetCharSet()
  693. {
  694. //we will use ADO's builtin property charSet
  695. if (!method_exists($this->_connectionID,'character_set_name'))
  696. return false;
  697. $this->charSet = @$this->_connectionID->character_set_name();
  698. if (!$this->charSet) {
  699. return false;
  700. } else {
  701. return $this->charSet;
  702. }
  703. }
  704. // SetCharSet - switch the client encoding
  705. function SetCharSet($charset_name)
  706. {
  707. if (!method_exists($this->_connectionID,'set_charset'))
  708. return false;
  709. if ($this->charSet !== $charset_name) {
  710. $if = @$this->_connectionID->set_charset($charset_name);
  711. if ($if === true & $this->GetCharSet() == $charset_name) {
  712. return true;
  713. } else return false;
  714. } else return true;
  715. }
  716. }
  717. /*--------------------------------------------------------------------------------------
  718. Class Name: Recordset
  719. --------------------------------------------------------------------------------------*/
  720. class ADORecordSet_mysqli extends ADORecordSet{
  721. var $databaseType = "mysqli";
  722. var $canSeek = true;
  723. function ADORecordSet_mysqli($queryID, $mode = false)
  724. {
  725. if ($mode === false)
  726. {
  727. global $ADODB_FETCH_MODE;
  728. $mode = $ADODB_FETCH_MODE;
  729. }
  730. switch ($mode)
  731. {
  732. case ADODB_FETCH_NUM:
  733. $this->fetchMode = MYSQLI_NUM;
  734. break;
  735. case ADODB_FETCH_ASSOC:
  736. $this->fetchMode = MYSQLI_ASSOC;
  737. break;
  738. case ADODB_FETCH_DEFAULT:
  739. case ADODB_FETCH_BOTH:
  740. default:
  741. $this->fetchMode = MYSQLI_BOTH;
  742. break;
  743. }
  744. $this->adodbFetchMode = $mode;
  745. $this->ADORecordSet($queryID);
  746. }
  747. function _initrs()
  748. {
  749. global $ADODB_COUNTRECS;
  750. $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
  751. $this->_numOfFields = @mysqli_num_fields($this->_queryID);
  752. }
  753. /*
  754. 1 = MYSQLI_NOT_NULL_FLAG
  755. 2 = MYSQLI_PRI_KEY_FLAG
  756. 4 = MYSQLI_UNIQUE_KEY_FLAG
  757. 8 = MYSQLI_MULTIPLE_KEY_FLAG
  758. 16 = MYSQLI_BLOB_FLAG
  759. 32 = MYSQLI_UNSIGNED_FLAG
  760. 64 = MYSQLI_ZEROFILL_FLAG
  761. 128 = MYSQLI_BINARY_FLAG
  762. 256 = MYSQLI_ENUM_FLAG
  763. 512 = MYSQLI_AUTO_INCREMENT_FLAG
  764. 1024 = MYSQLI_TIMESTAMP_FLAG
  765. 2048 = MYSQLI_SET_FLAG
  766. 32768 = MYSQLI_NUM_FLAG
  767. 16384 = MYSQLI_PART_KEY_FLAG
  768. 32768 = MYSQLI_GROUP_FLAG
  769. 65536 = MYSQLI_UNIQUE_FLAG
  770. 131072 = MYSQLI_BINCMP_FLAG
  771. */
  772. function FetchField($fieldOffset = -1)
  773. {
  774. $fieldnr = $fieldOffset;
  775. if ($fieldOffset != -1) {
  776. $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
  777. }
  778. $o = @mysqli_fetch_field($this->_queryID);
  779. if (!$o) return false;
  780. /* Properties of an ADOFieldObject as set by MetaColumns */
  781. $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG;
  782. $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG;
  783. $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG;
  784. $o->binary = $o->flags & MYSQLI_BINARY_FLAG;
  785. // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
  786. $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
  787. return $o;
  788. }
  789. function GetRowAssoc($upper = true)
  790. {
  791. if ($this->fetchMode == MYSQLI_ASSOC && !$upper)
  792. return $this->fields;
  793. $row = ADORecordSet::GetRowAssoc($upper);
  794. return $row;
  795. }
  796. /* Use associative array to get fields array */
  797. function Fields($colname)
  798. {
  799. if ($this->fetchMode != MYSQLI_NUM)
  800. return @$this->fields[$colname];
  801. if (!$this->bind) {
  802. $this->bind = array();
  803. for ($i = 0; $i < $this->_numOfFields; $i++) {
  804. $o = $this->FetchField($i);
  805. $this->bind[strtoupper($o->name)] = $i;
  806. }
  807. }
  808. return $this->fields[$this->bind[strtoupper($colname)]];
  809. }
  810. function _seek($row)
  811. {
  812. if ($this->_numOfRows == 0)
  813. return false;
  814. if ($row < 0)
  815. return false;
  816. mysqli_data_seek($this->_queryID, $row);
  817. $this->EOF = false;
  818. return true;
  819. }
  820. function NextRecordSet()
  821. {
  822. global $ADODB_COUNTRECS;
  823. mysqli_free_result($this->_queryID);
  824. $this->_queryID = -1;
  825. // Move to the next recordset, or return false if there is none. In a stored proc
  826. // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
  827. // returns false. I think this is because the last "recordset" is actually just the
  828. // return value of the stored proc (ie the number of rows affected).
  829. if(!mysqli_next_result($this->connection->_connectionID)) {
  830. return false;
  831. }
  832. // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
  833. $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID )
  834. : @mysqli_use_result( $this->connection->_connectionID );
  835. if(!$this->_queryID) {
  836. return false;
  837. }
  838. $this->_inited = false;
  839. $this->bind = false;
  840. $this->_currentRow = -1;
  841. $this->Init();
  842. return true;
  843. }
  844. // 10% speedup to move MoveNext to child class
  845. // This is the only implementation that works now (23-10-2003).
  846. // Other functions return no or the wrong results.
  847. function MoveNext()
  848. {
  849. if ($this->EOF) return false;
  850. $this->_currentRow++;
  851. $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
  852. if (is_array($this->fields)) return true;
  853. $this->EOF = true;
  854. return false;
  855. }
  856. function _fetch()
  857. {
  858. $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
  859. return is_array($this->fields);
  860. }
  861. function _close()
  862. {
  863. //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014
  864. //only a problem with persistant connections
  865. while(mysqli_more_results($this->connection->_connectionID)){
  866. @mysqli_next_result($this->connection->_connectionID);
  867. }
  868. mysqli_free_result($this->_queryID);
  869. $this->_queryID = false;
  870. }
  871. /*
  872. 0 = MYSQLI_TYPE_DECIMAL
  873. 1 = MYSQLI_TYPE_CHAR
  874. 1 = MYSQLI_TYPE_TINY
  875. 2 = MYSQLI_TYPE_SHORT
  876. 3 = MYSQLI_TYPE_LONG
  877. 4 = MYSQLI_TYPE_FLOAT
  878. 5 = MYSQLI_TYPE_DOUBLE
  879. 6 = MYSQLI_TYPE_NULL
  880. 7 = MYSQLI_TYPE_TIMESTAMP
  881. 8 = MYSQLI_TYPE_LONGLONG
  882. 9 = MYSQLI_TYPE_INT24
  883. 10 = MYSQLI_TYPE_DATE
  884. 11 = MYSQLI_TYPE_TIME
  885. 12 = MYSQLI_TYPE_DATETIME
  886. 13 = MYSQLI_TYPE_YEAR
  887. 14 = MYSQLI_TYPE_NEWDATE
  888. 247 = MYSQLI_TYPE_ENUM
  889. 248 = MYSQLI_TYPE_SET
  890. 249 = MYSQLI_TYPE_TINY_BLOB
  891. 250 = MYSQLI_TYPE_MEDIUM_BLOB
  892. 251 = MYSQLI_TYPE_LONG_BLOB
  893. 252 = MYSQLI_TYPE_BLOB
  894. 253 = MYSQLI_TYPE_VAR_STRING
  895. 254 = MYSQLI_TYPE_STRING
  896. 255 = MYSQLI_TYPE_GEOMETRY
  897. */
  898. function MetaType($t, $len = -1, $fieldobj = false)
  899. {
  900. if (is_object($t)) {
  901. $fieldobj = $t;
  902. $t = $fieldobj->type;
  903. $len = $fieldobj->max_length;
  904. }
  905. $len = -1; // mysql max_length is not accurate
  906. switch (strtoupper($t)) {
  907. case 'STRING':
  908. case 'CHAR':
  909. case 'VARCHAR':
  910. case 'TINYBLOB':
  911. case 'TINYTEXT':
  912. case 'ENUM':
  913. case 'SET':
  914. case MYSQLI_TYPE_TINY_BLOB :
  915. #case MYSQLI_TYPE_CHAR :
  916. case MYSQLI_TYPE_STRING :
  917. case MYSQLI_TYPE_ENUM :
  918. case MYSQLI_TYPE_SET :
  919. case 253 :
  920. if ($len <= $this->blobSize) return 'C';
  921. case 'TEXT':
  922. case 'LONGTEXT':
  923. case 'MEDIUMTEXT':
  924. return 'X';
  925. // php_mysql extension always returns 'blob' even if 'text'
  926. // so we have to check whether binary...
  927. case 'IMAGE':
  928. case 'LONGBLOB':
  929. case 'BLOB':
  930. case 'MEDIUMBLOB':
  931. case MYSQLI_TYPE_BLOB :
  932. case MYSQLI_TYPE_LONG_BLOB :
  933. case MYSQLI_TYPE_MEDIUM_BLOB :
  934. return !empty($fieldobj->binary) ? 'B' : 'X';
  935. case 'YEAR':
  936. case 'DATE':
  937. case MYSQLI_TYPE_DATE :
  938. case MYSQLI_TYPE_YEAR :
  939. return 'D';
  940. case 'TIME':
  941. case 'DATETIME':
  942. case 'TIMESTAMP':
  943. case MYSQLI_TYPE_DATETIME :
  944. case MYSQLI_TYPE_NEWDATE :
  945. case MYSQLI_TYPE_TIME :
  946. case MYSQLI_TYPE_TIMESTAMP :
  947. return 'T';
  948. case 'INT':
  949. case 'INTEGER':
  950. case 'BIGINT':
  951. case 'TINYINT':
  952. case 'MEDIUMINT':
  953. case 'SMALLINT':
  954. case MYSQLI_TYPE_INT24 :
  955. case MYSQLI_TYPE_LONG :
  956. case MYSQLI_TYPE_LONGLONG :
  957. case MYSQLI_TYPE_SHORT :
  958. case MYSQLI_TYPE_TINY :
  959. if (!empty($fieldobj->primary_key)) return 'R';
  960. return 'I';
  961. // Added floating-point types
  962. // Maybe not necessery.
  963. case 'FLOAT':
  964. case 'DOUBLE':
  965. // case 'DOUBLE PRECISION':
  966. case 'DECIMAL':
  967. case 'DEC':
  968. case 'FIXED':
  969. default:
  970. //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
  971. return 'N';
  972. }
  973. } // function
  974. } // rs class
  975. }
  976. class ADORecordSet_array_mysqli extends ADORecordSet_array {
  977. function ADORecordSet_array_mysqli($id=-1,$mode=false)
  978. {
  979. $this->ADORecordSet_array($id,$mode);
  980. }
  981. function MetaType($t, $len = -1, $fieldobj = false)
  982. {
  983. if (is_object($t)) {
  984. $fieldobj = $t;
  985. $t = $fieldobj->type;
  986. $len = $fieldobj->max_length;
  987. }
  988. $len = -1; // mysql max_length is not accurate
  989. switch (strtoupper($t)) {
  990. case 'STRING':
  991. case 'CHAR':
  992. case 'VARCHAR':
  993. case 'TINYBLOB':
  994. case 'TINYTEXT':
  995. case 'ENUM':
  996. case 'SET':
  997. case MYSQLI_TYPE_TINY_BLOB :
  998. #case MYSQLI_TYPE_CHAR :
  999. case MYSQLI_TYPE_STRING :
  1000. case MYSQLI_TYPE_ENUM :
  1001. case MYSQLI_TYPE_SET :
  1002. case 253 :
  1003. if ($len <= $this->blobSize) return 'C';
  1004. case 'TEXT':
  1005. case 'LONGTEXT':
  1006. case 'MEDIUMTEXT':
  1007. return 'X';
  1008. // php_mysql extension always returns 'blob' even if 'text'
  1009. // so we have to check whether binary...
  1010. case 'IMAGE':
  1011. case 'LONGBLOB':
  1012. case 'BLOB':
  1013. case 'MEDIUMBLOB':
  1014. case MYSQLI_TYPE_BLOB :
  1015. case MYSQLI_TYPE_LONG_BLOB :
  1016. case MYSQLI_TYPE_MEDIUM_BLOB :
  1017. return !empty($fieldobj->binary) ? 'B' : 'X';
  1018. case 'YEAR':
  1019. case 'DATE':
  1020. case MYSQLI_TYPE_DATE :
  1021. case MYSQLI_TYPE_YEAR :
  1022. return 'D';
  1023. case 'TIME':
  1024. case 'DATETIME':
  1025. case 'TIMESTAMP':
  1026. case MYSQLI_TYPE_DATETIME :
  1027. case MYSQLI_TYPE_NEWDATE :
  1028. case MYSQLI_TYPE_TIME :
  1029. case MYSQLI_TYPE_TIMESTAMP :
  1030. return 'T';
  1031. case 'INT':
  1032. case 'INTEGER':
  1033. case 'BIGINT':
  1034. case 'TINYINT':
  1035. case 'MEDIUMINT':
  1036. case 'SMALLINT':
  1037. case MYSQLI_TYPE_INT24 :
  1038. case MYSQLI_TYPE_LONG :
  1039. case MYSQLI_TYPE_LONGLONG :
  1040. case MYSQLI_TYPE_SHORT :
  1041. case MYSQLI_TYPE_TINY :
  1042. if (!empty($fieldobj->primary_key)) return 'R';
  1043. return 'I';
  1044. // Added floating-point types
  1045. // Maybe not necessery.
  1046. case 'FLOAT':
  1047. case 'DOUBLE':
  1048. // case 'DOUBLE PRECISION':
  1049. case 'DECIMAL':
  1050. case 'DEC':
  1051. case 'FIXED':
  1052. default:
  1053. //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
  1054. return 'N';
  1055. }
  1056. } // function
  1057. }
  1058. ?>