Packages

  • dibi
    • drivers
    • nette
    • reflection
  • None
  • PHP

Classes

  • DibiFirebirdDriver
  • DibiMsSql2005Driver
  • DibiMsSqlDriver
  • DibiMySqlDriver
  • DibiMySqliDriver
  • DibiOdbcDriver
  • DibiOracleDriver
  • DibiPdoDriver
  • DibiPostgreDriver
  • DibiSqlite3Driver
  • DibiSqliteDriver

Exceptions

  • DibiProcedureException
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the "dibi" - smart database abstraction layer.
  5:  *
  6:  * Copyright (c) 2005 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  */
 11: 
 12: 
 13: /**
 14:  * The dibi driver for Firebird/InterBase database.
 15:  *
 16:  * Driver options:
 17:  *   - database => the path to database file (server:/path/database.fdb)
 18:  *   - username (or user)
 19:  *   - password (or pass)
 20:  *   - charset => character encoding to set
 21:  *   - buffers (int) => buffers is the number of database buffers to allocate for the server-side cache. If 0 or omitted, server chooses its own default.
 22:  *   - resource (resource) => existing connection resource
 23:  *   - lazy, profiler, result, substitutes, ... => see DibiConnection options
 24:  *
 25:  * @author     Tomáš Kraina, Roman Sklenář
 26:  * @package    dibi\drivers
 27:  */
 28: class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultDriver, IDibiReflector
 29: {
 30:     const ERROR_EXCEPTION_THROWN = -836;
 31: 
 32:     /** @var resource  Connection resource */
 33:     private $connection;
 34: 
 35:     /** @var resource  Resultset resource */
 36:     private $resultSet;
 37: 
 38:     /** @var resource  Resultset resource */
 39:     private $transaction;
 40: 
 41:     /** @var bool */
 42:     private $inTransaction = FALSE;
 43: 
 44: 
 45:     /**
 46:      * @throws DibiNotSupportedException
 47:      */
 48:     public function __construct()
 49:     {
 50:         if (!extension_loaded('interbase')) {
 51:             throw new DibiNotSupportedException("PHP extension 'interbase' is not loaded.");
 52:         }
 53:     }
 54: 
 55: 
 56: 
 57:     /**
 58:      * Connects to a database.
 59:      * @return void
 60:      * @throws DibiException
 61:      */
 62:     public function connect(array &$config)
 63:     {
 64:         DibiConnection::alias($config, 'database', 'db');
 65: 
 66:         if (isset($config['resource'])) {
 67:             $this->connection = $config['resource'];
 68: 
 69:         } else {
 70:             // default values
 71:             if (!isset($config['username'])) $config['username'] = ini_get('ibase.default_password');
 72:             if (!isset($config['password'])) $config['password'] = ini_get('ibase.default_user');
 73:             if (!isset($config['database'])) $config['database'] = ini_get('ibase.default_db');
 74:             if (!isset($config['charset'])) $config['charset'] = ini_get('ibase.default_charset');
 75:             if (!isset($config['buffers'])) $config['buffers'] = 0;
 76: 
 77:             DibiDriverException::tryError();
 78:             if (empty($config['persistent'])) {
 79:                 $this->connection = ibase_connect($config['database'], $config['username'], $config['password'], $config['charset'], $config['buffers']); // intentionally @
 80:             } else {
 81:                 $this->connection = ibase_pconnect($config['database'], $config['username'], $config['password'], $config['charset'], $config['buffers']); // intentionally @
 82:             }
 83:             if (DibiDriverException::catchError($msg)) {
 84:                 throw new DibiDriverException($msg, ibase_errcode());
 85:             }
 86: 
 87:             if (!is_resource($this->connection)) {
 88:                 throw new DibiDriverException(ibase_errmsg(), ibase_errcode());
 89:             }
 90:         }
 91: 
 92:     }
 93: 
 94: 
 95: 
 96:     /**
 97:      * Disconnects from a database.
 98:      * @return void
 99:      */
100:     public function disconnect()
101:     {
102:         ibase_close($this->connection);
103:     }
104: 
105: 
106: 
107:     /**
108:      * Executes the SQL query.
109:      * @param  string      SQL statement.
110:      * @return IDibiResultDriver|NULL
111:      * @throws DibiDriverException|DibiException
112:      */
113:     public function query($sql)
114:     {
115:         DibiDriverException::tryError();
116:         $resource = $this->inTransaction ? $this->transaction : $this->connection;
117:         $res = ibase_query($resource, $sql);
118: 
119:         if (DibiDriverException::catchError($msg)) {
120:             if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
121:                 preg_match('/exception (\d+) (\w+) (.*)/i', ibase_errmsg(), $match);
122:                 throw new DibiProcedureException($match[3], $match[1], $match[2], dibi::$sql);
123: 
124:             } else {
125:                 throw new DibiDriverException(ibase_errmsg(), ibase_errcode(), dibi::$sql);
126:             }
127:         }
128: 
129:         if ($res === FALSE) {
130:             throw new DibiDriverException(ibase_errmsg(), ibase_errcode(), $sql);
131: 
132:         } elseif (is_resource($res)) {
133:             return $this->createResultDriver($res);
134:         }
135:     }
136: 
137: 
138: 
139:     /**
140:      * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
141:      * @return int|FALSE  number of rows or FALSE on error
142:      */
143:     public function getAffectedRows()
144:     {
145:         return ibase_affected_rows($this->connection);
146:     }
147: 
148: 
149: 
150:     /**
151:      * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
152:      * @param  string     generator name
153:      * @return int|FALSE  int on success or FALSE on failure
154:      */
155:     public function getInsertId($sequence)
156:     {
157:         return ibase_gen_id($sequence, 0, $this->connection);
158:     }
159: 
160: 
161: 
162:     /**
163:      * Begins a transaction (if supported).
164:      * @param  string  optional savepoint name
165:      * @return void
166:      * @throws DibiDriverException
167:      */
168:     public function begin($savepoint = NULL)
169:     {
170:         if ($savepoint !== NULL) {
171:             throw new DibiNotSupportedException('Savepoints are not supported in Firebird/Interbase.');
172:         }
173:         $this->transaction = ibase_trans($this->resource);
174:         $this->inTransaction = TRUE;
175:     }
176: 
177: 
178: 
179:     /**
180:      * Commits statements in a transaction.
181:      * @param  string  optional savepoint name
182:      * @return void
183:      * @throws DibiDriverException
184:      */
185:     public function commit($savepoint = NULL)
186:     {
187:         if ($savepoint !== NULL) {
188:             throw new DibiNotSupportedException('Savepoints are not supported in Firebird/Interbase.');
189:         }
190: 
191:         if (!ibase_commit($this->transaction)) {
192:             throw new DibiDriverException('Unable to handle operation - failure when commiting transaction.');
193:         }
194: 
195:         $this->inTransaction = FALSE;
196:     }
197: 
198: 
199: 
200:     /**
201:      * Rollback changes in a transaction.
202:      * @param  string  optional savepoint name
203:      * @return void
204:      * @throws DibiDriverException
205:      */
206:     public function rollback($savepoint = NULL)
207:     {
208:         if ($savepoint !== NULL) {
209:             throw new DibiNotSupportedException('Savepoints are not supported in Firebird/Interbase.');
210:         }
211: 
212:         if (!ibase_rollback($this->transaction)) {
213:             throw new DibiDriverException('Unable to handle operation - failure when rolbacking transaction.');
214:         }
215: 
216:         $this->inTransaction = FALSE;
217:     }
218: 
219: 
220: 
221:     /**
222:      * Is in transaction?
223:      * @return bool
224:      */
225:     public function inTransaction()
226:     {
227:         return $this->inTransaction;
228:     }
229: 
230: 
231: 
232:     /**
233:      * Returns the connection resource.
234:      * @return resource
235:      */
236:     public function getResource()
237:     {
238:         return $this->connection;
239:     }
240: 
241: 
242: 
243:     /**
244:      * Returns the connection reflector.
245:      * @return IDibiReflector
246:      */
247:     public function getReflector()
248:     {
249:         return $this;
250:     }
251: 
252: 
253: 
254:     /**
255:      * Result set driver factory.
256:      * @param  resource
257:      * @return IDibiResultDriver
258:      */
259:     public function createResultDriver($resource)
260:     {
261:         $res = clone $this;
262:         $res->resultSet = $resource;
263:         return $res;
264:     }
265: 
266: 
267: 
268:     /********************* SQL ********************/
269: 
270: 
271: 
272:     /**
273:      * Encodes data for use in a SQL statement.
274:      * @param  mixed     value
275:      * @param  string    type (dibi::TEXT, dibi::BOOL, ...)
276:      * @return string    encoded value
277:      * @throws InvalidArgumentException
278:      */
279:     public function escape($value, $type)
280:     {
281:         switch ($type) {
282:         case dibi::TEXT:
283:         case dibi::BINARY:
284:             return "'" . str_replace("'", "''", $value) . "'";
285: 
286:         case dibi::IDENTIFIER:
287:             return $value;
288: 
289:         case dibi::BOOL:
290:             return $value ? 1 : 0;
291: 
292:         case dibi::DATE:
293:             return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
294: 
295:         case dibi::DATETIME:
296:             return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
297: 
298:         default:
299:             throw new InvalidArgumentException('Unsupported type.');
300:         }
301:     }
302: 
303: 
304: 
305:     /**
306:      * Encodes string for use in a LIKE statement.
307:      * @param  string
308:      * @param  int
309:      * @return string
310:      */
311:     public function escapeLike($value, $pos)
312:     {
313:         throw new DibiNotImplementedException;
314:     }
315: 
316: 
317: 
318:     /**
319:      * Decodes data from result set.
320:      * @param  string    value
321:      * @param  string    type (dibi::BINARY)
322:      * @return string    decoded value
323:      * @throws InvalidArgumentException
324:      */
325:     public function unescape($value, $type)
326:     {
327:         if ($type === dibi::BINARY) {
328:             return $value;
329:         }
330:         throw new InvalidArgumentException('Unsupported type.');
331:     }
332: 
333: 
334: 
335:     /**
336:      * Injects LIMIT/OFFSET to the SQL query.
337:      * @param  string &$sql  The SQL query that will be modified.
338:      * @param  int $limit
339:      * @param  int $offset
340:      * @return void
341:      */
342:     public function applyLimit(&$sql, $limit, $offset)
343:     {
344:         if ($limit < 0 && $offset < 1) return;
345: 
346:         // see http://scott.yang.id.au/2004/01/limit-in-select-statements-in-firebird/
347:         $sql = 'SELECT FIRST ' . (int) $limit . ($offset > 0 ? ' SKIP ' . (int) $offset : '') . ' * FROM (' . $sql . ')';
348:     }
349: 
350: 
351: 
352:     /********************* result set ********************/
353: 
354: 
355: 
356:     /**
357:      * Automatically frees the resources allocated for this result set.
358:      * @return void
359:      */
360:     public function __destruct()
361:     {
362:         $this->resultSet && @$this->free();
363:     }
364: 
365: 
366: 
367:     /**
368:      * Returns the number of rows in a result set.
369:      * @return int
370:      */
371:     public function getRowCount()
372:     {
373:         return ibase_num_fields($this->resultSet);
374:     }
375: 
376: 
377: 
378:     /**
379:      * Fetches the row at current position and moves the internal cursor to the next position.
380:      * @param  bool     TRUE for associative array, FALSE for numeric
381:      * @return array    array on success, nonarray if no next record
382:      */
383:     public function fetch($assoc)
384:     {
385:         DibiDriverException::tryError();
386:         $result = $assoc ? ibase_fetch_assoc($this->resultSet, IBASE_TEXT) : ibase_fetch_row($this->resultSet, IBASE_TEXT); // intentionally @
387: 
388:         if (DibiDriverException::catchError($msg)) {
389:             if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
390:                 preg_match('/exception (\d+) (\w+) (.*)/i', ibase_errmsg(), $match);
391:                 throw new DibiProcedureException($match[3], $match[1], $match[2], dibi::$sql);
392: 
393:             } else {
394:                 throw new DibiDriverException($msg, ibase_errcode(), dibi::$sql);
395:             }
396:         }
397: 
398:         return $result;
399:     }
400: 
401: 
402: 
403:     /**
404:      * Moves cursor position without fetching row.
405:      * @param  int      the 0-based cursor pos to seek to
406:      * @return boolean  TRUE on success, FALSE if unable to seek to specified record
407:      * @throws DibiException
408:      */
409:     public function seek($row)
410:     {
411:         throw new DibiNotSupportedException("Firebird/Interbase do not support seek in result set.");
412:     }
413: 
414: 
415: 
416:     /**
417:      * Frees the resources allocated for this result set.
418:      * @return void
419:      */
420:     public function free()
421:     {
422:         ibase_free_result($this->resultSet);
423:         $this->resultSet = NULL;
424:     }
425: 
426: 
427: 
428:     /**
429:      * Returns the result set resource.
430:      * @return mysqli_result
431:      */
432:     public function getResultResource()
433:     {
434:         return $this->resultSet;
435:     }
436: 
437: 
438: 
439:     /**
440:      * Returns metadata for all columns in a result set.
441:      * @return array
442:      */
443:     public function getResultColumns()
444:     {
445:         $count = ibase_num_fields($this->resultSet);
446:         $columns = array();
447:         for ($i = 0; $i < $count; $i++) {
448:             $row = (array) ibase_field_info($this->resultSet, $i);
449:             $columns[] = array(
450:                 'name' => $row['name'],
451:                 'fullname' => $row['name'],
452:                 'table' => $row['relation'],
453:                 'nativetype' => $row['type'],
454:             );
455:         }
456:         return $columns;
457:     }
458: 
459: 
460: 
461:     /********************* IDibiReflector ********************/
462: 
463: 
464: 
465:     /**
466:      * Returns list of tables.
467:      * @return array
468:      */
469:     public function getTables()
470:     {
471:         $res = $this->query("
472:             SELECT TRIM(RDB\$RELATION_NAME),
473:                 CASE RDB\$VIEW_BLR WHEN NULL THEN 'TRUE' ELSE 'FALSE' END
474:             FROM RDB\$RELATIONS
475:             WHERE RDB\$SYSTEM_FLAG = 0;"
476:         );
477:         $tables = array();
478:         while ($row = $res->fetch(FALSE)) {
479:             $tables[] = array(
480:                 'name' => $row[0],
481:                 'view' => $row[1] === 'TRUE',
482:             );
483:         }
484:         return $tables;
485:     }
486: 
487: 
488: 
489:     /**
490:      * Returns metadata for all columns in a table.
491:      * @param  string
492:      * @return array
493:      */
494:     public function getColumns($table)
495:     {
496:         $table = strtoupper($table);
497:         $res = $this->query("
498:             SELECT TRIM(r.RDB\$FIELD_NAME) AS FIELD_NAME,
499:                 CASE f.RDB\$FIELD_TYPE
500:                     WHEN 261 THEN 'BLOB'
501:                     WHEN 14 THEN 'CHAR'
502:                     WHEN 40 THEN 'CSTRING'
503:                     WHEN 11 THEN 'D_FLOAT'
504:                     WHEN 27 THEN 'DOUBLE'
505:                     WHEN 10 THEN 'FLOAT'
506:                     WHEN 16 THEN 'INT64'
507:                     WHEN 8 THEN 'INTEGER'
508:                     WHEN 9 THEN 'QUAD'
509:                     WHEN 7 THEN 'SMALLINT'
510:                     WHEN 12 THEN 'DATE'
511:                     WHEN 13 THEN 'TIME'
512:                     WHEN 35 THEN 'TIMESTAMP'
513:                     WHEN 37 THEN 'VARCHAR'
514:                     ELSE 'UNKNOWN'
515:                 END AS FIELD_TYPE,
516:                 f.RDB\$FIELD_LENGTH AS FIELD_LENGTH,
517:                 r.RDB\$DEFAULT_VALUE AS DEFAULT_VALUE,
518:                 CASE r.RDB\$NULL_FLAG
519:                     WHEN 1 THEN 'FALSE' ELSE 'TRUE'
520:                 END AS NULLABLE
521:             FROM RDB\$RELATION_FIELDS r
522:                 LEFT JOIN RDB\$FIELDS f ON r.RDB\$FIELD_SOURCE = f.RDB\$FIELD_NAME
523:             WHERE r.RDB\$RELATION_NAME = '$table'
524:             ORDER BY r.RDB\$FIELD_POSITION;"
525: 
526:         );
527:         $columns = array();
528:         while ($row = $res->fetch(TRUE)) {
529:             $key = $row['FIELD_NAME'];
530:             $columns[$key] = array(
531:                 'name' => $key,
532:                 'table' => $table,
533:                 'nativetype' => trim($row['FIELD_TYPE']),
534:                 'size' => $row['FIELD_LENGTH'],
535:                 'nullable' => $row['NULLABLE'] === 'TRUE',
536:                 'default' => $row['DEFAULT_VALUE'],
537:                 'autoincrement' => FALSE,
538:             );
539:         }
540:         return $columns;
541:     }
542: 
543: 
544: 
545:     /**
546:      * Returns metadata for all indexes in a table (the constraints are included).
547:      * @param  string
548:      * @return array
549:      */
550:     public function getIndexes($table)
551:     {
552:         $table = strtoupper($table);
553:         $res = $this->query("
554:             SELECT TRIM(s.RDB\$INDEX_NAME) AS INDEX_NAME,
555:                 TRIM(s.RDB\$FIELD_NAME) AS FIELD_NAME,
556:                 i.RDB\$UNIQUE_FLAG AS UNIQUE_FLAG,
557:                 i.RDB\$FOREIGN_KEY AS FOREIGN_KEY,
558:                 TRIM(r.RDB\$CONSTRAINT_TYPE) AS CONSTRAINT_TYPE,
559:                 s.RDB\$FIELD_POSITION AS FIELD_POSITION
560:             FROM RDB\$INDEX_SEGMENTS s
561:                 LEFT JOIN RDB\$INDICES i ON i.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
562:                 LEFT JOIN RDB\$RELATION_CONSTRAINTS r ON r.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
563:             WHERE UPPER(i.RDB\$RELATION_NAME) = '$table'
564:             ORDER BY s.RDB\$FIELD_POSITION"
565:         );
566:         $indexes = array();
567:         while ($row = $res->fetch(TRUE)) {
568:             $key = $row['INDEX_NAME'];
569:             $indexes[$key]['name'] = $key;
570:             $indexes[$key]['unique'] = $row['UNIQUE_FLAG'] === 1;
571:             $indexes[$key]['primary'] = $row['CONSTRAINT_TYPE'] === 'PRIMARY KEY';
572:             $indexes[$key]['table'] = $table;
573:             $indexes[$key]['columns'][$row['FIELD_POSITION']] = $row['FIELD_NAME'];
574:         }
575:         return $indexes;
576:     }
577: 
578: 
579: 
580:     /**
581:      * Returns metadata for all foreign keys in a table.
582:      * @param  string
583:      * @return array
584:      */
585:     public function getForeignKeys($table)
586:     {
587:         $table = strtoupper($table);
588:         $res = $this->query("
589:             SELECT TRIM(s.RDB\$INDEX_NAME) AS INDEX_NAME,
590:                 TRIM(s.RDB\$FIELD_NAME) AS FIELD_NAME,
591:             FROM RDB\$INDEX_SEGMENTS s
592:                 LEFT JOIN RDB\$RELATION_CONSTRAINTS r ON r.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
593:             WHERE UPPER(i.RDB\$RELATION_NAME) = '$table'
594:                 AND r.RDB\$CONSTRAINT_TYPE = 'FOREIGN KEY'
595:             ORDER BY s.RDB\$FIELD_POSITION"
596:         );
597:         $keys = array();
598:         while ($row = $res->fetch(TRUE)) {
599:             $key = $row['INDEX_NAME'];
600:             $keys[$key] = array(
601:                 'name' => $key,
602:                 'column' => $row['FIELD_NAME'],
603:                 'table' => $table,
604:             );
605:         }
606:         return $keys;
607:     }
608: 
609: 
610: 
611:     /**
612:      * Returns list of indices in given table (the constraints are not listed).
613:      * @param  string
614:      * @return array
615:      */
616:     public function getIndices($table)
617:     {
618:         $res = $this->query("
619:             SELECT TRIM(RDB\$INDEX_NAME)
620:             FROM RDB\$INDICES
621:             WHERE RDB\$RELATION_NAME = UPPER('$table')
622:                 AND RDB\$UNIQUE_FLAG IS NULL
623:                 AND RDB\$FOREIGN_KEY IS NULL;"
624:         );
625:         $indices = array();
626:         while ($row = $res->fetch(FALSE)) {
627:             $indices[] = $row[0];
628:         }
629:         return $indices;
630:     }
631: 
632: 
633: 
634:     /**
635:      * Returns list of constraints in given table.
636:      * @param  string
637:      * @return array
638:      */
639:     public function getConstraints($table)
640:     {
641:         $res = $this->query("
642:             SELECT TRIM(RDB\$INDEX_NAME)
643:             FROM RDB\$INDICES
644:             WHERE RDB\$RELATION_NAME = UPPER('$table')
645:                 AND (
646:                     RDB\$UNIQUE_FLAG IS NOT NULL
647:                     OR RDB\$FOREIGN_KEY IS NOT NULL
648:             );"
649:         );
650:         $constraints = array();
651:         while ($row = $res->fetch(FALSE)) {
652:             $constraints[] = $row[0];
653:         }
654:         return $constraints;
655:     }
656: 
657: 
658: 
659:     /**
660:      * Returns metadata for all triggers in a table or database.
661:      * (Only if user has permissions on ALTER TABLE, INSERT/UPDATE/DELETE record in table)
662:      * @param  string
663:      * @param  string
664:      * @return array
665:      */
666:     public function getTriggersMeta($table = NULL)
667:     {
668:         $res = $this->query("
669:             SELECT TRIM(RDB\$TRIGGER_NAME) AS TRIGGER_NAME,
670:                 TRIM(RDB\$RELATION_NAME) AS TABLE_NAME,
671:                 CASE RDB\$TRIGGER_TYPE
672:                     WHEN 1 THEN 'BEFORE'
673:                     WHEN 2 THEN 'AFTER'
674:                     WHEN 3 THEN 'BEFORE'
675:                     WHEN 4 THEN 'AFTER'
676:                     WHEN 5 THEN 'BEFORE'
677:                     WHEN 6 THEN 'AFTER'
678:                 END AS TRIGGER_TYPE,
679:                 CASE RDB\$TRIGGER_TYPE
680:                     WHEN 1 THEN 'INSERT'
681:                     WHEN 2 THEN 'INSERT'
682:                     WHEN 3 THEN 'UPDATE'
683:                     WHEN 4 THEN 'UPDATE'
684:                     WHEN 5 THEN 'DELETE'
685:                     WHEN 6 THEN 'DELETE'
686:                 END AS TRIGGER_EVENT,
687:                 CASE RDB\$TRIGGER_INACTIVE
688:                     WHEN 1 THEN 'FALSE' ELSE 'TRUE'
689:                 END AS TRIGGER_ENABLED
690:             FROM RDB\$TRIGGERS
691:             WHERE RDB\$SYSTEM_FLAG = 0"
692:             . ($table === NULL ? ";" : " AND RDB\$RELATION_NAME = UPPER('$table');")
693:         );
694:         $triggers = array();
695:         while ($row = $res->fetch(TRUE)) {
696:             $triggers[$row['TRIGGER_NAME']] = array(
697:                 'name' => $row['TRIGGER_NAME'],
698:                 'table' => $row['TABLE_NAME'],
699:                 'type' => trim($row['TRIGGER_TYPE']),
700:                 'event' => trim($row['TRIGGER_EVENT']),
701:                 'enabled' => trim($row['TRIGGER_ENABLED']) === 'TRUE',
702:             );
703:         }
704:         return $triggers;
705:     }
706: 
707: 
708: 
709:     /**
710:      * Returns list of triggers for given table.
711:      * (Only if user has permissions on ALTER TABLE, INSERT/UPDATE/DELETE record in table)
712:      * @param  string
713:      * @return array
714:      */
715:     public function getTriggers($table = NULL)
716:     {
717:         $q = "SELECT TRIM(RDB\$TRIGGER_NAME)
718:             FROM RDB\$TRIGGERS
719:             WHERE RDB\$SYSTEM_FLAG = 0";
720:         $q .= $table === NULL ? ";" : " AND RDB\$RELATION_NAME = UPPER('$table')";
721: 
722:         $res = $this->query($q);
723:         $triggers = array();
724:         while ($row = $res->fetch(FALSE)) {
725:             $triggers[] = $row[0];
726:         }
727:         return $triggers;
728:     }
729: 
730: 
731: 
732:     /**
733:      * Returns metadata from stored procedures and their input and output parameters.
734:      * @param  string
735:      * @return array
736:      */
737:     public function getProceduresMeta()
738:     {
739:         $res = $this->query("
740:             SELECT
741:                 TRIM(p.RDB\$PARAMETER_NAME) AS PARAMETER_NAME,
742:                 TRIM(p.RDB\$PROCEDURE_NAME) AS PROCEDURE_NAME,
743:                 CASE p.RDB\$PARAMETER_TYPE
744:                     WHEN 0 THEN 'INPUT'
745:                     WHEN 1 THEN 'OUTPUT'
746:                     ELSE 'UNKNOWN'
747:                 END AS PARAMETER_TYPE,
748:                 CASE f.RDB\$FIELD_TYPE
749:                     WHEN 261 THEN 'BLOB'
750:                     WHEN 14 THEN 'CHAR'
751:                     WHEN 40 THEN 'CSTRING'
752:                     WHEN 11 THEN 'D_FLOAT'
753:                     WHEN 27 THEN 'DOUBLE'
754:                     WHEN 10 THEN 'FLOAT'
755:                     WHEN 16 THEN 'INT64'
756:                     WHEN 8 THEN 'INTEGER'
757:                     WHEN 9 THEN 'QUAD'
758:                     WHEN 7 THEN 'SMALLINT'
759:                     WHEN 12 THEN 'DATE'
760:                     WHEN 13 THEN 'TIME'
761:                     WHEN 35 THEN 'TIMESTAMP'
762:                     WHEN 37 THEN 'VARCHAR'
763:                     ELSE 'UNKNOWN'
764:                 END AS FIELD_TYPE,
765:                 f.RDB\$FIELD_LENGTH AS FIELD_LENGTH,
766:                 p.RDB\$PARAMETER_NUMBER AS PARAMETER_NUMBER
767:             FROM RDB\$PROCEDURE_PARAMETERS p
768:                 LEFT JOIN RDB\$FIELDS f ON f.RDB\$FIELD_NAME = p.RDB\$FIELD_SOURCE
769:             ORDER BY p.RDB\$PARAMETER_TYPE, p.RDB\$PARAMETER_NUMBER;"
770:         );
771:         $procedures = array();
772:         while ($row = $res->fetch(TRUE)) {
773:             $key = $row['PROCEDURE_NAME'];
774:             $io = trim($row['PARAMETER_TYPE']);
775:             $num = $row['PARAMETER_NUMBER'];
776:             $procedures[$key]['name'] = $row['PROCEDURE_NAME'];
777:             $procedures[$key]['params'][$io][$num]['name'] = $row['PARAMETER_NAME'];
778:             $procedures[$key]['params'][$io][$num]['type'] = trim($row['FIELD_TYPE']);
779:             $procedures[$key]['params'][$io][$num]['size'] = $row['FIELD_LENGTH'];
780:         }
781:         return $procedures;
782:     }
783: 
784: 
785: 
786:     /**
787:      * Returns list of stored procedures.
788:      * @return array
789:      */
790:     public function getProcedures()
791:     {
792:         $res = $this->query("
793:             SELECT TRIM(RDB\$PROCEDURE_NAME)
794:             FROM RDB\$PROCEDURES;"
795:         );
796:         $procedures = array();
797:         while ($row = $res->fetch(FALSE)) {
798:             $procedures[] = $row[0];
799:         }
800:         return $procedures;
801:     }
802: 
803: 
804: 
805:     /**
806:      * Returns list of generators.
807:      * @return array
808:      */
809:     public function getGenerators()
810:     {
811:         $res = $this->query("
812:             SELECT TRIM(RDB\$GENERATOR_NAME)
813:             FROM RDB\$GENERATORS
814:             WHERE RDB\$SYSTEM_FLAG = 0;"
815:         );
816:         $generators = array();
817:         while ($row = $res->fetch(FALSE)) {
818:             $generators[] = $row[0];
819:         }
820:         return $generators;
821:     }
822: 
823: 
824: 
825:     /**
826:      * Returns list of user defined functions (UDF).
827:      * @return array
828:      */
829:     public function getFunctions()
830:     {
831:         $res = $this->query("
832:             SELECT TRIM(RDB\$FUNCTION_NAME)
833:             FROM RDB\$FUNCTIONS
834:             WHERE RDB\$SYSTEM_FLAG = 0;"
835:         );
836:         $functions = array();
837:         while ($row = $res->fetch(FALSE)) {
838:             $functions[] = $row[0];
839:         }
840:         return $functions;
841:     }
842: 
843: }
844: 
845: 
846: 
847: 
848: /**
849:  * Database procedure exception.
850:  *
851:  * @author     Roman Sklenář
852:  * @copyright  Copyright (c) 2010
853:  * @package    dibi\drivers
854:  */
855: class DibiProcedureException extends DibiException
856: {
857:     /** @var string */
858:     protected $severity;
859: 
860: 
861:     /**
862:      * Construct the exception.
863:      * @param  string  Message describing the exception
864:      * @param  int     Some code
865:      * @param  string SQL command
866:      */
867:     public function __construct($message = NULL, $code = 0, $severity = NULL, $sql = NULL)
868:     {
869:         parent::__construct($message, (int) $code, $sql);
870:         $this->severity = $severity;
871:     }
872: 
873: 
874: 
875:     /**
876:      * Gets the exception severity.
877:      * @return string
878:      */
879:     public function getSeverity()
880:     {
881:         $this->severity;
882:     }
883: 
884: }
885: 
dibi API documentation API documentation generated by ApiGen 2.3.0