1: <?php
2: /**
3: * EXPERIMENTAL Informix database driver, based on PDO.
4: *
5: *
6: * 04/18/2010 BG NonQuery new, because Query-String contans to much "
7: * 04/18/2010 BG mostly working
8: * 04/16/2010 BG start to change
9: *
10: * Known bugs
11: * 04/18/2010 BG numbers / dates not working with german setting (DMY4.), only US/english with (DBDATA / DBMONEY)
12: *
13: * programming completly based on
14: * - generic PDO adapter (Marcos Sanchez) --> unchanged base
15: * - PostgreSql PDO adapater (Marcos Sanchez) --> base of this file
16: * - InformixSql adapter (PHP-ifx_xxx functions ) Josue Balbuena --> copied SQLs and some PHP-Lines
17: *
18: * the old Postgres-Code remains, but commented
19: * the copies from the InformixSql is signed
20: */
21:
22: /** BG
23: *
24: * Definition of the Informix PDO-Connection
25: define('DB_CONNECTION_1', serialize(array(
26: 'adapter' => 'InformixPDO',
27: 'host' => 'maxdata', // IP of the Computer (Informix naming)
28: 'server' => 'maxdata', // Informix-Server (Informix-naming)
29: 'service' => 9088, // same as port (Informix-naming)
30: 'protocol' => 'onsoctcp', // Informix Special:
31: 'database' => 'festival',
32: 'username' => 'prinzBernhard',
33: 'password' => 'eisenherz',
34: 'profiling' => false)));
35:
36: Additionally, the following two constants MUST be defined
37: to the special needs of the actual server
38: define(__INFORMIX_TRANSLATION__, "/home/informix/lib/esql/igo4a304.so");
39: define(__INFORMIX_DRIVER__, "/home/informix/lib/cli/libifdmr.so");
40: */
41:
42: /** BG
43: *
44: * aprox Line 105 Informix-Libs must be adapted to the actual need at the Informix-Server
45: *
46: */
47:
48: /**
49: * mainly based on: PDO_PGSQL database driver
50: * @author Marcos S�nchez [marcosdsanchez at thinkclear dot com dot ar]
51: */
52:
53: /**
54: * EXPERIMENTAL Informix database driver bases (via copy) on this work:
55: *
56: * Copyright (C) 2009
57: * Josue Balbuena - Ajusco Technology Developers, S.C. <josue.balbuena@gmail.com>
58: *
59: * Database Adapter for Informix SQL Server
60: * Utilizes the Informix extension : ESQL/C is now part of the Informix Client SDK
61: *
62: * @author BG = Bernhard Gramberg [qcubed@gramberg.de]
63: * @package DatabaseAdapters
64: */
65: class QInformixPdoDatabase extends QPdoDatabase {
66: const Adapter = 'Informix PDO Database Adapter';
67: const PDO_INFORMXIX_DSN_IDENTIFIER = 'informix'; // BG needed ?
68:
69: public function Connect() {
70: // Lookup Adapter-Specific Connection Properties
71: // $strDsn = sprintf("%s:host=%s;dbname=%s;port=%s",QInformixPdoDatabase::PDO_PGSQL_DSN_IDENTIFIER, $this->Server, $this->Database, $this->Port);
72:
73: $strDsn = $this->getInformixPdoDsn($this->Database, $this->Host, $this->Server, $this->Service, $this->Protocol); // BG
74:
75: // Connect to the Database Server
76: try {
77: $this->objPdo = new PDO($strDsn, $this->Username, $this->Password);
78: } catch (PDOException $expPgSql) {
79: throw new QInformixDatabaseException(sprintf("Unable to connect to Database: %s",$expPgSql->getMessage()), -1, null);
80: }
81:
82: // BG Informix specific PDO setting
83: $this->objPdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // BG get some warnings as well
84: $this->objPdo->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); // BG downshift letters in fields: ABC -> abc
85:
86: // Update Connected Flag
87: $this->blnConnectedFlag = true;
88: }
89:
90: public function Close()
91: {
92: parent::Close();
93:
94: // Update Connected Flag
95: $this->blnConnectedFlag = false;
96: }
97:
98: function getInformixPdoDsn($database, $host, $server, $service, $protocol) {
99: /** Informix naming convention:
100: * host = IP-Adresse of the Server, where the Informix-Server is running
101: * server = Internal Informix-Name of the Informix-Instance
102: * service = Port, where Informix is listening
103: * protocol = like ONSOCTCP, informix specific protocols
104: */
105:
106: // build PDO-dsn-String
107: $scroll = "EnableScrollableCursors=1"; // Scroll-Cursor an machen
108: $dsn = "informix:host=$host;service=$service;";
109: $dsn .= "database=$database;protocol=$protocol;server=$server;$scroll;;";
110: $dsn .= "TRANSLATIONDLL=" . __INFORMIX_TRANSLATION__ . ";Driver=" . __INFORMIX_DRIVER__ . ";;";
111: return $dsn;
112: }
113:
114: public function SqlVariable($mixData, $blnIncludeEquality = false, $blnReverseEquality = false) {
115: // Are we SqlVariabling a BOOLEAN value?
116: if (is_bool($mixData)) {
117: // Yes
118: if ($blnIncludeEquality) {
119: // We must include the inequality
120:
121: if ($blnReverseEquality) {
122: // Do a "Reverse Equality"
123:
124: // Check against NULL, True then False
125: if (is_null($mixData))
126: return 'IS NOT NULL';
127: else if ($mixData)
128: return "= '0'";
129: else
130: return "!= '0'";
131: } else {
132: // Check against NULL, True then False
133: if (is_null($mixData))
134: return 'IS NULL';
135: else if ($mixData)
136: return "!= '0'";
137: else
138: return "= '0'";
139: }
140: } else {
141: // Check against NULL, True then False
142: if (is_null($mixData))
143: return 'NULL';
144: else if ($mixData)
145: return "'1'";
146: else
147: return "'0'";
148: }
149: }
150:
151: // Check for Equality Inclusion
152: if ($blnIncludeEquality) {
153: if ($blnReverseEquality) {
154: if (is_null($mixData))
155: $strToReturn = 'IS NOT ';
156: else
157: $strToReturn = '!= ';
158: } else {
159: if (is_null($mixData))
160: $strToReturn = 'IS ';
161: else
162: $strToReturn = '= ';
163: }
164: } else
165: $strToReturn = '';
166:
167: // Check for NULL Value
168: if (is_null($mixData))
169: return $strToReturn . 'NULL';
170:
171: // Check for NUMERIC Value
172: if (is_integer($mixData) || is_float($mixData))
173: return $strToReturn . sprintf('%s', $mixData);
174:
175: // Check for DATE Value
176: if ($mixData instanceof QDateTime) {
177: if ($mixData->IsTimeNull())
178: return $strToReturn . sprintf("'%s'", $mixData->__toString('YYYY-MM-DD'));
179: else
180: return $strToReturn . sprintf("'%s'", $mixData->__toString(QDateTime::FormatIso));
181: }
182:
183: // Assume it's some kind of string value
184: return $strToReturn . sprintf("'%s'", addslashes($mixData));
185: }
186:
187:
188:
189: public function SqlLimitVariableSuffix($strLimitInfo) {
190: // BG changed, in the ifx-adapter, LIMIt is via Prefix
191: // Informix uses Limit by prefix (via a LIMIT clause)
192: return null;
193: }
194:
195: public function SqlLimitVariablePrefix($strLimitInfo) {
196: // Setup limit suffix (if applicable) via a LIMIT clause
197: if (strlen($strLimitInfo)) {
198: if (strpos($strLimitInfo, ';') !== false)
199: throw new Exception('Invalid Semicolon in LIMIT Info');
200: if (strpos($strLimitInfo, '`') !== false)
201: throw new Exception('Invalid Backtick in LIMIT Info');
202:
203: // First figure out if we HAVE an offset
204: $strArray = explode(',', $strLimitInfo);
205:
206: if (count($strArray) == 2) {
207: // Yep -- there's an offset
208: // 04/18/2010 BG LIMIT OFFSET --> SKIP LIMIT
209: return sprintf('SKIP %s LIMIT %s ', $strArray[1], $strArray[0]);
210: } else if (count($strArray) == 1) {
211: return sprintf('LIMIT %s', $strArray[0]);
212: } else {
213: throw new QInformixDatabaseException('Invalid Limit Info: ' . $strLimitInfo, 0, null);
214: }
215: }
216:
217: return null;
218: }
219:
220: public function SqlSortByVariable($strSortByInfo) {
221: // Setup sorting information (if applicable) via a ORDER BY clause
222: if (strlen($strSortByInfo)) {
223: if (strpos($strSortByInfo, ';') !== false)
224: throw new Exception('Invalid Semicolon in ORDER BY Info');
225: if (strpos($strSortByInfo, '`') !== false)
226: throw new Exception('Invalid Backtick in ORDER BY Info');
227:
228: return "ORDER BY $strSortByInfo";
229: }
230:
231: return null;
232: }
233:
234: public function GetTables() {
235: // Postgres / $objResult = $this->Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = current_schema() ORDER BY TABLE_NAME ASC");
236:
237: // BG copy fom InformixSql
238: $objResult = $this->Query(
239: "SELECT tabname FROM systables
240: WHERE tabname NOT LIKE 'sys%'
241: AND tabname NOT LIKE ' GL_%'
242: AND tabname NOT LIKE ' VERSION'
243: ORDER BY tabname ASC"
244: );
245:
246: $strToReturn = array();
247: while ($strRowArray = $objResult->FetchRow())
248: array_push($strToReturn, $strRowArray[0]);
249: return $strToReturn;
250: }
251:
252: // BG New, modified Copy of InformixSql
253: public function GetTableForId($intTableId) {
254: $intTableId = $this->SqlVariable($intTableId);
255: $strQuery = sprintf('
256: SELECT tabname
257: FROM systables
258: WHERE tabid = %s
259: ', $intTableId);
260:
261: $objResult = $this->Query($strQuery);
262: // $objRow = $objResult->FetchRow(); /ifx
263: $objRow = $objResult->GetNextRow(); // BG changed
264: // print ("$strQuery <br> ") ; // BG Testing
265: // print_r( $objRow) ; // BG Testing
266: return $objRow->GetColumn('tabname'); // BG Changed to PDO access
267: }
268:
269: public function GetFieldsForTable($strTableName) {
270: $strTableName = $this->SqlVariable($strTableName);
271: /** Postgres
272: * $strQuery = sprintf('
273: * SELECT
274: * table_name,
275: * column_name,
276: * ordinal_position,
277: * column_default,
278: * is_nullable,
279: * data_type,
280: * character_maximum_length,
281: * (pg_get_serial_sequence(table_name,column_name) IS NOT NULL) AS is_serial
282: * FROM
283: * INFORMATION_SCHEMA.COLUMNS
284: * WHERE
285: * table_schema = current_schema()
286: * AND
287: * table_name = %s
288: * ORDER BY ordinal_position
289: * ', $strTableName);
290: */
291:
292: // BG copy from InformixSql
293: $strQuery = sprintf('
294: SELECT syscolumns.*
295: FROM syscolumns, systables
296: WHERE systables.tabname = %s
297: AND systables.tabid = syscolumns.tabid
298: ORDER BY colno ASC ',
299: $strTableName);
300: $objResult = $this->Query($strQuery);
301:
302: $objFields = array();
303:
304: while ($objRow = $objResult->GetNextRow()) {
305: array_push($objFields, new QInformixPdoDatabaseField($objRow, $this));
306: }
307:
308: return $objFields;
309: }
310:
311: public function InsertId($strTableName = null, $strColumnName = null) {
312: /** Postgres
313: * $strQuery = sprintf('
314: * SELECT currval(pg_get_serial_sequence(%s, %s))
315: * ', $this->SqlVariable($strTableName), $this->SqlVariable($strColumnName));
316:
317: * $objResult = $this->Query($strQuery);
318: * $objRow = $objResult->FetchRow();
319: * return $objRow[0];
320: */
321: return $this->lastId; // BG ???? Correct ?
322: }
323:
324:
325: private function ParseColumnNameArrayFromKeyDefinition($strKeyDefinition) {
326: $strKeyDefinition = trim($strKeyDefinition);
327:
328: // Get rid of the opening "(" and the closing ")"
329: $intPosition = strpos($strKeyDefinition, '(');
330: if ($intPosition === false)
331: throw new Exception("Invalid Key Definition: $strKeyDefinition");
332: $strKeyDefinition = trim(substr($strKeyDefinition, $intPosition + 1));
333:
334: $intPosition = strpos($strKeyDefinition, ')');
335: if ($intPosition === false)
336: throw new Exception("Invalid Key Definition: $strKeyDefinition");
337: $strKeyDefinition = trim(substr($strKeyDefinition, 0, $intPosition));
338: $strKeyDefinition = str_replace(" ","",$strKeyDefinition);
339:
340: // Create the Array
341: // TODO: Current method doesn't support key names with commas or parenthesis in them!
342: $strToReturn = explode(',', $strKeyDefinition);
343:
344: // Take out trailing and leading '"' character in each name (if applicable)
345: for ($intIndex = 0; $intIndex < count($strToReturn); $intIndex++) {
346: $strColumn = $strToReturn[$intIndex];
347:
348: if (substr($strColumn, 0, 1) == '"')
349: $strColumn = substr($strColumn, 1, strpos($strColumn, '"', 1) - 1);
350:
351: $strToReturn[$intIndex] = $strColumn;
352: }
353:
354: return $strToReturn;
355: }
356:
357: public function GetIndexesForTable($strTableName) {
358: $objIndexArray = array();
359:
360: /**
361: * $objResult = $this->Query(sprintf('
362: * SELECT
363: * c2.relname AS indname,
364: * i.indisprimary,
365: * i.indisunique,
366: * pg_catalog.pg_get_indexdef(i.indexrelid) AS inddef
367: * FROM
368: * pg_catalog.pg_class c,
369: * pg_catalog.pg_class c2,
370: * pg_catalog.pg_index i
371: * WHERE
372: * c.relname = %s
373: * AND
374: * pg_catalog.pg_table_is_visible(c.oid)
375: * AND
376: * c.oid = i.indrelid
377: * AND
378: * i.indexrelid = c2.oid
379: * ORDER BY
380: * c2.relname
381: * ', $this->SqlVariable($strTableName)));
382: */
383: // BG yopy of InformixSql
384: // Query sysindexes & sysconstraints to get a list of indexes by TableId
385: $strQuery = sprintf(
386: 'SELECT a.idxname, a.idxtype, a.tabid, b.constrtype, b.constrid
387: FROM sysindexes a, sysconstraints b, systables c
388: WHERE a.idxname = b.idxname
389: AND a.tabid = b.tabid
390: AND a.tabid = c.tabid
391: AND c.tabname = %s', $this->SqlVariable($strTableName));
392: $objResult = $this->Query($strQuery);
393:
394: while ($objRow = $objResult->GetNextRow()) {
395: /** POstgres
396: * $strIndexDefinition = $objRow->GetColumn('inddef');
397: * $strKeyName = $objRow->GetColumn('indname');
398: * $blnPrimaryKey = $objRow->GetColumn('indisprimary');
399: * $blnUnique = $objRow->GetColumn('indisunique');
400: * $strColumnNameArray = $this->ParseColumnNameArrayFromKeyDefinition($strIndexDefinition);
401: */
402: // BG copy of informixSql
403: $strKeyName = $objRow->GetColumn('idxname');
404: $strIndexType = $objRow->GetColumn('idxtype');
405: $intTableId = $objRow->GetColumn('tabid');
406: $strConstraintType = $objRow->GetColumn('constrtype');
407: $intConstraintId = $objRow->GetColumn('constrid');
408: $blnPrimaryKey = (strpos($strConstraintType, 'P') !== false);
409: $blnUnique = (strpos($strIndexType, 'U') !== false);
410: //$strColumnNameArray = explode(', ', $objRow->GetColumn('index_keys'));
411: $strColumnNameArray = $this->GetColumnsForConstraint($intConstraintId, $intTableId);
412:
413: // BG postgres + Informix
414: $objIndex = new QDatabaseIndex($strKeyName, $blnPrimaryKey, $blnUnique, $strColumnNameArray);
415: array_push($objIndexArray, $objIndex);
416: }
417:
418: return $objIndexArray;
419: }
420:
421: // BG New: modified Copy of InformixSql
422: public function GetColumnsForConstraint($intConstraintId, $intTableId){
423: $strColumnNameArray = array();
424: $strQuery = sprintf("
425: SELECT a.constrid, b.*
426: FROM sysconstraints a, sysindexes b
427: WHERE a.idxname = b.idxname
428: AND a.tabid = b.tabid
429: AND a.constrid = %d
430: AND a.tabid = %d",
431: $intConstraintId, $intTableId);
432: $objResult = $this->Query($strQuery);
433: $objRow = $objResult->GetNextRow($objResult); // BG instead of FetchRow
434: //each column in the index is stored in a separate column Part1 thru Part16
435: for($i = 1; $i <= 16; $i++){
436: $intIndexColumnId = $objRow->GetColumn("part$i");
437: if ($intIndexColumnId > 0) {
438: $objIndexColumn = $this->Query(sprintf(
439: 'SELECT colname
440: FROM syscolumns
441: WHERE colno = %d
442: AND tabid = %d',
443: $intIndexColumnId, $intTableId));
444: while ($strRowArray = $objIndexColumn->GetNextRow() ) // BG FetchRow())
445: array_push($strColumnNameArray, $strRowArray->GetColumn('colname'));
446: }
447: }
448: return $strColumnNameArray;
449: }
450:
451: public function GetForeignKeysForTable($strTableName) {
452: $objForeignKeyArray = array();
453:
454: /** Postgres
455: * // Use Query to pull the FKs
456: * $strQuery = sprintf('
457: * SELECT pc.conname, pg_catalog.pg_get_constraintdef(pc.oid, true) AS consrc
458: * FROM pg_catalog.pg_constraint pc
459: * WHERE pc.conrelid =
460: * (SELECT oid FROM pg_catalog.pg_class
461: * WHERE relname=%s
462: * AND relnamespace = (
463: * SELECT oid FROM pg_catalog.pg_namespace
464: * WHERE nspname=current_schema()
465: * )
466: * )
467: * AND pc.contype = \'f\'
468: * ', $this->SqlVariable($strTableName));
469: */
470: // BG copy of InformixSql
471: // Use Query to pull the FKs
472: $strQuery = sprintf(
473: "SELECT a.constrid, a.constrname, a.tabid, b.primary pconstrid, b.ptabid, pk_tables.tabname pk_table, fk_tables.tabname fk_table
474: FROM sysconstraints a, sysreferences b, systables pk_tables, systables fk_tables
475: WHERE a.constrid = b.constrid
476: AND b.ptabid = pk_tables.tabid
477: AND a.tabid = fk_tables.tabid
478: AND fk_tables.tabname = %s",
479: $this->SqlVariable($strTableName));
480:
481: $objResult = $this->Query($strQuery);
482:
483:
484: /**
485: * while ($objRow = $objResult->GetNextRow()) {
486: * $strKeyName = $objRow->GetColumn('conname');
487:
488: * // Remove leading and trailing '"' characters (if applicable)
489: * if (substr($strKeyName, 0, 1) == '"')
490: * $strKeyName = substr($strKeyName, 1, strlen($strKeyName) - 2);
491:
492: * // By the end of the following lines, we will end up with a strTokenArray
493: * // Index 1: the list of columns that are the foreign key
494: * // Index 2: the table which this FK references
495: * // Index 3: the list of columns which this FK references
496: * $strTokenArray = split('FOREIGN KEY ', $objRow->GetColumn('consrc'));
497: * $strTokenArray[1] = split(' REFERENCES ', $strTokenArray[1]);
498: * $strTokenArray[2] = $strTokenArray[1][1];
499: * $strTokenArray[1] = $strTokenArray[1][0];
500: * $strTokenArray[2] = explode("(", $strTokenArray[2]);
501: * $strTokenArray[3] = "(".$strTokenArray[2][1];
502: * $strTokenArray[2] = $strTokenArray[2][0];
503:
504: * // Remove leading and trailing '"' characters (if applicable)
505: * if (substr($strTokenArray[2], 0, 1) == '"')
506: * $strTokenArray[2] = substr($strTokenArray[2], 1, strlen($strTokenArray[2]) - 2);
507:
508: * $strColumnNameArray = $this->ParseColumnNameArrayFromKeyDefinition($strTokenArray[1]);
509: * $strReferenceTableName = $strTokenArray[2];
510: * $strReferenceColumnNameArray = $this->ParseColumnNameArrayFromKeyDefinition($strTokenArray[3]);
511:
512: * $objForeignKey = new QDatabaseForeignKey(
513: * $strKeyName,
514: * $strColumnNameArray,
515: * $strReferenceTableName,
516: * $strReferenceColumnNameArray);
517: * array_push($objForeignKeyArray, $objForeignKey);
518: * }
519: */
520: // Bg copy of InformixSql
521: $strKeyName = '';
522: while ($objRow = $objResult->GetNextRow()) {
523: if ($strKeyName != $objRow->GetColumn('constrname')) {
524: if ($strKeyName) {
525: $objForeignKey = new QDatabaseForeignKey(
526: $strKeyName,
527: $strColumnNameArray,
528: $strReferenceTableName,
529: $strReferenceColumnNameArray);
530: array_push($objForeignKeyArray, $objForeignKey);
531: }
532:
533: $strKeyName = $objRow->GetColumn('constrname');
534: $intConstraintId = $objRow->GetColumn('constrid');
535: $intTableId = $objRow->GetColumn('tabid');
536: $strReferenceTableName = $objRow->GetColumn('pk_table');
537: $intReferenceConstraintId = $objRow->GetColumn('pconstrid');
538: $intReferenceTableId = $objRow->GetColumn('ptabid');
539: $strColumnNameArray = array();
540: $strReferenceColumnNameArray = array();
541: }
542:
543: $strColumnNameArray = $this->GetColumnsForConstraint($intConstraintId, $intTableId);
544: $strReferenceColumnNameArray = $this->GetColumnsForConstraint($intReferenceConstraintId, $intReferenceTableId);
545: }
546:
547: if ($strKeyName) {
548: $objForeignKey = new QDatabaseForeignKey(
549: $strKeyName,
550: $strColumnNameArray,
551: $strReferenceTableName,
552: $strReferenceColumnNameArray);
553: array_push($objForeignKeyArray, $objForeignKey);
554: }
555:
556: // --- BG End of Copy
557:
558: // Return the Array of Foreign Keys
559: return $objForeignKeyArray;
560: }
561:
562:
563:
564: protected function ExecuteQuery($strQuery) {
565: $strQuery = $this->QueryStringToInformixSyntax ($strQuery);
566:
567: // echo "$strQuery <br>" ;
568: // $objResult = $this->objPdo->query($strQuery);
569:
570: try {
571: $objResult = $this->objPdo->query($strQuery);
572: } catch (PDOException $expPgSql) {
573: # throw new QInformixDatabaseException(sprintf("Unable to connect to Database: %s",$expPgSql->getMessage()), -1, null);
574: echo "Catched ERROR: $strQuery <br>" ;
575: throw new QPdoDatabaseException($this->objPdo->errorInfo(), $this->objPdo->errorCode(), $strQuery);
576: }
577:
578: /*
579: if ($objResult === false)
580: {
581: echo "$strQuery <br>" ;
582: throw new QPdoDatabaseException($this->objPdo->errorInfo(), $this->objPdo->errorCode(), $strQuery);
583: }
584:
585: */
586: // Return the Result
587: $this->objMostRecentResult = $objResult;
588: $objPdoStatementDatabaseResult = new QInformixPdoDatabaseResult($objResult, $this);
589: return $objPdoStatementDatabaseResult;
590: }
591:
592:
593: // BG Copied from generic PDO-adapter, because SQL-String not comaptible with Informix (to much " )
594: protected function ExecuteNonQuery($strNonQuery) {
595: $strNonQuery = $this->QueryStringToInformixSyntax ($strNonQuery);
596:
597: // Perform the Query
598: $objResult = $this->objPdo->query($strNonQuery);
599: if ($objResult === false)
600: throw new QPdoDatabaseException($this->objPdo->errorInfo(), $this->objPdo->errorCode(), $strNonQuery);
601: $this->objMostRecentResult = $objResult;
602: }
603:
604: function QueryStringToInformixSyntax ( $strQuery ) {
605: $strQuery = str_replace('"','',$strQuery); //
606: //remove backslash from escaped characters like \" and \\
607: $strQuery = stripslashes($strQuery);
608:
609: // Informix does not accept the word AS to alias a table
610: $strQuery = str_replace(' AS ',' ',$strQuery);
611:
612: return $strQuery ;
613: }
614:
615:
616: } // end of class
617:
618:
619:
620: /**
621: * QInformixPdoDatabaseResult: Class to handle results sent by database upon querying
622: */
623: class QInformixPdoDatabaseResult extends QPdoDatabaseResult {
624:
625: public function GetNextRow() {
626: $strColumnArray = $this->FetchArray();
627:
628: if ($strColumnArray)
629: return new QInformixPdoDatabaseRow($strColumnArray);
630: else
631: return null;
632: }
633:
634: public function FetchFields() {
635: $objArrayToReturn = array();
636: while ($objField = $this->FetchColumn()) {
637: array_push($objArrayToReturn, new QInformixPdoDatabaseField($objField, $this->objDb));
638: }
639: return $objArrayToReturn;
640: }
641:
642: public function FetchField() {
643: if ($objField = $this->FetchColumn())
644: return new QInformixPdoDatabaseField($objField, $this->objDb);
645: }
646:
647: }
648: /**
649: * QInformixPdoDatabaseRow
650: */
651: class QInformixPdoDatabaseRow extends QDatabaseRowBase {
652: protected $strColumnArray;
653:
654: public function __construct($strColumnArray) {
655: $this->strColumnArray = $strColumnArray;
656: }
657:
658: /**
659: * Gets the value of a column from a result row returned by the database
660: *
661: * @param string $strColumnName Name of te column
662: * @param null|QDatabaseFieldType $strColumnType Data type
663: *
664: * @return mixed
665: */
666: public function GetColumn($strColumnName, $strColumnType = null) {
667: if (!isset($this->strColumnArray[$strColumnName])) {
668: return null;
669: }
670: $strColumnValue = $this->strColumnArray[$strColumnName];
671: switch ($strColumnType) {
672: case QDatabaseFieldType::Bit:
673: if (!$strColumnValue) {
674: return false;
675: } else {
676: return ($strColumnValue) ? true : false;
677: }
678:
679: case QDatabaseFieldType::Blob:
680: case QDatabaseFieldType::Char:
681: case QDatabaseFieldType::VarChar:
682: return QType::Cast($strColumnValue, QType::String);
683:
684: case QDatabaseFieldType::Date:
685: case QDatabaseFieldType::DateTime:
686: case QDatabaseFieldType::Time:
687: return new QDateTime($strColumnValue);
688:
689: case QDatabaseFieldType::Float:
690: return QType::Cast($strColumnValue, QType::Float);
691:
692: case QDatabaseFieldType::Integer:
693: return QType::Cast($strColumnValue, QType::Integer);
694:
695: default:
696: return $strColumnValue;
697: }
698: }
699:
700: /**
701: * Tells whether a particular column exists in a returned database row
702: *
703: * @param string $strColumnName Name of te column
704: *
705: * @return bool
706: */
707: public function ColumnExists($strColumnName) {
708: return array_key_exists($strColumnName, $this->strColumnArray);
709: }
710:
711: public function GetColumnNameArray() {
712: return $this->strColumnArray;
713: }
714: }
715: /**
716: * QInformixPdoDatabaseField
717: *
718: *
719: * BG complete copy from InformixSql
720: */
721:
722: class QInformixPdoDatabaseField extends QDatabaseFieldBase {
723: public function __construct($mixFieldData, $objDb = null) {
724: $objDatabaseRow = null;
725:
726: $objDatabaseRow = $mixFieldData ; // BG New
727:
728: /**
729: * try {
730: * $objDatabaseRow = QType::Cast($mixFieldData, 'QInformixSqlDatabaseRow');
731: * } catch (InvalidCastException $objExc) {
732: * }
733: */
734:
735: if ($objDatabaseRow) {
736: // Passed in field data is a row from select * from syscolumns for this table
737: $intTableId = $objDatabaseRow->GetColumn('tabid');
738: $this->strName = $objDatabaseRow->GetColumn('colname');
739: $this->strOriginalName = $this->strName;
740: $this->strTable = $objDb->GetTableForId($intTableId);
741: $this->strOriginalTable = $this->strTable;
742: $this->strDefault = null; /* Not Supported */
743: // If the coltype contains a value greater than 256, it does not allow null values.
744: $this->blnNotNull = ($objDatabaseRow->GetColumn('coltype')>=256) ? true : false;
745:
746: // Determine Primary Key
747: $objResult = $objDb->Query(sprintf("
748: SELECT a.constrid, a.constrname, c.colname
749: FROM sysconstraints a, sysindexes b, syscolumns c
750: WHERE (a.idxname = b.idxname and b.part1 = c.colno and a.tabid = b.tabid and b.tabid = c.tabid)
751: AND a.tabid = %d and a.constrtype = 'P'", $intTableId));
752: while ($objRow = $objResult->GetNextRow()) {
753: if ($objRow->GetColumn('colname') == $this->strName)
754: $this->blnPrimaryKey = true;
755: }
756: if (!$this->blnPrimaryKey)
757: $this->blnPrimaryKey = false;
758:
759: // UNIQUE
760: $objResult = $objDb->Query(sprintf("
761: SELECT a.idxname, a.idxtype, b.colname
762: FROM sysindexes a, syscolumns b
763: WHERE a.tabid = b.tabid and a.part1 = b.colno and a.part2 = 0 and a.tabid = %d", $intTableId));
764: while ($objRow = $objResult->GetNextRow()) {
765: if ($objRow->GetColumn('colname') == $this->strName && $objRow->GetColumn('idxtype') == 'U')
766: $this->blnUnique = true;
767: }
768: if (!$this->blnUnique)
769: $this->blnUnique = false;
770:
771:
772: /* Figure out Type, Maxlength and Identity by using syscolumns */
773:
774: $this->blnIdentity = false; // A serial is an identity column
775:
776: /* For each column in the tablea corresponding 'coltype' value will be given that is a numeric
777: representation of the column type.
778:
779: 0 = CHAR 8 = MONEY
780: 1 = SMALLINT 10 = DATETIME
781: 2 = INTEGER 11 = BYTE
782: 3 = FLOAT 12 = TEXT
783: 4 = SMALLFLOAT 13 = VARCHAR
784: 5 = DECIMAL 14 = INTERVAL
785: 6 = SERIAL 15 = NCHAR
786: 7 = DATE 16 = NVARCHAR
787:
788: */
789:
790: $intColType =$objDatabaseRow->GetColumn('coltype', QDatabaseFieldType::Integer );
791: $this->intMaxLength = $objDatabaseRow->GetColumn('collength', QDatabaseFieldType::Integer);
792: switch (($intColType < 256) ? $intColType : $intColType - 256 ) {
793: case 0: //char
794: $this->strType = QDatabaseFieldType::Char;
795: break;
796: case 1: //smallint
797: $this->strType = QDatabaseFieldType::Integer;
798: break;
799: case 2: //integer
800: $this->strType = QDatabaseFieldType::Integer;
801: break;
802: case 3: //float
803: $this->strType = QDatabaseFieldType::Float;
804: break;
805: case 4: //smallfloat
806: $this->strType = QDatabaseFieldType::Float;
807: break;
808: case 5: //decimal
809: $this->intMaxLength = ((($objDatabaseRow->GetColumn('collength', QDatabaseFieldType::Integer))>>8) & 0xff);
810: case 6: //serial
811: $this->strType = QDatabaseFieldType::Integer;
812: $this->blnIdentity = true; //if a serial is found: this is the identity column
813: break;
814: case 7: //date
815: $this->strType = QDatabaseFieldType::Date;
816: break;
817: case 8: //money
818: $this->strType = QDatabaseFieldType::Float;
819: $this->intMaxLength = ((($objDatabaseRow->GetColumn('collength', QDatabaseFieldType::Integer))>>8) & 0xff);
820: break;
821: case 'bit':
822: $this->strType = QDatabaseFieldType::Bit;
823: break;
824: case 10: //datetime
825: $this->strType = QDatabaseFieldType::DateTime;
826: break;
827: case 11: //byte
828: $this->strType = QDatabaseFieldType::Integer;
829: break;
830: case 12: //text
831: $this->strType = QDatabaseFieldType::Blob;
832: break;
833: case 13: //varchar
834: $this->strType = QDatabaseFieldType::VarChar;
835: $this->intMaxLength = (($objDatabaseRow->GetColumn('collength', QDatabaseFieldType::Integer)) & 0x00ff);
836: // BG added Q -> QDatabsseFieldType
837: break;
838: case 14: //interval
839: $this->strType = QDatabaseFieldType::Integer;
840: break;
841: case 15: //nchar
842: $this->strType = QDatabaseFieldType::VarChar;
843: break;
844: case 16: //nvarchar
845: $this->intMaxLength = (($objDatabaseRow->GetColumn('collength', QDatabaseFieldType::Integer)) & 0x00ff);
846: $this->strType = QDatabaseFieldType::VarChar;
847: break;
848: default:
849: throw new QInformixSqlDatabaseException('Unsupported Field Type: ' . $intColType, 0, null);
850: }
851: } else {
852: // Passed in fielddata is a ifx_fetch_field field result
853: $this->strName = $mixFieldData->name;
854: $this->strOriginalName = $mixFieldData->name;
855: $this->strTable = $mixFieldData->column_source;
856: $this->strOriginalTable = $mixFieldData->column_source;
857: $this->intMaxLength = $mixFieldData->max_length;
858: }
859: }
860: }
861:
862:
863: /** Postgres
864: * class QInformixPdoDatabaseField extends QDatabaseFieldBase {
865: * public function __construct($mixFieldData, $objDb = null) {
866: * $this->strName = $mixFieldData->GetColumn('column_name');
867: * $this->strOriginalName = $this->strName;
868: * $this->strTable = $mixFieldData->GetColumn('table_name');
869: * $this->strOriginalTable = $this->strTable;
870: * $this->strDefault = $mixFieldData->GetColumn('column_default');
871: * $this->intMaxLength = $mixFieldData->GetColumn('character_maximum_length', QDatabaseFieldType::Integer);
872: * $this->blnNotNull = ($mixFieldData->GetColumn('is_nullable') == "NO") ? true : false;
873:
874: * // If the first column of the table was created as SERIAL, we assume it's the identity field.
875: * // Otherwise, no identity field will be set for this table.
876: * $ordinalPos = $mixFieldData->GetColumn('ordinal_position', QDatabaseFieldType::Integer);
877: * $isSerial = $mixFieldData->GetColumn('is_serial');
878: * $this->blnIdentity = ($ordinalPos == 1 && $isSerial) ? true : false;
879:
880: * // Determine Primary Key
881: * $objResult = $objDb->Query(sprintf('
882: * SELECT
883: * kcu.column_name
884: * FROM
885: * information_schema.table_constraints tc,
886: * information_schema.key_column_usage kcu
887: * WHERE
888: * tc.table_name = %s
889: * AND
890: * tc.table_schema = current_schema()
891: * AND
892: * tc.constraint_type = \'PRIMARY KEY\'
893: * AND
894: * kcu.table_name = tc.table_name
895: * AND
896: * kcu.table_schema = tc.table_schema
897: * AND
898: * kcu.constraint_name = tc.constraint_name
899: * ', $objDb->SqlVariable($this->strTable)));
900:
901: * while ($objRow = $objResult->GetNextRow()) {
902: * if ($objRow->GetColumn('column_name') == $this->strName)
903: * $this->blnPrimaryKey = true;
904: * }
905:
906: * if (!$this->blnPrimaryKey)
907: * $this->blnPrimaryKey = false;
908:
909: * // UNIQUE
910: * $objResult = $objDb->Query(sprintf('
911: * SELECT
912: * kcu.column_name, (SELECT COUNT(*) FROM information_schema.key_column_usage kcu2 WHERE kcu2.constraint_name=kcu.constraint_name ) as unique_fields
913: * FROM
914: * information_schema.table_constraints tc,
915: * information_schema.key_column_usage kcu
916: * WHERE
917: * tc.table_name = %s
918: * AND
919: * tc.table_schema = current_schema()
920: * AND
921: * tc.constraint_type = \'UNIQUE\'
922: * AND
923: * kcu.table_name = tc.table_name
924: * AND
925: * kcu.table_schema = tc.table_schema
926: * AND
927: * kcu.constraint_name = tc.constraint_name
928: * GROUP BY
929: * kcu.constraint_name, kcu.column_name
930: * ', $objDb->SqlVariable($this->strTable)));
931: * while ($objRow = $objResult->GetNextRow()) {
932: * if ($objRow->GetColumn('column_name') == $this->strName && $objRow->GetColumn('unique_fields') == 1)
933: * $this->blnUnique = true;
934: * }
935: * if (!$this->blnUnique)
936: * $this->blnUnique = false;
937:
938: * // Determine Type
939: * $this->strType = $mixFieldData->GetColumn('data_type');
940:
941: * switch ($this->strType) {
942: * case 'integer':
943: * case 'smallint':
944: * $this->strType = QDatabaseFieldType::Integer;
945: * break;
946: * case 'money':
947: * // NOTE: The money type is deprecated in Informix.
948: * throw new QInformixDatabaseException('Unsupported Field Type: money. Use numeric or decimal instead.', 0,null);
949: * break;
950: * case 'bigint':
951: * case 'decimal':
952: * case 'numeric':
953: * case 'real':
954: * // "BIGINT" must be specified here as a float so that PHP can support it's size
955: * // http://www.Informix.org/docs/8.2/static/datatype-numeric.html
956: * $this->strType = QDatabaseFieldType::Float;
957: * break;
958: * case 'bit':
959: * if ($this->intMaxLength == 1)
960: * $this->strType = QDatabaseFieldType::Bit;
961: * else
962: * throw new QInformixDatabaseException('Unsupported Field Type: bit with MaxLength > 1', 0, null);
963: * break;
964: * case 'boolean':
965: * $this->strType = QDatabaseFieldType::Bit;
966: * break;
967: * case 'character':
968: * $this->strType = QDatabaseFieldType::Char;
969: * break;
970: * case 'character varying':
971: * case 'double precision':
972: * // NOTE: PHP does not offer full support of double-precision floats.
973: * // Value will be set as a VarChar which will guarantee that the precision will be maintained.
974: * // However, you will not be able to support full typing control (e.g. you would
975: * // not be able to use a QFloatTextBox -- only a regular QTextBox)
976: * $this->strType = QDatabaseFieldType::VarChar;
977: * break;
978: * case 'text':
979: * $this->strType = QDatabaseFieldType::Blob;
980: * break;
981: * case 'timestamp':
982: * case 'timestamp without time zone':
983: * // System-generated Timestamp values need to be treated as plain text
984: * $this->strType = QDatabaseFieldType::VarChar;
985: * $this->blnTimestamp = true;
986: * break;
987: * case 'date':
988: * $this->strType = QDatabaseFieldType::Date;
989: * break;
990: * case 'time':
991: * case 'time without time zone':
992: * $this->strType = QDatabaseFieldType::Time;
993: * break;
994: * default:
995: * throw new QInformixDatabaseException('Unsupported Field Type: ' . $this->strType, 0, null);
996: * }
997: * }
998: * }
999: */
1000: /**
1001: * QInformixPdoDatabaseException
1002: */
1003: class QInformixPdoDatabaseException extends QPdoDatabaseException {
1004:
1005: }