oci8.php 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356
  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP versions 4 and 5 |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
  6. // | Stig. S. Bakken, Lukas Smith |
  7. // | All rights reserved. |
  8. // +----------------------------------------------------------------------+
  9. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
  10. // | API as well as database abstraction for PHP applications. |
  11. // | This LICENSE is in the BSD license style. |
  12. // | |
  13. // | Redistribution and use in source and binary forms, with or without |
  14. // | modification, are permitted provided that the following conditions |
  15. // | are met: |
  16. // | |
  17. // | Redistributions of source code must retain the above copyright |
  18. // | notice, this list of conditions and the following disclaimer. |
  19. // | |
  20. // | Redistributions in binary form must reproduce the above copyright |
  21. // | notice, this list of conditions and the following disclaimer in the |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // | |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission. |
  28. // | |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
  40. // | POSSIBILITY OF SUCH DAMAGE. |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lukas Smith <smith@pooteeweet.org> |
  43. // +----------------------------------------------------------------------+
  44. // $Id$
  45. require_once 'MDB2/Driver/Manager/Common.php';
  46. /**
  47. * MDB2 oci8 driver for the management modules
  48. *
  49. * @package MDB2
  50. * @category Database
  51. * @author Lukas Smith <smith@pooteeweet.org>
  52. */
  53. class MDB2_Driver_Manager_oci8 extends MDB2_Driver_Manager_Common
  54. {
  55. // {{{ createDatabase()
  56. /**
  57. * create a new database
  58. *
  59. * @param string $name name of the database that should be created
  60. * @param array $options array with charset, collation info
  61. *
  62. * @return mixed MDB2_OK on success, a MDB2 error on failure
  63. * @access public
  64. */
  65. function createDatabase($name, $options = array())
  66. {
  67. $db = $this->getDBInstance();
  68. if (MDB2::isError($db)) {
  69. return $db;
  70. }
  71. $username = $db->options['database_name_prefix'].$name;
  72. $password = $db->dsn['password'] ? $db->dsn['password'] : $name;
  73. $tablespace = $db->options['default_tablespace']
  74. ? ' DEFAULT TABLESPACE '.$db->options['default_tablespace'] : '';
  75. $query = 'CREATE USER '.$username.' IDENTIFIED BY '.$password.$tablespace;
  76. $result = $db->standaloneQuery($query, null, true);
  77. if (MDB2::isError($result)) {
  78. return $result;
  79. }
  80. $query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO '.$username;
  81. $result = $db->standaloneQuery($query, null, true);
  82. if (MDB2::isError($result)) {
  83. $query = 'DROP USER '.$username.' CASCADE';
  84. $result2 = $db->standaloneQuery($query, null, true);
  85. if (MDB2::isError($result2)) {
  86. return $db->raiseError($result2, null, null,
  87. 'could not setup the database user', __FUNCTION__);
  88. }
  89. return $result;
  90. }
  91. return MDB2_OK;
  92. }
  93. // }}}
  94. // {{{ alterDatabase()
  95. /**
  96. * alter an existing database
  97. *
  98. * IMPORTANT: the safe way to change the db charset is to do a full import/export!
  99. * If - and only if - the new character set is a strict superset of the current
  100. * character set, it is possible to use the ALTER DATABASE CHARACTER SET to
  101. * expedite the change in the database character set.
  102. *
  103. * @param string $name name of the database that is intended to be changed
  104. * @param array $options array with name, charset info
  105. *
  106. * @return mixed MDB2_OK on success, a MDB2 error on failure
  107. * @access public
  108. */
  109. function alterDatabase($name, $options = array())
  110. {
  111. //disabled
  112. //return parent::alterDatabase($name, $options);
  113. $db = $this->getDBInstance();
  114. if (MDB2::isError($db)) {
  115. return $db;
  116. }
  117. if (!empty($options['name'])) {
  118. $query = 'ALTER DATABASE ' . $db->quoteIdentifier($name, true)
  119. .' RENAME GLOBAL_NAME TO ' . $db->quoteIdentifier($options['name'], true);
  120. $result = $db->standaloneQuery($query);
  121. if (MDB2::isError($result)) {
  122. return $result;
  123. }
  124. }
  125. if (!empty($options['charset'])) {
  126. $queries = array();
  127. $queries[] = 'SHUTDOWN IMMEDIATE'; //or NORMAL
  128. $queries[] = 'STARTUP MOUNT';
  129. $queries[] = 'ALTER SYSTEM ENABLE RESTRICTED SESSION';
  130. $queries[] = 'ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0';
  131. $queries[] = 'ALTER DATABASE OPEN';
  132. $queries[] = 'ALTER DATABASE CHARACTER SET ' . $options['charset'];
  133. $queries[] = 'ALTER DATABASE NATIONAL CHARACTER SET ' . $options['charset'];
  134. $queries[] = 'SHUTDOWN IMMEDIATE'; //or NORMAL
  135. $queries[] = 'STARTUP';
  136. foreach ($queries as $query) {
  137. $result = $db->standaloneQuery($query);
  138. if (MDB2::isError($result)) {
  139. return $result;
  140. }
  141. }
  142. }
  143. return MDB2_OK;
  144. }
  145. // }}}
  146. // {{{ dropDatabase()
  147. /**
  148. * drop an existing database
  149. *
  150. * @param object $db database object that is extended by this class
  151. * @param string $name name of the database that should be dropped
  152. * @return mixed MDB2_OK on success, a MDB2 error on failure
  153. * @access public
  154. */
  155. function dropDatabase($name)
  156. {
  157. $db = $this->getDBInstance();
  158. if (MDB2::isError($db)) {
  159. return $db;
  160. }
  161. $username = $db->options['database_name_prefix'].$name;
  162. return $db->standaloneQuery('DROP USER '.$username.' CASCADE', null, true);
  163. }
  164. // }}}
  165. // {{{ _makeAutoincrement()
  166. /**
  167. * add an autoincrement sequence + trigger
  168. *
  169. * @param string $name name of the PK field
  170. * @param string $table name of the table
  171. * @param string $start start value for the sequence
  172. * @return mixed MDB2_OK on success, a MDB2 error on failure
  173. * @access private
  174. */
  175. function _makeAutoincrement($name, $table, $start = 1)
  176. {
  177. $db = $this->getDBInstance();
  178. if (MDB2::isError($db)) {
  179. return $db;
  180. }
  181. $table_uppercase = strtoupper($table);
  182. $index_name = $table_uppercase . '_AI_PK';
  183. $definition = array(
  184. 'primary' => true,
  185. 'fields' => array($name => true),
  186. );
  187. $idxname_format = $db->getOption('idxname_format');
  188. $db->setOption('idxname_format', '%s');
  189. $result = $this->createConstraint($table, $index_name, $definition);
  190. $db->setOption('idxname_format', $idxname_format);
  191. if (MDB2::isError($result)) {
  192. return $db->raiseError($result, null, null,
  193. 'primary key for autoincrement PK could not be created', __FUNCTION__);
  194. }
  195. if (null === $start) {
  196. $db->beginTransaction();
  197. $query = 'SELECT MAX(' . $db->quoteIdentifier($name, true) . ') FROM ' . $db->quoteIdentifier($table, true);
  198. $start = $this->db->queryOne($query, 'integer');
  199. if (MDB2::isError($start)) {
  200. return $start;
  201. }
  202. ++$start;
  203. $result = $this->createSequence($table, $start);
  204. $db->commit();
  205. } else {
  206. $result = $this->createSequence($table, $start);
  207. }
  208. if (MDB2::isError($result)) {
  209. return $db->raiseError($result, null, null,
  210. 'sequence for autoincrement PK could not be created', __FUNCTION__);
  211. }
  212. $seq_name = $db->getSequenceName($table);
  213. $trigger_name = $db->quoteIdentifier($table_uppercase . '_AI_PK', true);
  214. $seq_name_quoted = $db->quoteIdentifier($seq_name, true);
  215. $table = $db->quoteIdentifier($table, true);
  216. $name = $db->quoteIdentifier($name, true);
  217. $trigger_sql = '
  218. CREATE TRIGGER '.$trigger_name.'
  219. BEFORE INSERT
  220. ON '.$table.'
  221. FOR EACH ROW
  222. DECLARE
  223. last_Sequence NUMBER;
  224. last_InsertID NUMBER;
  225. BEGIN
  226. SELECT '.$seq_name_quoted.'.NEXTVAL INTO :NEW.'.$name.' FROM DUAL;
  227. IF (:NEW.'.$name.' IS NULL OR :NEW.'.$name.' = 0) THEN
  228. SELECT '.$seq_name_quoted.'.NEXTVAL INTO :NEW.'.$name.' FROM DUAL;
  229. ELSE
  230. SELECT NVL(Last_Number, 0) INTO last_Sequence
  231. FROM User_Sequences
  232. WHERE UPPER(Sequence_Name) = UPPER(\''.$seq_name.'\');
  233. SELECT :NEW.'.$name.' INTO last_InsertID FROM DUAL;
  234. WHILE (last_InsertID > last_Sequence) LOOP
  235. SELECT '.$seq_name_quoted.'.NEXTVAL INTO last_Sequence FROM DUAL;
  236. END LOOP;
  237. END IF;
  238. END;
  239. ';
  240. $result = $db->exec($trigger_sql);
  241. if (MDB2::isError($result)) {
  242. return $result;
  243. }
  244. return MDB2_OK;
  245. }
  246. // }}}
  247. // {{{ _dropAutoincrement()
  248. /**
  249. * drop an existing autoincrement sequence + trigger
  250. *
  251. * @param string $table name of the table
  252. * @return mixed MDB2_OK on success, a MDB2 error on failure
  253. * @access private
  254. */
  255. function _dropAutoincrement($table)
  256. {
  257. $db = $this->getDBInstance();
  258. if (MDB2::isError($db)) {
  259. return $db;
  260. }
  261. $table = strtoupper($table);
  262. $trigger_name = $table . '_AI_PK';
  263. $trigger_name_quoted = $db->quote($trigger_name, 'text');
  264. $query = 'SELECT trigger_name FROM user_triggers';
  265. $query.= ' WHERE trigger_name='.$trigger_name_quoted.' OR trigger_name='.strtoupper($trigger_name_quoted);
  266. $trigger = $db->queryOne($query);
  267. if (MDB2::isError($trigger)) {
  268. return $trigger;
  269. }
  270. if ($trigger) {
  271. $trigger_name = $db->quoteIdentifier($table . '_AI_PK', true);
  272. $trigger_sql = 'DROP TRIGGER ' . $trigger_name;
  273. $result = $db->exec($trigger_sql);
  274. if (MDB2::isError($result)) {
  275. return $db->raiseError($result, null, null,
  276. 'trigger for autoincrement PK could not be dropped', __FUNCTION__);
  277. }
  278. $result = $this->dropSequence($table);
  279. if (MDB2::isError($result)) {
  280. return $db->raiseError($result, null, null,
  281. 'sequence for autoincrement PK could not be dropped', __FUNCTION__);
  282. }
  283. $index_name = $table . '_AI_PK';
  284. $idxname_format = $db->getOption('idxname_format');
  285. $db->setOption('idxname_format', '%s');
  286. $result1 = $this->dropConstraint($table, $index_name);
  287. $db->setOption('idxname_format', $idxname_format);
  288. $result2 = $this->dropConstraint($table, $index_name);
  289. if (MDB2::isError($result1) && MDB2::isError($result2)) {
  290. return $db->raiseError($result1, null, null,
  291. 'primary key for autoincrement PK could not be dropped', __FUNCTION__);
  292. }
  293. }
  294. return MDB2_OK;
  295. }
  296. // }}}
  297. // {{{ _getTemporaryTableQuery()
  298. /**
  299. * A method to return the required SQL string that fits between CREATE ... TABLE
  300. * to create the table as a temporary table.
  301. *
  302. * @return string The string required to be placed between "CREATE" and "TABLE"
  303. * to generate a temporary table, if possible.
  304. */
  305. function _getTemporaryTableQuery()
  306. {
  307. return 'GLOBAL TEMPORARY';
  308. }
  309. // }}}
  310. // {{{ _getAdvancedFKOptions()
  311. /**
  312. * Return the FOREIGN KEY query section dealing with non-standard options
  313. * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
  314. *
  315. * @param array $definition
  316. * @return string
  317. * @access protected
  318. */
  319. function _getAdvancedFKOptions($definition)
  320. {
  321. $query = '';
  322. if (!empty($definition['ondelete']) && (strtoupper($definition['ondelete']) != 'NO ACTION')) {
  323. $query .= ' ON DELETE '.$definition['ondelete'];
  324. }
  325. if (!empty($definition['deferrable'])) {
  326. $query .= ' DEFERRABLE';
  327. } else {
  328. $query .= ' NOT DEFERRABLE';
  329. }
  330. if (!empty($definition['initiallydeferred'])) {
  331. $query .= ' INITIALLY DEFERRED';
  332. } else {
  333. $query .= ' INITIALLY IMMEDIATE';
  334. }
  335. return $query;
  336. }
  337. // }}}
  338. // {{{ createTable()
  339. /**
  340. * create a new table
  341. *
  342. * @param string $name Name of the database that should be created
  343. * @param array $fields Associative array that contains the definition of each field of the new table
  344. * The indexes of the array entries are the names of the fields of the table an
  345. * the array entry values are associative arrays like those that are meant to be
  346. * passed with the field definitions to get[Type]Declaration() functions.
  347. *
  348. * Example
  349. * array(
  350. *
  351. * 'id' => array(
  352. * 'type' => 'integer',
  353. * 'unsigned' => 1
  354. * 'notnull' => 1
  355. * 'default' => 0
  356. * ),
  357. * 'name' => array(
  358. * 'type' => 'text',
  359. * 'length' => 12
  360. * ),
  361. * 'password' => array(
  362. * 'type' => 'text',
  363. * 'length' => 12
  364. * )
  365. * );
  366. * @param array $options An associative array of table options:
  367. * array(
  368. * 'comment' => 'Foo',
  369. * 'temporary' => true|false,
  370. * );
  371. * @return mixed MDB2_OK on success, a MDB2 error on failure
  372. * @access public
  373. */
  374. function createTable($name, $fields, $options = array())
  375. {
  376. $db = $this->getDBInstance();
  377. if (MDB2::isError($db)) {
  378. return $db;
  379. }
  380. $db->beginNestedTransaction();
  381. $result = parent::createTable($name, $fields, $options);
  382. if (!MDB2::isError($result)) {
  383. foreach ($fields as $field_name => $field) {
  384. if (!empty($field['autoincrement'])) {
  385. $result = $this->_makeAutoincrement($field_name, $name);
  386. }
  387. }
  388. }
  389. $db->completeNestedTransaction();
  390. return $result;
  391. }
  392. // }}}
  393. // {{{ dropTable()
  394. /**
  395. * drop an existing table
  396. *
  397. * @param string $name name of the table that should be dropped
  398. * @return mixed MDB2_OK on success, a MDB2 error on failure
  399. * @access public
  400. */
  401. function dropTable($name)
  402. {
  403. $db = $this->getDBInstance();
  404. if (MDB2::isError($db)) {
  405. return $db;
  406. }
  407. $db->beginNestedTransaction();
  408. $result = $this->_dropAutoincrement($name);
  409. if (!MDB2::isError($result)) {
  410. $result = parent::dropTable($name);
  411. if (MDB2::isError($result)) {
  412. return $result;
  413. }
  414. }
  415. $db->completeNestedTransaction();
  416. return $result;
  417. }
  418. // }}}
  419. // {{{ truncateTable()
  420. /**
  421. * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
  422. * it falls back to a DELETE FROM TABLE query)
  423. *
  424. * @param string $name name of the table that should be truncated
  425. * @return mixed MDB2_OK on success, a MDB2 error on failure
  426. * @access public
  427. */
  428. function truncateTable($name)
  429. {
  430. $db = $this->getDBInstance();
  431. if (MDB2::isError($db)) {
  432. return $db;
  433. }
  434. $name = $db->quoteIdentifier($name, true);
  435. $result = $db->exec("TRUNCATE TABLE $name");
  436. if (MDB2::isError($result)) {
  437. return $result;
  438. }
  439. return MDB2_OK;
  440. }
  441. // }}}
  442. // {{{ vacuum()
  443. /**
  444. * Optimize (vacuum) all the tables in the db (or only the specified table)
  445. * and optionally run ANALYZE.
  446. *
  447. * @param string $table table name (all the tables if empty)
  448. * @param array $options an array with driver-specific options:
  449. * - timeout [int] (in seconds) [mssql-only]
  450. * - analyze [boolean] [pgsql and mysql]
  451. * - full [boolean] [pgsql-only]
  452. * - freeze [boolean] [pgsql-only]
  453. *
  454. * @return mixed MDB2_OK success, a MDB2 error on failure
  455. * @access public
  456. */
  457. function vacuum($table = null, $options = array())
  458. {
  459. // not needed in Oracle
  460. return MDB2_OK;
  461. }
  462. // }}}
  463. // {{{ alterTable()
  464. /**
  465. * alter an existing table
  466. *
  467. * @param string $name name of the table that is intended to be changed.
  468. * @param array $changes associative array that contains the details of each type
  469. * of change that is intended to be performed. The types of
  470. * changes that are currently supported are defined as follows:
  471. *
  472. * name
  473. *
  474. * New name for the table.
  475. *
  476. * add
  477. *
  478. * Associative array with the names of fields to be added as
  479. * indexes of the array. The value of each entry of the array
  480. * should be set to another associative array with the properties
  481. * of the fields to be added. The properties of the fields should
  482. * be the same as defined by the MDB2 parser.
  483. *
  484. *
  485. * remove
  486. *
  487. * Associative array with the names of fields to be removed as indexes
  488. * of the array. Currently the values assigned to each entry are ignored.
  489. * An empty array should be used for future compatibility.
  490. *
  491. * rename
  492. *
  493. * Associative array with the names of fields to be renamed as indexes
  494. * of the array. The value of each entry of the array should be set to
  495. * another associative array with the entry named name with the new
  496. * field name and the entry named Declaration that is expected to contain
  497. * the portion of the field declaration already in DBMS specific SQL code
  498. * as it is used in the CREATE TABLE statement.
  499. *
  500. * change
  501. *
  502. * Associative array with the names of the fields to be changed as indexes
  503. * of the array. Keep in mind that if it is intended to change either the
  504. * name of a field and any other properties, the change array entries
  505. * should have the new names of the fields as array indexes.
  506. *
  507. * The value of each entry of the array should be set to another associative
  508. * array with the properties of the fields to that are meant to be changed as
  509. * array entries. These entries should be assigned to the new values of the
  510. * respective properties. The properties of the fields should be the same
  511. * as defined by the MDB2 parser.
  512. *
  513. * Example
  514. * array(
  515. * 'name' => 'userlist',
  516. * 'add' => array(
  517. * 'quota' => array(
  518. * 'type' => 'integer',
  519. * 'unsigned' => 1
  520. * )
  521. * ),
  522. * 'remove' => array(
  523. * 'file_limit' => array(),
  524. * 'time_limit' => array()
  525. * ),
  526. * 'change' => array(
  527. * 'name' => array(
  528. * 'length' => '20',
  529. * 'definition' => array(
  530. * 'type' => 'text',
  531. * 'length' => 20,
  532. * ),
  533. * )
  534. * ),
  535. * 'rename' => array(
  536. * 'sex' => array(
  537. * 'name' => 'gender',
  538. * 'definition' => array(
  539. * 'type' => 'text',
  540. * 'length' => 1,
  541. * 'default' => 'M',
  542. * ),
  543. * )
  544. * )
  545. * )
  546. *
  547. * @param boolean $check indicates whether the function should just check if the DBMS driver
  548. * can perform the requested table alterations if the value is true or
  549. * actually perform them otherwise.
  550. * @access public
  551. *
  552. * @return mixed MDB2_OK on success, a MDB2 error on failure
  553. */
  554. function alterTable($name, $changes, $check)
  555. {
  556. $db = $this->getDBInstance();
  557. if (MDB2::isError($db)) {
  558. return $db;
  559. }
  560. foreach ($changes as $change_name => $change) {
  561. switch ($change_name) {
  562. case 'add':
  563. case 'remove':
  564. case 'change':
  565. case 'name':
  566. case 'rename':
  567. break;
  568. default:
  569. return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
  570. 'change type "'.$change_name.'" not yet supported', __FUNCTION__);
  571. }
  572. }
  573. if ($check) {
  574. return MDB2_OK;
  575. }
  576. $name = $db->quoteIdentifier($name, true);
  577. if (!empty($changes['add']) && is_array($changes['add'])) {
  578. $fields = array();
  579. foreach ($changes['add'] as $field_name => $field) {
  580. $fields[] = $db->getDeclaration($field['type'], $field_name, $field);
  581. }
  582. $result = $db->exec("ALTER TABLE $name ADD (". implode(', ', $fields).')');
  583. if (MDB2::isError($result)) {
  584. return $result;
  585. }
  586. }
  587. if (!empty($changes['change']) && is_array($changes['change'])) {
  588. $fields = array();
  589. foreach ($changes['change'] as $field_name => $field) {
  590. //fix error "column to be modified to NOT NULL is already NOT NULL"
  591. if (!array_key_exists('notnull', $field)) {
  592. unset($field['definition']['notnull']);
  593. }
  594. $fields[] = $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']);
  595. }
  596. $result = $db->exec("ALTER TABLE $name MODIFY (". implode(', ', $fields).')');
  597. if (MDB2::isError($result)) {
  598. return $result;
  599. }
  600. }
  601. if (!empty($changes['rename']) && is_array($changes['rename'])) {
  602. foreach ($changes['rename'] as $field_name => $field) {
  603. $field_name = $db->quoteIdentifier($field_name, true);
  604. $query = "ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name']);
  605. $result = $db->exec($query);
  606. if (MDB2::isError($result)) {
  607. return $result;
  608. }
  609. }
  610. }
  611. if (!empty($changes['remove']) && is_array($changes['remove'])) {
  612. $fields = array();
  613. foreach ($changes['remove'] as $field_name => $field) {
  614. $fields[] = $db->quoteIdentifier($field_name, true);
  615. }
  616. $result = $db->exec("ALTER TABLE $name DROP COLUMN ". implode(', ', $fields));
  617. if (MDB2::isError($result)) {
  618. return $result;
  619. }
  620. }
  621. if (!empty($changes['name'])) {
  622. $change_name = $db->quoteIdentifier($changes['name'], true);
  623. $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
  624. if (MDB2::isError($result)) {
  625. return $result;
  626. }
  627. }
  628. return MDB2_OK;
  629. }
  630. // }}}
  631. // {{{ _fetchCol()
  632. /**
  633. * Utility method to fetch and format a column from a resultset
  634. *
  635. * @param resource $result
  636. * @param boolean $fixname (used when listing indices or constraints)
  637. * @return mixed array of names on success, a MDB2 error on failure
  638. * @access private
  639. */
  640. function _fetchCol($result, $fixname = false)
  641. {
  642. if (MDB2::isError($result)) {
  643. return $result;
  644. }
  645. $col = $result->fetchCol();
  646. if (MDB2::isError($col)) {
  647. return $col;
  648. }
  649. $result->free();
  650. $db = $this->getDBInstance();
  651. if (MDB2::isError($db)) {
  652. return $db;
  653. }
  654. if ($fixname) {
  655. foreach ($col as $k => $v) {
  656. $col[$k] = $this->_fixIndexName($v);
  657. }
  658. }
  659. if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
  660. && $db->options['field_case'] == CASE_LOWER
  661. ) {
  662. $col = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $col);
  663. }
  664. return $col;
  665. }
  666. // }}}
  667. // {{{ listDatabases()
  668. /**
  669. * list all databases
  670. *
  671. * @return mixed array of database names on success, a MDB2 error on failure
  672. * @access public
  673. */
  674. function listDatabases()
  675. {
  676. $db = $this->getDBInstance();
  677. if (MDB2::isError($db)) {
  678. return $db;
  679. }
  680. if (!$db->options['emulate_database']) {
  681. return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
  682. 'database listing is only supported if the "emulate_database" option is enabled', __FUNCTION__);
  683. }
  684. if ($db->options['database_name_prefix']) {
  685. $query = 'SELECT SUBSTR(username, ';
  686. $query.= (strlen($db->options['database_name_prefix'])+1);
  687. $query.= ") FROM sys.dba_users WHERE username LIKE '";
  688. $query.= $db->options['database_name_prefix']."%'";
  689. } else {
  690. $query = 'SELECT username FROM sys.dba_users';
  691. }
  692. $result = $db->standaloneQuery($query, array('text'), false);
  693. return $this->_fetchCol($result);
  694. }
  695. // }}}
  696. // {{{ listUsers()
  697. /**
  698. * list all users
  699. *
  700. * @return mixed array of user names on success, a MDB2 error on failure
  701. * @access public
  702. */
  703. function listUsers()
  704. {
  705. $db = $this->getDBInstance();
  706. if (MDB2::isError($db)) {
  707. return $db;
  708. }
  709. if ($db->options['emulate_database'] && $db->options['database_name_prefix']) {
  710. $query = 'SELECT SUBSTR(username, ';
  711. $query.= (strlen($db->options['database_name_prefix'])+1);
  712. $query.= ") FROM sys.dba_users WHERE username NOT LIKE '";
  713. $query.= $db->options['database_name_prefix']."%'";
  714. } else {
  715. $query = 'SELECT username FROM sys.dba_users';
  716. }
  717. return $db->queryCol($query);
  718. }
  719. // }}}
  720. // {{{ listViews()
  721. /**
  722. * list all views in the current database
  723. *
  724. * @param string owner, the current is default
  725. * @return mixed array of view names on success, a MDB2 error on failure
  726. * @access public
  727. */
  728. function listViews($owner = null)
  729. {
  730. $db = $this->getDBInstance();
  731. if (MDB2::isError($db)) {
  732. return $db;
  733. }
  734. if (empty($owner)) {
  735. $owner = $db->dsn['username'];
  736. }
  737. $query = 'SELECT view_name
  738. FROM sys.all_views
  739. WHERE owner=? OR owner=?';
  740. $stmt = $db->prepare($query);
  741. if (MDB2::isError($stmt)) {
  742. return $stmt;
  743. }
  744. $result = $stmt->execute(array($owner, strtoupper($owner)));
  745. return $this->_fetchCol($result);
  746. }
  747. // }}}
  748. // {{{ listFunctions()
  749. /**
  750. * list all functions in the current database
  751. *
  752. * @param string owner, the current is default
  753. * @return mixed array of function names on success, a MDB2 error on failure
  754. * @access public
  755. */
  756. function listFunctions($owner = null)
  757. {
  758. $db = $this->getDBInstance();
  759. if (MDB2::isError($db)) {
  760. return $db;
  761. }
  762. if (empty($owner)) {
  763. $owner = $db->dsn['username'];
  764. }
  765. $query = "SELECT name
  766. FROM sys.all_source
  767. WHERE line = 1
  768. AND type = 'FUNCTION'
  769. AND (owner=? OR owner=?)";
  770. $stmt = $db->prepare($query);
  771. if (MDB2::isError($stmt)) {
  772. return $stmt;
  773. }
  774. $result = $stmt->execute(array($owner, strtoupper($owner)));
  775. return $this->_fetchCol($result);
  776. }
  777. // }}}
  778. // {{{ listTableTriggers()
  779. /**
  780. * list all triggers in the database that reference a given table
  781. *
  782. * @param string table for which all referenced triggers should be found
  783. * @return mixed array of trigger names on success, a MDB2 error on failure
  784. * @access public
  785. */
  786. function listTableTriggers($table = null)
  787. {
  788. $db = $this->getDBInstance();
  789. if (MDB2::isError($db)) {
  790. return $db;
  791. }
  792. if (empty($owner)) {
  793. $owner = $db->dsn['username'];
  794. }
  795. $query = "SELECT trigger_name
  796. FROM sys.all_triggers
  797. WHERE (table_name=? OR table_name=?)
  798. AND (owner=? OR owner=?)";
  799. $stmt = $db->prepare($query);
  800. if (MDB2::isError($stmt)) {
  801. return $stmt;
  802. }
  803. $args = array(
  804. $table,
  805. strtoupper($table),
  806. $owner,
  807. strtoupper($owner),
  808. );
  809. $result = $stmt->execute($args);
  810. return $this->_fetchCol($result);
  811. }
  812. // }}}
  813. // {{{ listTables()
  814. /**
  815. * list all tables in the database
  816. *
  817. * @param string owner, the current is default
  818. * @return mixed array of table names on success, a MDB2 error on failure
  819. * @access public
  820. */
  821. function listTables($owner = null)
  822. {
  823. $db = $this->getDBInstance();
  824. if (MDB2::isError($db)) {
  825. return $db;
  826. }
  827. if (empty($owner)) {
  828. $owner = $db->dsn['username'];
  829. }
  830. $query = 'SELECT table_name
  831. FROM sys.all_tables
  832. WHERE owner=? OR owner=?';
  833. $stmt = $db->prepare($query);
  834. if (MDB2::isError($stmt)) {
  835. return $stmt;
  836. }
  837. $result = $stmt->execute(array($owner, strtoupper($owner)));
  838. return $this->_fetchCol($result);
  839. }
  840. // }}}
  841. // {{{ listTableFields()
  842. /**
  843. * list all fields in a table in the current database
  844. *
  845. * @param string $table name of table that should be used in method
  846. * @return mixed array of field names on success, a MDB2 error on failure
  847. * @access public
  848. */
  849. function listTableFields($table)
  850. {
  851. $db = $this->getDBInstance();
  852. if (MDB2::isError($db)) {
  853. return $db;
  854. }
  855. list($owner, $table) = $this->splitTableSchema($table);
  856. if (empty($owner)) {
  857. $owner = $db->dsn['username'];
  858. }
  859. $query = 'SELECT column_name
  860. FROM all_tab_columns
  861. WHERE (table_name=? OR table_name=?)
  862. AND (owner=? OR owner=?)
  863. ORDER BY column_id';
  864. $stmt = $db->prepare($query);
  865. if (MDB2::isError($stmt)) {
  866. return $stmt;
  867. }
  868. $args = array(
  869. $table,
  870. strtoupper($table),
  871. $owner,
  872. strtoupper($owner),
  873. );
  874. $result = $stmt->execute($args);
  875. return $this->_fetchCol($result);
  876. }
  877. // }}}
  878. // {{{ listTableIndexes()
  879. /**
  880. * list all indexes in a table
  881. *
  882. * @param string $table name of table that should be used in method
  883. * @return mixed array of index names on success, a MDB2 error on failure
  884. * @access public
  885. */
  886. function listTableIndexes($table)
  887. {
  888. $db = $this->getDBInstance();
  889. if (MDB2::isError($db)) {
  890. return $db;
  891. }
  892. list($owner, $table) = $this->splitTableSchema($table);
  893. if (empty($owner)) {
  894. $owner = $db->dsn['username'];
  895. }
  896. $query = 'SELECT i.index_name name
  897. FROM all_indexes i
  898. LEFT JOIN all_constraints c
  899. ON c.index_name = i.index_name
  900. AND c.owner = i.owner
  901. AND c.table_name = i.table_name
  902. WHERE (i.table_name=? OR i.table_name=?)
  903. AND (i.owner=? OR i.owner=?)
  904. AND c.index_name IS NULL
  905. AND i.generated=' .$db->quote('N', 'text');
  906. $stmt = $db->prepare($query);
  907. if (MDB2::isError($stmt)) {
  908. return $stmt;
  909. }
  910. $args = array(
  911. $table,
  912. strtoupper($table),
  913. $owner,
  914. strtoupper($owner),
  915. );
  916. $result = $stmt->execute($args);
  917. return $this->_fetchCol($result, true);
  918. }
  919. // }}}
  920. // {{{ createConstraint()
  921. /**
  922. * create a constraint on a table
  923. *
  924. * @param string $table name of the table on which the constraint is to be created
  925. * @param string $name name of the constraint to be created
  926. * @param array $definition associative array that defines properties of the constraint to be created.
  927. * Currently, only one property named FIELDS is supported. This property
  928. * is also an associative with the names of the constraint fields as array
  929. * constraints. Each entry of this array is set to another type of associative
  930. * array that specifies properties of the constraint that are specific to
  931. * each field.
  932. *
  933. * Example
  934. * array(
  935. * 'fields' => array(
  936. * 'user_name' => array(),
  937. * 'last_login' => array()
  938. * )
  939. * )
  940. * @return mixed MDB2_OK on success, a MDB2 error on failure
  941. * @access public
  942. */
  943. function createConstraint($table, $name, $definition)
  944. {
  945. $result = parent::createConstraint($table, $name, $definition);
  946. if (MDB2::isError($result)) {
  947. return $result;
  948. }
  949. if (!empty($definition['foreign'])) {
  950. return $this->_createFKTriggers($table, array($name => $definition));
  951. }
  952. return MDB2_OK;
  953. }
  954. // }}}
  955. // {{{ dropConstraint()
  956. /**
  957. * drop existing constraint
  958. *
  959. * @param string $table name of table that should be used in method
  960. * @param string $name name of the constraint to be dropped
  961. * @param string $primary hint if the constraint is primary
  962. * @return mixed MDB2_OK on success, a MDB2 error on failure
  963. * @access public
  964. */
  965. function dropConstraint($table, $name, $primary = false)
  966. {
  967. $db = $this->getDBInstance();
  968. if (MDB2::isError($db)) {
  969. return $db;
  970. }
  971. //is it a FK constraint? If so, also delete the associated triggers
  972. $db->loadModule('Reverse', null, true);
  973. $definition = $db->reverse->getTableConstraintDefinition($table, $name);
  974. if (!MDB2::isError($definition) && !empty($definition['foreign'])) {
  975. //first drop the FK enforcing triggers
  976. $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']);
  977. if (MDB2::isError($result)) {
  978. return $result;
  979. }
  980. }
  981. return parent::dropConstraint($table, $name, $primary);
  982. }
  983. // }}}
  984. // {{{ _createFKTriggers()
  985. /**
  986. * Create triggers to enforce the FOREIGN KEY constraint on the table
  987. *
  988. * @param string $table table name
  989. * @param array $foreign_keys FOREIGN KEY definitions
  990. *
  991. * @return mixed MDB2_OK on success, a MDB2 error on failure
  992. * @access private
  993. */
  994. function _createFKTriggers($table, $foreign_keys)
  995. {
  996. $db = $this->getDBInstance();
  997. if (MDB2::isError($db)) {
  998. return $db;
  999. }
  1000. // create triggers to enforce FOREIGN KEY constraints
  1001. if ($db->supports('triggers') && !empty($foreign_keys)) {
  1002. $table = $db->quoteIdentifier($table, true);
  1003. foreach ($foreign_keys as $fkname => $fkdef) {
  1004. if (empty($fkdef)) {
  1005. continue;
  1006. }
  1007. $fkdef['onupdate'] = empty($fkdef['onupdate']) ? $db->options['default_fk_action_onupdate'] : strtoupper($fkdef['onupdate']);
  1008. if ('RESTRICT' == $fkdef['onupdate'] || 'NO ACTION' == $fkdef['onupdate']) {
  1009. // already handled by default
  1010. continue;
  1011. }
  1012. $trigger_name = substr(strtolower($fkname.'_pk_upd_trg'), 0, $db->options['max_identifiers_length']);
  1013. $table_fields = array_keys($fkdef['fields']);
  1014. $referenced_fields = array_keys($fkdef['references']['fields']);
  1015. //create the ON UPDATE trigger on the primary table
  1016. $restrict_action = ' IF (SELECT ';
  1017. $aliased_fields = array();
  1018. foreach ($table_fields as $field) {
  1019. $aliased_fields[] = $table .'.'.$field .' AS '.$field;
  1020. }
  1021. $restrict_action .= implode(',', $aliased_fields)
  1022. .' FROM '.$table
  1023. .' WHERE ';
  1024. $conditions = array();
  1025. $new_values = array();
  1026. $null_values = array();
  1027. for ($i=0; $i<count($table_fields); $i++) {
  1028. $conditions[] = $table_fields[$i] .' = :OLD.'.$referenced_fields[$i];
  1029. $new_values[] = $table_fields[$i] .' = :NEW.'.$referenced_fields[$i];
  1030. $null_values[] = $table_fields[$i] .' = NULL';
  1031. }
  1032. $cascade_action = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
  1033. $setnull_action = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
  1034. if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
  1035. $db->loadModule('Reverse', null, true);
  1036. $default_values = array();
  1037. foreach ($table_fields as $table_field) {
  1038. $field_definition = $db->reverse->getTableFieldDefinition($table, $field);
  1039. if (MDB2::isError($field_definition)) {
  1040. return $field_definition;
  1041. }
  1042. $default_values[] = $table_field .' = '. $field_definition[0]['default'];
  1043. }
  1044. $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
  1045. }
  1046. $query = 'CREATE TRIGGER %s'
  1047. .' %s ON '.$fkdef['references']['table']
  1048. .' FOR EACH ROW '
  1049. .' BEGIN ';
  1050. if ('CASCADE' == $fkdef['onupdate']) {
  1051. $sql_update = sprintf($query, $trigger_name, 'BEFORE UPDATE', 'update') . $cascade_action;
  1052. } elseif ('SET NULL' == $fkdef['onupdate']) {
  1053. $sql_update = sprintf($query, $trigger_name, 'BEFORE UPDATE', 'update') . $setnull_action;
  1054. } elseif ('SET DEFAULT' == $fkdef['onupdate']) {
  1055. $sql_update = sprintf($query, $trigger_name, 'BEFORE UPDATE', 'update') . $setdefault_action;
  1056. }
  1057. $sql_update .= ' END;';
  1058. $result = $db->exec($sql_update);
  1059. if (MDB2::isError($result)) {
  1060. if ($result->getCode() === MDB2_ERROR_ALREADY_EXISTS) {
  1061. return MDB2_OK;
  1062. }
  1063. return $result;
  1064. }
  1065. }
  1066. }
  1067. return MDB2_OK;
  1068. }
  1069. // }}}
  1070. // {{{ _dropFKTriggers()
  1071. /**
  1072. * Drop the triggers created to enforce the FOREIGN KEY constraint on the table
  1073. *
  1074. * @param string $table table name
  1075. * @param string $fkname FOREIGN KEY constraint name
  1076. * @param string $referenced_table referenced table name
  1077. *
  1078. * @return mixed MDB2_OK on success, a MDB2 error on failure
  1079. * @access private
  1080. */
  1081. function _dropFKTriggers($table, $fkname, $referenced_table)
  1082. {
  1083. $db = $this->getDBInstance();
  1084. if (MDB2::isError($db)) {
  1085. return $db;
  1086. }
  1087. $triggers = $this->listTableTriggers($table);
  1088. $triggers2 = $this->listTableTriggers($referenced_table);
  1089. if (!MDB2::isError($triggers2) && !MDB2::isError($triggers)) {
  1090. $triggers = array_merge($triggers, $triggers2);
  1091. $trigger_name = substr(strtolower($fkname.'_pk_upd_trg'), 0, $db->options['max_identifiers_length']);
  1092. $pattern = '/^'.$trigger_name.'$/i';
  1093. foreach ($triggers as $trigger) {
  1094. if (preg_match($pattern, $trigger)) {
  1095. $result = $db->exec('DROP TRIGGER '.$trigger);
  1096. if (MDB2::isError($result)) {
  1097. return $result;
  1098. }
  1099. }
  1100. }
  1101. }
  1102. return MDB2_OK;
  1103. }
  1104. // }}}
  1105. // {{{ listTableConstraints()
  1106. /**
  1107. * list all constraints in a table
  1108. *
  1109. * @param string $table name of table that should be used in method
  1110. * @return mixed array of constraint names on success, a MDB2 error on failure
  1111. * @access public
  1112. */
  1113. function listTableConstraints($table)
  1114. {
  1115. $db = $this->getDBInstance();
  1116. if (MDB2::isError($db)) {
  1117. return $db;
  1118. }
  1119. list($owner, $table) = $this->splitTableSchema($table);
  1120. if (empty($owner)) {
  1121. $owner = $db->dsn['username'];
  1122. }
  1123. $query = 'SELECT constraint_name
  1124. FROM all_constraints
  1125. WHERE (table_name=? OR table_name=?)
  1126. AND (owner=? OR owner=?)';
  1127. $stmt = $db->prepare($query);
  1128. if (MDB2::isError($stmt)) {
  1129. return $stmt;
  1130. }
  1131. $args = array(
  1132. $table,
  1133. strtoupper($table),
  1134. $owner,
  1135. strtoupper($owner),
  1136. );
  1137. $result = $stmt->execute($args);
  1138. return $this->_fetchCol($result, true);
  1139. }
  1140. // }}}
  1141. // {{{ createSequence()
  1142. /**
  1143. * create sequence
  1144. *
  1145. * @param object $db database object that is extended by this class
  1146. * @param string $seq_name name of the sequence to be created
  1147. * @param string $start start value of the sequence; default is 1
  1148. * @return mixed MDB2_OK on success, a MDB2 error on failure
  1149. * @access public
  1150. */
  1151. function createSequence($seq_name, $start = 1)
  1152. {
  1153. $db = $this->getDBInstance();
  1154. if (MDB2::isError($db)) {
  1155. return $db;
  1156. }
  1157. $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
  1158. $query = "CREATE SEQUENCE $sequence_name START WITH $start INCREMENT BY 1 NOCACHE";
  1159. $query.= ($start < 1 ? " MINVALUE $start" : '');
  1160. $result = $db->exec($query);
  1161. if (MDB2::isError($result)) {
  1162. return $result;
  1163. }
  1164. return MDB2_OK;
  1165. }
  1166. // }}}
  1167. // {{{ dropSequence()
  1168. /**
  1169. * drop existing sequence
  1170. *
  1171. * @param object $db database object that is extended by this class
  1172. * @param string $seq_name name of the sequence to be dropped
  1173. * @return mixed MDB2_OK on success, a MDB2 error on failure
  1174. * @access public
  1175. */
  1176. function dropSequence($seq_name)
  1177. {
  1178. $db = $this->getDBInstance();
  1179. if (MDB2::isError($db)) {
  1180. return $db;
  1181. }
  1182. $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
  1183. $result = $db->exec("DROP SEQUENCE $sequence_name");
  1184. if (MDB2::isError($result)) {
  1185. return $result;
  1186. }
  1187. return MDB2_OK;
  1188. }
  1189. // }}}
  1190. // {{{ listSequences()
  1191. /**
  1192. * list all sequences in the current database
  1193. *
  1194. * @param string owner, the current is default
  1195. * @return mixed array of sequence names on success, a MDB2 error on failure
  1196. * @access public
  1197. */
  1198. function listSequences($owner = null)
  1199. {
  1200. $db = $this->getDBInstance();
  1201. if (MDB2::isError($db)) {
  1202. return $db;
  1203. }
  1204. if (empty($owner)) {
  1205. $owner = $db->dsn['username'];
  1206. }
  1207. $query = 'SELECT sequence_name
  1208. FROM sys.all_sequences
  1209. WHERE (sequence_owner=? OR sequence_owner=?)';
  1210. $stmt = $db->prepare($query);
  1211. if (MDB2::isError($stmt)) {
  1212. return $stmt;
  1213. }
  1214. $result = $stmt->execute(array($owner, strtoupper($owner)));
  1215. if (MDB2::isError($result)) {
  1216. return $result;
  1217. }
  1218. $col = $result->fetchCol();
  1219. if (MDB2::isError($col)) {
  1220. return $col;
  1221. }
  1222. $result->free();
  1223. foreach ($col as $k => $v) {
  1224. $col[$k] = $this->_fixSequenceName($v);
  1225. }
  1226. if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
  1227. && $db->options['field_case'] == CASE_LOWER
  1228. ) {
  1229. $col = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $col);
  1230. }
  1231. return $col;
  1232. }
  1233. }
  1234. ?>