ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilDBPdoFieldDefinition.php
Go to the documentation of this file.
1 <?php
2 
8 abstract class ilDBPdoFieldDefinition
9 {
11  const DEFAULT_TEXT_LENGTH = 4000;
12  const DEFINITION_COLUMN_NAME = "/^[a-z]+[_a-z0-9]*$/";
13  const DEFINITION_TABLE_NAME = "/^[a-z]+[_a-z0-9]*$/";
14  const INDEX_FORMAT = '%s_idx';
15  const SEQUENCE_COLUMNS_NAME = 'sequence';
16  const SEQUENCE_FORMAT = '%s_seq';
17  const T_BLOB = 'blob';
18  const T_CLOB = 'clob';
19  const T_DATE = 'date';
20  const T_DATETIME = 'datetime';
21  const T_FLOAT = 'float';
22  const T_INTEGER = 'integer';
23  const T_TEXT = 'text';
24  const T_TIME = 'time';
25  const T_TIMESTAMP = 'timestamp';
29  protected static $instance;
33  public $allowed_attributes_old = array(
34  self::T_TEXT => array( 'length', 'notnull', 'default', 'fixed' ),
35  self::T_INTEGER => array( 'length', 'notnull', 'default', 'unsigned' ),
36  self::T_FLOAT => array( 'notnull', 'default' ),
37  self::T_DATE => array( 'notnull', 'default' ),
38  self::T_TIME => array( 'notnull', 'default' ),
39  self::T_TIMESTAMP => array( 'notnull', 'default' ),
40  self::T_CLOB => array( 'notnull', 'default' ),
41  self::T_BLOB => array( 'notnull', 'default' ),
42  );
46  public $allowed_attributes = array(
47  "text" => array( "length", "notnull", "default", "fixed" ),
48  "integer" => array( "length", "notnull", "default", "unsigned" ),
49  "float" => array( "notnull", "default" ),
50  "date" => array( "notnull", "default" ),
51  "time" => array( "notnull", "default" ),
52  "timestamp" => array( "notnull", "default" ),
53  "clob" => array( "length", "notnull", "default" ),
54  "blob" => array( "length", "notnull", "default" ),
55  );
59  protected $db_instance;
63  protected $max_length = array(
64  self::T_INTEGER => array( 1, 2, 3, 4, 8 ),
65  self::T_TEXT => 4000,
66  );
70  protected $available_types = array(
71  self::T_TEXT,
72  self::T_INTEGER,
73  self::T_FLOAT,
74  self::T_DATE,
75  self::T_TIME,
76  self::T_TIMESTAMP,
77  self::T_CLOB,
78  self::T_BLOB,
79  );
83  protected $reserved_mysql = array(
84  "ACCESSIBLE",
85  "ACCOUNT",
86  "ACTION",
87  "ADD",
88  "AFTER",
89  "AGAINST",
90  "AGGREGATE",
91  "ALGORITHM",
92  "ALL",
93  "ALTER",
94  "ALWAYS",
95  "ANALYSE",
96  "ANALYZE",
97  "AND",
98  "ANY",
99  "AS",
100  "ASC",
101  "ASCII",
102  "ASENSITIVE",
103  "AT",
104  "AUTHORS",
105  "AUTOEXTEND_SIZE",
106  "AUTO_INCREMENT",
107  "AVG",
108  "AVG_ROW_LENGTH",
109  "BACKUP",
110  "BEFORE",
111  "BEGIN",
112  "BETWEEN",
113  "BIGINT",
114  "BINARY",
115  "BINLOG",
116  "BIT",
117  "BLOB",
118  "BLOCK",
119  "BOOL",
120  "BOOLEAN",
121  "BOTH",
122  "BTREE",
123  "BY",
124  "BYTE",
125  "CACHE",
126  "CALL",
127  "CASCADE",
128  "CASCADED",
129  "CASE",
130  "CATALOG_NAME",
131  "CHAIN",
132  "CHANGE",
133  "CHANGED",
134  "CHANNEL",
135  "CHAR",
136  "CHARACTER",
137  "CHARSET",
138  "CHECK",
139  "CHECKSUM",
140  "CIPHER",
141  "CLASS_ORIGIN",
142  "CLIENT",
143  "CLOSE",
144  "COALESCE",
145  "CODE",
146  "COLLATE",
147  "COLLATION",
148  "COLUMN",
149  "COLUMNS",
150  "COLUMN_FORMAT",
151  "COLUMN_NAME",
152  "COMMENT",
153  "COMMIT",
154  "COMMITTED",
155  "COMPACT",
156  "COMPLETION",
157  "COMPRESSED",
158  "COMPRESSION",
159  "CONCURRENT",
160  "CONDITION",
161  "CONNECTION",
162  "CONSISTENT",
163  "CONSTRAINT",
164  "CONSTRAINT_CATALOG",
165  "CONSTRAINT_NAME",
166  "CONSTRAINT_SCHEMA",
167  "CONTAINS",
168  "CONTEXT",
169  "CONTINUE",
170  "CONTRIBUTORS",
171  "CONVERT",
172  "CPU",
173  "CREATE",
174  "CROSS",
175  "CUBE",
176  "CURRENT",
177  "CURRENT_DATE",
178  "CURRENT_TIME",
179  "CURRENT_TIMESTAMP",
180  "CURRENT_USER",
181  "CURSOR",
182  "CURSOR_NAME",
183  "DATA",
184  "DATABASE",
185  "DATABASES",
186  "DATAFILE",
187  "DATE",
188  "DATETIME",
189  "DAY",
190  "DAY_HOUR",
191  "DAY_MICROSECOND",
192  "DAY_MINUTE",
193  "DAY_SECOND",
194  "DEALLOCATE",
195  "DEC",
196  "DECIMAL",
197  "DECLARE",
198  "DEFAULT",
199  "DEFAULT_AUTH",
200  "DEFINER",
201  "DELAYED",
202  "DELAY_KEY_WRITE",
203  "DELETE",
204  "DESC",
205  "DESCRIBE",
206  "DES_KEY_FILE",
207  "DETERMINISTIC",
208  "DIAGNOSTICS",
209  "DIRECTORY",
210  "DISABLE",
211  "DISCARD",
212  "DISK",
213  "DISTINCT",
214  "DISTINCTROW",
215  "DIV",
216  "DO",
217  "DOUBLE",
218  "DROP",
219  "DUAL",
220  "DUMPFILE",
221  "DUPLICATE",
222  "DYNAMIC",
223  "EACH",
224  "ELSE",
225  "ELSEIF",
226  "ENABLE",
227  "ENCLOSED",
228  "ENCRYPTION",
229  "END",
230  "ENDS",
231  "ENGINE",
232  "ENGINES",
233  "ENUM",
234  "ERROR",
235  "ERRORS",
236  "ESCAPE",
237  "ESCAPED",
238  "EVENT",
239  "EVENTS",
240  "EVERY",
241  "EXCHANGE",
242  "EXECUTE",
243  "EXISTS",
244  "EXIT",
245  "EXPANSION",
246  "EXPIRE",
247  "EXPLAIN",
248  "EXPORT",
249  "EXTENDED",
250  "EXTENT_SIZE",
251  "FALSE",
252  "FAST",
253  "FAULTS",
254  "FETCH",
255  "FIELDS",
256  "FILE",
257  "FILE_BLOCK_SIZE",
258  "FILTER",
259  "FIRST",
260  "FIXED",
261  "FLOAT",
262  "FLOAT4",
263  "FLOAT8",
264  "FLUSH",
265  "FOLLOWS",
266  "FOR",
267  "FORCE",
268  "FOREIGN",
269  "FORMAT",
270  "FOUND",
271  "FROM",
272  "FULL",
273  "FULLTEXT",
274  "FUNCTION",
275  "GENERAL",
276  "GENERATED",
277  "GEOMETRY",
278  "GEOMETRYCOLLECTION",
279  "GET",
280  "GET_FORMAT",
281  "GLOBAL",
282  "GRANT",
283  "GRANTS",
284  "GROUP",
285  "GROUP_REPLICATION",
286  "HANDLER",
287  "HASH",
288  "HAVING",
289  "HELP",
290  "HIGH_PRIORITY",
291  "HOST",
292  "HOSTS",
293  "HOUR",
294  "HOUR_MICROSECOND",
295  "HOUR_MINUTE",
296  "HOUR_SECOND",
297  "IDENTIFIED",
298  "IF",
299  "IGNORE",
300  "IGNORE_SERVER_IDS",
301  "IMPORT",
302  "IN",
303  "INDEX",
304  "INDEXES",
305  "INFILE",
306  "INITIAL_SIZE",
307  "INNER",
308  "INOUT",
309  "INSENSITIVE",
310  "INSERT",
311  "INSERT_METHOD",
312  "INSTALL",
313  "INSTANCE",
314  "INT",
315  "INT1",
316  "INT2",
317  "INT3",
318  "INT4",
319  "INT8",
320  "INTEGER",
321  "INTERVAL",
322  "INTO",
323  "INVOKER",
324  "IO",
325  "IO_AFTER_GTIDS",
326  "IO_BEFORE_GTIDS",
327  "IO_THREAD",
328  "IPC",
329  "IS",
330  "ISOLATION",
331  "ISSUER",
332  "ITERATE",
333  "JOIN",
334  "JSON",
335  "KEY",
336  "KEYS",
337  "KEY_BLOCK_SIZE",
338  "KILL",
339  "LANGUAGE",
340  "LAST",
341  "LEADING",
342  "LEAVE",
343  "LEAVES",
344  "LEFT",
345  "LESS",
346  "LEVEL",
347  "LIKE",
348  "LIMIT",
349  "LINEAR",
350  "LINES",
351  "LINESTRING",
352  "LIST",
353  "LOAD",
354  "LOCAL",
355  "LOCALTIME",
356  "LOCALTIMESTAMP",
357  "LOCK",
358  "LOCKS",
359  "LOGFILE",
360  "LOGS",
361  "LONG",
362  "LONGBLOB",
363  "LONGTEXT",
364  "LOOP",
365  "LOW_PRIORITY",
366  "MASTER",
367  "MASTER_AUTO_POSITION",
368  "MASTER_BIND",
369  "MASTER_CONNECT_RETRY",
370  "MASTER_DELAY",
371  "MASTER_HEARTBEAT_PERIOD",
372  "MASTER_HOST",
373  "MASTER_LOG_FILE",
374  "MASTER_LOG_POS",
375  "MASTER_PASSWORD",
376  "MASTER_PORT",
377  "MASTER_RETRY_COUNT",
378  "MASTER_SERVER_ID",
379  "MASTER_SSL",
380  "MASTER_SSL_CA",
381  "MASTER_SSL_CAPATH",
382  "MASTER_SSL_CERT",
383  "MASTER_SSL_CIPHER",
384  "MASTER_SSL_CRL",
385  "MASTER_SSL_CRLPATH",
386  "MASTER_SSL_KEY",
387  "MASTER_SSL_VERIFY_SERVER_CERT",
388  "MASTER_TLS_VERSION",
389  "MASTER_USER",
390  "MATCH",
391  "MAXVALUE",
392  "MAX_CONNECTIONS_PER_HOUR",
393  "MAX_QUERIES_PER_HOUR",
394  "MAX_ROWS",
395  "MAX_SIZE",
396  "MAX_STATEMENT_TIME",
397  "MAX_UPDATES_PER_HOUR",
398  "MAX_USER_CONNECTIONS",
399  "MEDIUM",
400  "MEDIUMBLOB",
401  "MEDIUMINT",
402  "MEDIUMTEXT",
403  "MEMORY",
404  "MERGE",
405  "MESSAGE_TEXT",
406  "MICROSECOND",
407  "MIDDLEINT",
408  "MIGRATE",
409  "MINUTE",
410  "MINUTE_MICROSECOND",
411  "MINUTE_SECOND",
412  "MIN_ROWS",
413  "MOD",
414  "MODE",
415  "MODIFIES",
416  "MODIFY",
417  "MONTH",
418  "MULTILINESTRING",
419  "MULTIPOINT",
420  "MULTIPOLYGON",
421  "MUTEX",
422  "MYSQL_ERRNO",
423  "NAME",
424  "NAMES",
425  "NATIONAL",
426  "NATURAL",
427  "NCHAR",
428  "NDB",
429  "NDBCLUSTER",
430  "NEVER",
431  "NEW",
432  "NEXT",
433  "NO",
434  "NODEGROUP",
435  "NONBLOCKING",
436  "NONE",
437  "NOT",
438  "NO_WAIT",
439  "NO_WRITE_TO_BINLOG",
440  "NULL",
441  "NUMBER",
442  "NUMERIC",
443  "NVARCHAR",
444  "OFFSET",
445  "OLD_PASSWORD",
446  "ON",
447  "ONE",
448  "ONE_SHOT",
449  "ONLY",
450  "OPEN",
451  "OPTIMIZE",
452  "OPTIMIZER_COSTS",
453  "OPTION",
454  "OPTIONALLY",
455  "OPTIONS",
456  "OR",
457  "ORDER",
458  "OUT",
459  "OUTER",
460  "OUTFILE",
461  "OWNER",
462  "PACK_KEYS",
463  "PAGE",
464  "PARSER",
465  "PARSE_GCOL_EXPR",
466  "PARTIAL",
467  "PARTITION",
468  "PARTITIONING",
469  "PARTITIONS",
470  "PASSWORD",
471  "PHASE",
472  "PLUGIN",
473  "PLUGINS",
474  "PLUGIN_DIR",
475  "POINT",
476  "POLYGON",
477  "PORT",
478  "PRECEDES",
479  "PRECISION",
480  "PREPARE",
481  "PRESERVE",
482  "PREV",
483  "PRIMARY",
484  "PRIVILEGES",
485  "PROCEDURE",
486  "PROCESSLIST",
487  "PROFILE",
488  "PROFILES",
489  "PROXY",
490  "PURGE",
491  "QUARTER",
492  "QUERY",
493  "QUICK",
494  "RANGE",
495  "READ",
496  "READS",
497  "READ_ONLY",
498  "READ_WRITE",
499  "REAL",
500  "REBUILD",
501  "RECOVER",
502  "REDOFILE",
503  "REDO_BUFFER_SIZE",
504  "REDUNDANT",
505  "REFERENCES",
506  "REGEXP",
507  "RELAY",
508  "RELAYLOG",
509  "RELAY_LOG_FILE",
510  "RELAY_LOG_POS",
511  "RELAY_THREAD",
512  "RELEASE",
513  "RELOAD",
514  "REMOVE",
515  "RENAME",
516  "REORGANIZE",
517  "REPAIR",
518  "REPEAT",
519  "REPEATABLE",
520  "REPLACE",
521  "REPLICATE_DO_DB",
522  "REPLICATE_DO_TABLE",
523  "REPLICATE_IGNORE_DB",
524  "REPLICATE_IGNORE_TABLE",
525  "REPLICATE_REWRITE_DB",
526  "REPLICATE_WILD_DO_TABLE",
527  "REPLICATE_WILD_IGNORE_TABLE",
528  "REPLICATION",
529  "REQUIRE",
530  "RESET",
531  "RESIGNAL",
532  "RESTORE",
533  "RESTRICT",
534  "RESUME",
535  "RETURN",
536  "RETURNED_SQLSTATE",
537  "RETURNS",
538  "REVERSE",
539  "REVOKE",
540  "RIGHT",
541  "RLIKE",
542  "ROLLBACK",
543  "ROLLUP",
544  "ROTATE",
545  "ROUTINE",
546  "ROW",
547  "ROWS",
548  "ROW_COUNT",
549  "ROW_FORMAT",
550  "RTREE",
551  "SAVEPOINT",
552  "SCHEDULE",
553  "SCHEMA",
554  "SCHEMAS",
555  "SCHEMA_NAME",
556  "SECOND",
557  "SECOND_MICROSECOND",
558  "SECURITY",
559  "SELECT",
560  "SENSITIVE",
561  "SEPARATOR",
562  "SERIAL",
563  "SERIALIZABLE",
564  "SERVER",
565  "SESSION",
566  "SET",
567  "SHARE",
568  "SHOW",
569  "SHUTDOWN",
570  "SIGNAL",
571  "SIGNED",
572  "SIMPLE",
573  "SLAVE",
574  "SLOW",
575  "SMALLINT",
576  "SNAPSHOT",
577  "SOCKET",
578  "SOME",
579  "SONAME",
580  "SOUNDS",
581  "SOURCE",
582  "SPATIAL",
583  "SPECIFIC",
584  "SQL",
585  "SQLEXCEPTION",
586  "SQLSTATE",
587  "SQLWARNING",
588  "SQL_AFTER_GTIDS",
589  "SQL_AFTER_MTS_GAPS",
590  "SQL_BEFORE_GTIDS",
591  "SQL_BIG_RESULT",
592  "SQL_BUFFER_RESULT",
593  "SQL_CACHE",
594  "SQL_CALC_FOUND_ROWS",
595  "SQL_NO_CACHE",
596  "SQL_SMALL_RESULT",
597  "SQL_THREAD",
598  "SQL_TSI_DAY",
599  "SQL_TSI_HOUR",
600  "SQL_TSI_MINUTE",
601  "SQL_TSI_MONTH",
602  "SQL_TSI_QUARTER",
603  "SQL_TSI_SECOND",
604  "SQL_TSI_WEEK",
605  "SQL_TSI_YEAR",
606  "SSL",
607  "STACKED",
608  "START",
609  "STARTING",
610  "STARTS",
611  "STATS_AUTO_RECALC",
612  "STATS_PERSISTENT",
613  "STATS_SAMPLE_PAGES",
614  "STATUS",
615  "STOP",
616  "STORAGE",
617  "STORED",
618  "STRAIGHT_JOIN",
619  "STRING",
620  "SUBCLASS_ORIGIN",
621  "SUBJECT",
622  "SUBPARTITION",
623  "SUBPARTITIONS",
624  "SUPER",
625  "SUSPEND",
626  "SWAPS",
627  "SWITCHES",
628  "TABLE",
629  "TABLES",
630  "TABLESPACE",
631  "TABLE_CHECKSUM",
632  "TABLE_NAME",
633  "TEMPORARY",
634  "TEMPTABLE",
635  "TERMINATED",
636  "TEXT",
637  "THAN",
638  "THEN",
639  "TIME",
640  "TIMESTAMP",
641  "TIMESTAMPADD",
642  "TIMESTAMPDIFF",
643  "TINYBLOB",
644  "TINYINT",
645  "TINYTEXT",
646  "TO",
647  "TRAILING",
648  "TRANSACTION",
649  "TRIGGER",
650  "TRIGGERS",
651  "TRUE",
652  "TRUNCATE",
653  "TYPE",
654  "TYPES",
655  "UNCOMMITTED",
656  "UNDEFINED",
657  "UNDO",
658  "UNDOFILE",
659  "UNDO_BUFFER_SIZE",
660  "UNICODE",
661  "UNINSTALL",
662  "UNION",
663  "UNIQUE",
664  "UNKNOWN",
665  "UNLOCK",
666  "UNSIGNED",
667  "UNTIL",
668  "UPDATE",
669  "UPGRADE",
670  "USAGE",
671  "USE",
672  "USER",
673  "USER_RESOURCES",
674  "USE_FRM",
675  "USING",
676  "UTC_DATE",
677  "UTC_TIME",
678  "UTC_TIMESTAMP",
679  "VALIDATION",
680  "VALUE",
681  "VALUES",
682  "VARBINARY",
683  "VARCHAR",
684  "VARCHARACTER",
685  "VARIABLES",
686  "VARYING",
687  "VIEW",
688  "VIRTUAL",
689  "WAIT",
690  "WARNINGS",
691  "WEEK",
692  "WEIGHT_STRING",
693  "WHEN",
694  "WHERE",
695  "WHILE",
696  "WITH",
697  "WITHOUT",
698  "WORK",
699  "WRAPPER",
700  "WRITE",
701  "X509",
702  "XA",
703  "XID",
704  "XML",
705  "XOR",
706  "YEAR",
707  "YEAR_MONTH",
708  "ZEROFILL",
709  );
713  protected $reserved_postgres = array(
714  "ALL",
715  "ANALYSE",
716  "ANALYZE",
717  "AND",
718  "ANY",
719  "ARRAY",
720  "AS",
721  "ASC",
722  "ASYMMETRIC",
723  "AUTHORIZATION",
724  "BETWEEN",
725  "BINARY",
726  "BOTH",
727  "CASE",
728  "CAST",
729  "CHECK",
730  "COLLATE",
731  "COLUMN",
732  "CONSTRAINT",
733  "CREATE",
734  "CROSS",
735  "CURRENT_DATE",
736  "CURRENT_ROLE",
737  "CURRENT_TIME",
738  "CURRENT_TIMESTAMP",
739  "CURRENT_USER",
740  "DEFAULT",
741  "DEFERRABLE",
742  "DESC",
743  "DISTINCT",
744  "DO",
745  "ELSE",
746  "END",
747  "EXCEPT",
748  "FALSE",
749  "FOR",
750  "FOREIGN",
751  "FREEZE",
752  "FROM",
753  "FULL",
754  "GRANT",
755  "GROUP",
756  "HAVING",
757  "ILIKE",
758  "IN",
759  "INITIALLY",
760  "INNER",
761  "INTERSECT",
762  "INTO",
763  "IS",
764  "ISNULL",
765  "JOIN",
766  "LEADING",
767  "LEFT",
768  "LIKE",
769  "LIMIT",
770  "LOCALTIME",
771  "LOCALTIMESTAMP",
772  "NATURAL",
773  "NEW",
774  "NOT",
775  "NOTNULL",
776  "NULL",
777  "OFF",
778  "OFFSET",
779  "OLD",
780  "ON",
781  "ONLY",
782  "OR",
783  "ORDER",
784  "OUTER",
785  "OVERLAPS",
786  "PLACING",
787  "PRIMARY",
788  "REFERENCES",
789  "RETURNING",
790  "RIGHT",
791  "SELECT",
792  "SESSION_USER",
793  "SIMILAR",
794  "SOME",
795  "SYMMETRIC",
796  "TABLE",
797  "THEN",
798  "TO",
799  "TRAILING",
800  "TRUE",
801  "UNION",
802  "UNIQUE",
803  "USER",
804  "USING",
805  "VERBOSE",
806  "WHEN",
807  "WHERE",
808  "WITH",
809  );
813  protected $query_utils;
814 
815 
821  public function __construct(\ilDBInterface $ilDBInterface)
822  {
823  $this->db_instance = $ilDBInterface;
824  }
825 
826 
830  protected function getQueryUtils()
831  {
832  if (!$this->query_utils) {
833  $this->query_utils = new ilMySQLQueryUtils($this->db_instance);
834  }
835 
836  return $this->query_utils;
837  }
838 
839 
843  protected $valid_default_values = array(
844  'text' => '',
845  'boolean' => true,
846  'integer' => 0,
847  'decimal' => 0.0,
848  'float' => 0.0,
849  'timestamp' => '1970-01-01 00:00:00',
850  'time' => '00:00:00',
851  'date' => '1970-01-01',
852  'clob' => '',
853  'blob' => '',
854  );
855 
856 
862  public function checkTableName($table_name)
863  {
864  if (!preg_match(self::DEFINITION_TABLE_NAME, $table_name)) {
865  throw new ilDatabaseException('Table name must only contain _a-z0-9 and must start with a-z.');
866  }
867 
868  if ($this->isReserved($table_name)) {
869  throw new ilDatabaseException("Invalid table name '" . $table_name . "' (Reserved Word).");
870  }
871 
872  if (strtolower(substr($table_name, 0, 4)) == "sys_") {
873  throw new ilDatabaseException("Invalid table name '" . $table_name . "'. Name must not start with 'sys_'.");
874  }
875 
876  if (strlen($table_name) > 22) {
877  throw new ilDatabaseException("Invalid table name '" . $table_name . "'. Maximum table identifer length is 22 bytes.");
878  }
879 
880  return true;
881  }
882 
883 
888  public function isReserved($table_name)
889  {
890  return false;
891  }
892 
893 
897  public function getAllReserved()
898  {
899  return array_merge($this->getReservedMysql(), $this->getReservedPostgres());
900  }
901 
902 
906  public function getReservedMysql()
907  {
908  return $this->reserved_mysql;
909  }
910 
911 
916  {
917  $this->reserved_mysql = $reserved_mysql;
918  }
919 
920 
924  public function getReservedPostgres()
925  {
927  }
928 
929 
934  {
935  $this->reserved_postgres = $reserved_postgres;
936  }
937 
938 
944  public function checkColumnName($column_name)
945  {
946  if (!preg_match("/^[a-z]+[_a-z0-9]*$/", $column_name)) {
947  throw new ilDatabaseException("Invalid column name '" . $column_name
948  . "'. Column name must only contain _a-z0-9 and must start with a-z.");
949  }
950 
951  if ($this->isReserved($column_name)) {
952  throw new ilDatabaseException("Invalid column name '" . $column_name . "' (Reserved Word).");
953  }
954 
955  if (strtolower(substr($column_name, 0, 4)) == "sys_") {
956  throw new ilDatabaseException("Invalid column name '" . $column_name . "'. Name must not start with 'sys_'.");
957  }
958 
959  if (strlen($column_name) > 30) {
960  throw new ilDatabaseException("Invalid column name '" . $column_name . "'. Maximum column identifer length is 30 bytes.");
961  }
962 
963  return true;
964  }
965 
966 
972  public function checkIndexName($a_name)
973  {
974  if (!preg_match("/^[a-z]+[_a-z0-9]*$/", $a_name)) {
975  throw new ilDatabaseException("Invalid column name '" . $a_name . "'. Column name must only contain _a-z0-9 and must start with a-z.");
976  }
977 
978  if ($this->isReserved($a_name)) {
979  throw new ilDatabaseException("Invalid column name '" . $a_name . "' (Reserved Word).");
980  }
981 
982  if (strlen($a_name) > 3) {
983  throw new ilDatabaseException("Invalid index name '" . $a_name . "'. Maximum index identifer length is 3 bytes.");
984  }
985 
986  return true;
987  }
988 
989 
995  public function checkColumnDefinition($a_def)
996  {
997  // check valid type
998  if (!in_array($a_def["type"], $this->getAvailableTypes())) {
999  switch ($a_def["type"]) {
1000  case "boolean":
1001  throw new ilDatabaseException("Invalid column type '" . $a_def["type"] . "'. Use integer(1) instead.");
1002  break;
1003 
1004  case "decimal":
1005  throw new ilDatabaseException("Invalid column type '" . $a_def["type"] . "'. Use float or integer instead.");
1006  break;
1007 
1008  default:
1009  throw new ilDatabaseException("Invalid column type '" . $a_def["type"] . "'. Allowed types are: "
1010  . implode(', ', $this->getAvailableTypes()));
1011  }
1012  }
1013 
1014  // check used attributes
1016  foreach ($a_def as $k => $v) {
1017  if ($k != "type" && !in_array($k, $allowed_attributes[$a_def["type"]])) {
1018  throw new ilDatabaseException("Attribute '" . $k . "' is not allowed for column type '" . $a_def["type"] . "'.");
1019  }
1020  }
1021 
1022  // type specific checks
1023  $max_length = $this->getMaxLength();
1024  switch ($a_def["type"]) {
1025  case self::T_TEXT:
1026  if ($a_def["length"] < 1 || $a_def["length"] > $max_length[self::T_TEXT]) {
1027  if (isset($a_def["length"])) {
1028  throw new ilDatabaseException("Invalid length '" . $a_def["length"] . "' for type text." . " Length must be >=1 and <= "
1029  . $max_length[self::T_TEXT] . ".");
1030  }
1031  }
1032  break;
1033 
1034  case self::T_INTEGER:
1035  if (!in_array($a_def["length"], $max_length[self::T_INTEGER])) {
1036  if (isset($a_def["length"])) {
1037  throw new ilDatabaseException("Invalid length '" . $a_def["length"] . "' for type integer." . " Length must be "
1038  . implode(', ', $max_length[self::T_INTEGER]) . " (bytes).");
1039  }
1040  }
1041  if ($a_def["unsigned"]) {
1042  throw new ilDatabaseException("Unsigned attribut must not be true for type integer.");
1043  }
1044  break;
1045  }
1046 
1047  return true;
1048  }
1049 
1050 
1056  public function isAllowedAttribute($attribute, $type)
1057  {
1058  return in_array($attribute, $this->allowed_attributes[$type]);
1059  }
1060 
1061 
1065  public function getAvailableTypes()
1066  {
1067  return $this->available_types;
1068  }
1069 
1070 
1075  {
1076  $this->available_types = $available_types;
1077  }
1078 
1079 
1083  public function getAllowedAttributes()
1084  {
1086  }
1087 
1088 
1093  {
1094  $this->allowed_attributes = $allowed_attributes;
1095  }
1096 
1097 
1101  public function getMaxLength()
1102  {
1103  return $this->max_length;
1104  }
1105 
1106 
1110  public function setMaxLength($max_length)
1111  {
1112  $this->max_length = $max_length;
1113  }
1114 
1115 
1119  protected function getDBInstance()
1120  {
1121  return $this->db_instance;
1122  }
1123 
1124 
1128  public function getValidTypes()
1129  {
1130  $types = $this->valid_default_values;
1131  $db = $this->getDBInstance();
1132 
1133  if (!empty($db->options['datatype_map'])) {
1134  foreach ($db->options['datatype_map'] as $type => $mapped_type) {
1135  if (array_key_exists($mapped_type, $types)) {
1136  $types[$type] = $types[$mapped_type];
1137  } elseif (!empty($db->options['datatype_map_callback'][$type])) {
1138  $parameter = array( 'type' => $type, 'mapped_type' => $mapped_type );
1139  $default = call_user_func_array($db->options['datatype_map_callback'][$type], array( &$db, __FUNCTION__, $parameter ));
1140  $types[$type] = $default;
1141  }
1142  }
1143  }
1144 
1145  return $types;
1146  }
1147 
1148 
1154  protected function checkResultTypes($types)
1155  {
1156  $types = is_array($types) ? $types : array( $types );
1157  foreach ($types as $key => $type) {
1158  if (!isset($this->valid_default_values[$type])) {
1159  $db = $this->getDBInstance();
1160  if (empty($db->options['datatype_map'][$type])) {
1161  throw new ilDatabaseException($type . ' for ' . $key . ' is not a supported column type');
1162  }
1163  }
1164  }
1165 
1166  return $types;
1167  }
1168 
1169 
1177  protected function baseConvertResult($value, $type, $rtrim = true)
1178  {
1179  throw new ilDatabaseException("deprecated");
1180  switch ($type) {
1181  case 'text':
1182  if ($rtrim) {
1183  $value = rtrim($value);
1184  }
1185 
1186  return $value;
1187  case 'integer':
1188  return intval($value);
1189  case 'boolean':
1190  return !empty($value);
1191  case 'decimal':
1192  return $value;
1193  case 'float':
1194  return doubleval($value);
1195  case 'date':
1196  return $value;
1197  case 'time':
1198  return $value;
1199  case 'timestamp':
1200  return $value;
1201  case 'clob':
1202  case 'blob':
1203  $this->lobs[] = array(
1204  'buffer' => null,
1205  'position' => 0,
1206  'lob_index' => null,
1207  'endOfLOB' => false,
1208  'resource' => $value,
1209  'value' => null,
1210  'loaded' => false,
1211  );
1212  end($this->lobs);
1213  $lob_index = key($this->lobs);
1214  $this->lobs[$lob_index]['lob_index'] = $lob_index;
1215 
1216  return fopen('MDB2LOB://' . $lob_index . '@' . $this->db_index, 'r+');
1217  }
1218 
1219  throw new ilDatabaseException('attempt to convert result value to an unknown type :' . $type);
1220  }
1221 
1222 
1230  public function convertResult($value, $type, $rtrim = true)
1231  {
1232  throw new ilDatabaseException("deprecated");
1233  if (is_null($value)) {
1234  return null;
1235  }
1236  $db = $this->getDBInstance();
1237 
1238  if (!empty($db->options['datatype_map'][$type])) {
1239  $type = $db->options['datatype_map'][$type];
1240  if (!empty($db->options['datatype_map_callback'][$type])) {
1241  $parameter = array( 'type' => $type, 'value' => $value, 'rtrim' => $rtrim );
1242 
1243  return call_user_func_array($db->options['datatype_map_callback'][$type], array( &$db, __FUNCTION__, $parameter ));
1244  }
1245  }
1246 
1247  return $this->baseConvertResult($value, $type, $rtrim);
1248  }
1249 
1250 
1257  public function convertResultRow($types, $row, $rtrim = true)
1258  {
1259  throw new ilDatabaseException("deprecated");
1260  $types = $this->sortResultFieldTypes(array_keys($row), $types);
1261  foreach ($row as $key => $value) {
1262  if (empty($types[$key])) {
1263  continue;
1264  }
1265  $value = $this->convertResult($row[$key], $types[$key], $rtrim);
1266 
1267  $row[$key] = $value;
1268  }
1269 
1270  return $row;
1271  }
1272 
1273  // }}}
1274  // {{{ _sortResultFieldTypes()
1275 
1281  protected function sortResultFieldTypes($columns, $types)
1282  {
1283  $n_cols = count($columns);
1284  $n_types = count($types);
1285  if ($n_cols > $n_types) {
1286  for ($i = $n_cols - $n_types; $i >= 0; $i--) {
1287  $types[] = null;
1288  }
1289  }
1290  $sorted_types = array();
1291  foreach ($columns as $col) {
1292  $sorted_types[$col] = null;
1293  }
1294  foreach ($types as $name => $type) {
1295  if (array_key_exists($name, $sorted_types)) {
1296  $sorted_types[$name] = $type;
1297  unset($types[$name]);
1298  }
1299  }
1300  // if there are left types in the array, fill the null values of the
1301  // sorted array with them, in order.
1302  if (count($types)) {
1303  reset($types);
1304  foreach (array_keys($sorted_types) as $k) {
1305  if (is_null($sorted_types[$k])) {
1306  $sorted_types[$k] = current($types);
1307  next($types);
1308  }
1309  }
1310  }
1311 
1312  return $sorted_types;
1313  }
1314 
1315 
1323  public function getDeclaration($type, $name, $field)
1324  {
1325  $db = $this->getDBInstance();
1326 
1327  if (!empty($db->options['datatype_map'][$type])) {
1328  $type = $db->options['datatype_map'][$type];
1329  if (!empty($db->options['datatype_map_callback'][$type])) {
1330  $parameter = array( 'type' => $type, 'name' => $name, 'field' => $field );
1331 
1332  return call_user_func_array($db->options['datatype_map_callback'][$type], array( &$db, __FUNCTION__, $parameter ));
1333  }
1334  $field['type'] = $type;
1335  }
1336 
1337  if (!method_exists($this, "get{$type}Declaration")) {
1338  throw new ilDatabaseException('type not defined: ' . $type);
1339  }
1340 
1341  return $this->{"get{$type}Declaration"}($name, $field);
1342  }
1343 
1344 
1349  public function getTypeDeclaration($field)
1350  {
1351  $db = $this->getDBInstance();
1352 
1353  switch ($field['type']) {
1354  case 'text':
1355  $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length'];
1356  $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
1357 
1358  return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(' . $db->options['default_text_field_length']
1359  . ')') : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
1360  case 'clob':
1361  return 'TEXT';
1362  case 'blob':
1363  return 'TEXT';
1364  case 'integer':
1365  return 'INT';
1366  case 'boolean':
1367  return 'INT';
1368  case 'date':
1369  return 'CHAR (' . strlen('YYYY-MM-DD') . ')';
1370  case 'time':
1371  return 'CHAR (' . strlen('HH:MM:SS') . ')';
1372  case 'timestamp':
1373  return 'CHAR (' . strlen('YYYY-MM-DD HH:MM:SS') . ')';
1374  case 'float':
1375  return 'TEXT';
1376  case 'decimal':
1377  return 'TEXT';
1378  }
1379 
1380  return '';
1381  }
1382 
1383 
1389  protected function getInternalDeclaration($name, $field)
1390  {
1391  $db = $this->getDBInstance();
1392 
1393  $name = $db->quoteIdentifier($name, true);
1394  $declaration_options = $db->getFieldDefinition()->getDeclarationOptions($field);
1395 
1396  return $name . ' ' . $this->getTypeDeclaration($field) . $declaration_options;
1397  }
1398 
1399 
1405  protected function getDeclarationOptions($field)
1406  {
1407  $charset = empty($field['charset']) ? '' : ' ' . $this->getCharsetFieldDeclaration($field['charset']);
1408 
1409  $default = '';
1410  if (array_key_exists('default', $field)) {
1411  if ($field['default'] === '') {
1412  $db = $this->getDBInstance();
1413 
1414  if (empty($field['notnull'])) {
1415  $field['default'] = null;
1416  } else {
1418  $field['default'] = $valid_default_values[$field['type']];
1419  }
1420  if ($field['default'] === ''
1421  && ($db->options['portability'] & 32)
1422  ) {
1423  $field['default'] = ' ';
1424  }
1425  }
1426  $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']);
1427  } elseif (empty($field['notnull'])) {
1428  $default = ' DEFAULT NULL';
1429  }
1430 
1431  $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
1432  // alex patch 28 Nov 2011 start
1433  if ($field['notnull'] === false) {
1434  $notnull = " NULL";
1435  }
1436  // alex patch 28 Nov 2011 end
1437 
1438  $collation = empty($field['collation']) ? '' : ' ' . $this->getCollationFieldDeclaration($field['collation']);
1439 
1440  return $charset . $default . $notnull . $collation;
1441  }
1442 
1443 
1448  protected function getCharsetFieldDeclaration($charset)
1449  {
1450  return '';
1451  }
1452 
1453 
1458  protected function getCollationFieldDeclaration($collation)
1459  {
1460  return '';
1461  }
1462 
1463 
1470  protected function getIntegerDeclaration($name, $field)
1471  {
1472  if (!empty($field['unsigned'])) {
1473  $db = $this->getDBInstance();
1474 
1475  $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
1476  }
1477 
1478  return $this->getInternalDeclaration($name, $field);
1479  }
1480 
1481 
1488  protected function getTextDeclaration($name, $field)
1489  {
1490  return $this->getInternalDeclaration($name, $field);
1491  }
1492 
1493 
1499  protected function getCLOBDeclaration($name, $field)
1500  {
1501  $db = $this->getDBInstance();
1502 
1503  $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
1504  $name = $db->quoteIdentifier($name, true);
1505 
1506  return $name . ' ' . $this->getTypeDeclaration($field) . $notnull;
1507  }
1508 
1509 
1515  protected function getBLOBDeclaration($name, $field)
1516  {
1517  $db = $this->getDBInstance();
1518 
1519  $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
1520  $name = $db->quoteIdentifier($name, true);
1521 
1522  return $name . ' ' . $this->getTypeDeclaration($field) . $notnull;
1523  }
1524 
1525 
1531  protected function getBooleanDeclaration($name, $field)
1532  {
1533  return $this->getInternalDeclaration($name, $field);
1534  }
1535 
1536 
1542  protected function getDateDeclaration($name, $field)
1543  {
1544  return $this->getInternalDeclaration($name, $field);
1545  }
1546 
1547 
1553  protected function getTimestampDeclaration($name, $field)
1554  {
1555  return $this->getInternalDeclaration($name, $field);
1556  }
1557 
1558 
1564  protected function getTimeDeclaration($name, $field)
1565  {
1566  return $this->getInternalDeclaration($name, $field);
1567  }
1568 
1569 
1575  protected function getFloatDeclaration($name, $field)
1576  {
1577  return $this->getInternalDeclaration($name, $field);
1578  }
1579 
1580 
1586  protected function getDecimalDeclaration($name, $field)
1587  {
1588  return $this->getInternalDeclaration($name, $field);
1589  }
1590 
1591 
1598  public function compareDefinition($current, $previous)
1599  {
1600  $type = !empty($current['type']) ? $current['type'] : null;
1601 
1602  if (!method_exists($this, "compare{$type}Definition")) {
1603  $db = $this->getDBInstance();
1604 
1605  if (!empty($db->options['datatype_map_callback'][$type])) {
1606  $parameter = array( 'current' => $current, 'previous' => $previous );
1607  $change = call_user_func_array($db->options['datatype_map_callback'][$type], array( &$db, __FUNCTION__, $parameter ));
1608 
1609  return $change;
1610  }
1611 
1612  throw new ilDatabaseException('type "' . $current['type'] . '" is not yet supported');
1613  }
1614 
1615  if (empty($previous['type']) || $previous['type'] != $type) {
1616  return $current;
1617  }
1618 
1619  $change = $this->{"compare{$type}Definition"}($current, $previous);
1620 
1621  if ($previous['type'] != $type) {
1622  $change['type'] = true;
1623  }
1624 
1625  $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
1626  $notnull = !empty($current['notnull']) ? $current['notnull'] : false;
1627  if ($previous_notnull != $notnull) {
1628  $change['notnull'] = true;
1629  }
1630 
1631  $previous_default = array_key_exists('default', $previous) ? $previous['default'] : ($previous_notnull ? '' : null);
1632  $default = array_key_exists('default', $current) ? $current['default'] : ($notnull ? '' : null);
1633  if ($previous_default !== $default) {
1634  $change['default'] = true;
1635  }
1636 
1637  return $change;
1638  }
1639 
1640 
1646  protected function compareIntegerDefinition($current, $previous)
1647  {
1648  $change = array();
1649  $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false;
1650  $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false;
1651  if ($previous_unsigned != $unsigned) {
1652  $change['unsigned'] = true;
1653  }
1654  $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false;
1655  $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false;
1656  if ($previous_autoincrement != $autoincrement) {
1657  $change['autoincrement'] = true;
1658  }
1659 
1660  return $change;
1661  }
1662 
1663 
1669  protected function compareTextDefinition($current, $previous)
1670  {
1671  $change = array();
1672  $previous_length = !empty($previous['length']) ? $previous['length'] : 0;
1673  $length = !empty($current['length']) ? $current['length'] : 0;
1674  if ($previous_length != $length) {
1675  $change['length'] = true;
1676  }
1677  $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0;
1678  $fixed = !empty($current['fixed']) ? $current['fixed'] : 0;
1679  if ($previous_fixed != $fixed) {
1680  $change['fixed'] = true;
1681  }
1682 
1683  return $change;
1684  }
1685 
1686 
1692  protected function compareCLOBDefinition($current, $previous)
1693  {
1694  return $this->compareTextDefinition($current, $previous);
1695  }
1696 
1697 
1703  protected function compareBLOBDefinition($current, $previous)
1704  {
1705  return $this->compareTextDefinition($current, $previous);
1706  }
1707 
1708 
1714  protected function compareDateDefinition($current, $previous)
1715  {
1716  return array();
1717  }
1718 
1719 
1725  protected function compareTimeDefinition($current, $previous)
1726  {
1727  return array();
1728  }
1729 
1730 
1736  protected function compareTimestampDefinition($current, $previous)
1737  {
1738  return array();
1739  }
1740 
1741 
1747  protected function compareBooleanDefinition($current, $previous)
1748  {
1749  return array();
1750  }
1751 
1752 
1758  protected function compareFloatDefinition($current, $previous)
1759  {
1760  return array();
1761  }
1762 
1763 
1769  protected function compareDecimalDefinition($current, $previous)
1770  {
1771  return array();
1772  }
1773 
1774 
1783  public function quote($value, $type = null, $quote = true, $escape_wildcards = false)
1784  {
1785  $db = $this->getDBInstance();
1786 
1787  return $db->quote($value, $type);
1788 
1789  if (is_null($value)
1790  || ($value === '' && $db->options['portability'])
1791  ) {
1792  if (!$quote) {
1793  return null;
1794  }
1795 
1796  return 'NULL';
1797  }
1798 
1799  if (is_null($type)) {
1800  switch (gettype($value)) {
1801  case 'integer':
1802  $type = 'integer';
1803  break;
1804  case 'double':
1805  // todo: default to decimal as float is quite unusual
1806  // $type = 'float';
1807  $type = 'decimal';
1808  break;
1809  case 'boolean':
1810  $type = 'boolean';
1811  break;
1812  case 'array':
1813  $value = serialize($value);
1814  // no break
1815  case 'object':
1816  $type = 'text';
1817  break;
1818  default:
1819  if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) {
1820  $type = 'timestamp';
1821  } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) {
1822  $type = 'time';
1823  } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
1824  $type = 'date';
1825  } else {
1826  $type = 'text';
1827  }
1828  break;
1829  }
1830  } elseif (!empty($db->options['datatype_map'][$type])) {
1831  $type = $db->options['datatype_map'][$type];
1832  if (!empty($db->options['datatype_map_callback'][$type])) {
1833  $parameter = array( 'type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards );
1834 
1835  return call_user_func_array($db->options['datatype_map_callback'][$type], array( &$db, __FUNCTION__, $parameter ));
1836  }
1837  }
1838 
1839  if (!method_exists($this, "quote{$type}")) {
1840  throw new ilDatabaseException('type not defined: ' . $type);
1841  }
1842  $value = $this->{"quote{$type}"}($value, $quote, $escape_wildcards);
1843  if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
1844  && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern']
1845  ) {
1846  $value .= $this->patternEscapeString();
1847  }
1848 
1849  return $value;
1850  }
1851 
1852 
1859  protected function quoteInteger($value, $quote, $escape_wildcards)
1860  {
1861  return (int) $value;
1862  }
1863 
1864 
1871  protected function quoteText($value, $quote, $escape_wildcards)
1872  {
1873  if (!$quote) {
1874  return $value;
1875  }
1876 
1877  $db = $this->getDBInstance();
1878 
1879  $value = $db->escape($value, $escape_wildcards);
1880 
1881  return "'" . $value . "'";
1882  }
1883 
1884 
1889  protected function readFile($value)
1890  {
1891  $close = false;
1892  if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
1893  $close = true;
1894  if ($match[1] == 'file://') {
1895  $value = $match[2];
1896  }
1897  // do not try to open urls
1898  #$value = @fopen($value, 'r');
1899  }
1900 
1901  if (is_resource($value)) {
1902  $db = $this->getDBInstance();
1903 
1904  $fp = $value;
1905  $value = '';
1906  while (!@feof($fp)) {
1907  $value .= @fread($fp, $db->options['lob_buffer_length']);
1908  }
1909  if ($close) {
1910  @fclose($fp);
1911  }
1912  }
1913 
1914  return $value;
1915  }
1916 
1917 
1924  protected function quoteLOB($value, $quote, $escape_wildcards)
1925  {
1926  $value = $this->readFile($value);
1927 
1928  return $this->quoteText($value, $quote, $escape_wildcards);
1929  }
1930 
1931 
1938  protected function quoteCLOB($value, $quote, $escape_wildcards)
1939  {
1940  return $this->quoteLOB($value, $quote, $escape_wildcards);
1941  }
1942 
1943 
1950  protected function quoteBLOB($value, $quote, $escape_wildcards)
1951  {
1952  return $this->quoteLOB($value, $quote, $escape_wildcards);
1953  }
1954 
1955 
1962  protected function quoteBoolean($value, $quote, $escape_wildcards)
1963  {
1964  return ($value ? 1 : 0);
1965  }
1966 
1967 
1974  protected function quoteDate($value, $quote, $escape_wildcards)
1975  {
1976  if ($value === 'CURRENT_DATE') {
1977  $db = $this->getDBInstance();
1978 
1979  return 'CURRENT_DATE';
1980  }
1981 
1982  return $this->quoteText($value, $quote, $escape_wildcards);
1983  }
1984 
1985 
1992  protected function quoteTimestamp($value, $quote, $escape_wildcards)
1993  {
1994  throw new ilDatabaseException("deprecated");
1995  if ($value === 'CURRENT_TIMESTAMP') {
1996  $db = $this->getDBInstance();
1997 
1998  if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
1999  return $db->function->now('timestamp');
2000  }
2001 
2002  return 'CURRENT_TIMESTAMP';
2003  }
2004 
2005  return $this->quoteText($value, $quote, $escape_wildcards);
2006  }
2007 
2008 
2015  protected function quoteTime($value, $quote, $escape_wildcards)
2016  {
2017  throw new ilDatabaseException("deprecated");
2018  if ($value === 'CURRENT_TIME') {
2019  $db = $this->getDBInstance();
2020 
2021  if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
2022  return $db->function->now('time');
2023  }
2024 
2025  return 'CURRENT_TIME';
2026  }
2027 
2028  return $this->quoteText($value, $quote, $escape_wildcards);
2029  }
2030 
2031 
2038  protected function quoteFloat($value, $quote, $escape_wildcards)
2039  {
2040  if (preg_match('/^(.*)e([-+])(\d+)$/i', $value, $matches)) {
2041  $decimal = $this->quoteDecimal($matches[1], $quote, $escape_wildcards);
2042  $sign = $matches[2];
2043  $exponent = str_pad($matches[3], 2, '0', STR_PAD_LEFT);
2044  $value = $decimal . 'E' . $sign . $exponent;
2045  } else {
2046  $value = $this->quoteDecimal($value, $quote, $escape_wildcards);
2047  }
2048 
2049  return $value;
2050  }
2051 
2052 
2059  protected function quoteDecimal($value, $quote, $escape_wildcards)
2060  {
2061  $value = (string) $value;
2062  $value = preg_replace('/[^\d\.,\-+eE]/', '', $value);
2063  if (preg_match('/[^.0-9]/', $value)) {
2064  if (strpos($value, ',')) {
2065  // 1000,00
2066  if (!strpos($value, '.')) {
2067  // convert the last "," to a "."
2068  $value = strrev(str_replace(',', '.', strrev($value)));
2069  // 1.000,00
2070  } elseif (strpos($value, '.') && strpos($value, '.') < strpos($value, ',')) {
2071  $value = str_replace('.', '', $value);
2072  // convert the last "," to a "."
2073  $value = strrev(str_replace(',', '.', strrev($value)));
2074  // 1,000.00
2075  } else {
2076  $value = str_replace(',', '', $value);
2077  }
2078  }
2079  }
2080 
2081  return $value;
2082  }
2083 
2084 
2091  public function writeLOBToFile($lob, $file)
2092  {
2093  $db = $this->getDBInstance();
2094 
2095  if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) {
2096  if ($match[1] == 'file://') {
2097  $file = $match[2];
2098  }
2099  }
2100 
2101  $fp = @fopen($file, 'wb');
2102  while (!@feof($lob)) {
2103  $result = @fread($lob, $db->options['lob_buffer_length']);
2104  $read = strlen($result);
2105  if (@fwrite($fp, $result, $read) != $read) {
2106  @fclose($fp);
2107 
2108  throw new ilDatabaseException('could not write to the output file');
2109  }
2110  }
2111  @fclose($fp);
2112 
2113  return true;
2114  }
2115 
2116 
2121  protected function retrieveLOB(&$lob)
2122  {
2123  if (is_null($lob['value'])) {
2124  $lob['value'] = $lob['resource'];
2125  }
2126  $lob['loaded'] = true;
2127 
2128  return true;
2129  }
2130 
2131 
2137  protected function readLOB($lob, $length)
2138  {
2139  return substr($lob['value'], $lob['position'], $length);
2140  }
2141 
2142 
2147  protected function endOfLOB($lob)
2148  {
2149  return $lob['endOfLOB'];
2150  }
2151 
2152 
2157  public function destroyLOB($lob)
2158  {
2159  $lob_data = stream_get_meta_data($lob);
2160  $lob_index = $lob_data['wrapper_data']->lob_index;
2161  fclose($lob);
2162  if (isset($this->lobs[$lob_index])) {
2163  $this->destroyLOBInternal($this->lobs[$lob_index]);
2164  unset($this->lobs[$lob_index]);
2165  }
2166 
2167  return true;
2168  }
2169 
2170 
2175  protected function destroyLOBInternal(&$lob)
2176  {
2177  return true;
2178  }
2179 
2180 
2187  public function implodeArray($array, $type = false)
2188  {
2189  if (!is_array($array) || empty($array)) {
2190  return 'NULL';
2191  }
2192  if ($type) {
2193  foreach ($array as $value) {
2194  $return[] = $this->quote($value, $type);
2195  }
2196  } else {
2197  $return = $array;
2198  }
2199 
2200  return implode(', ', $return);
2201  }
2202 
2203 
2211  public function matchPattern($pattern, $operator = null, $field = null)
2212  {
2213  $db = $this->getDBInstance();
2214 
2215  $match = '';
2216  if (!is_null($operator)) {
2217  $operator = strtoupper($operator);
2218  switch ($operator) {
2219  // case insensitive
2220  case 'ILIKE':
2221  if (is_null($field)) {
2222  throw new ilDatabaseException('case insensitive LIKE matching requires passing the field name');
2223  }
2224  $db->loadModule('Function', null, true);
2225  $match = $db->function->lower($field) . ' LIKE ';
2226  break;
2227  // case sensitive
2228  case 'LIKE':
2229  $match = is_null($field) ? 'LIKE ' : $field . ' LIKE ';
2230  break;
2231  default:
2232  throw new ilDatabaseException('not a supported operator type:' . $operator);
2233  }
2234  }
2235  $match .= "'";
2236  foreach ($pattern as $key => $value) {
2237  if ($key % 2) {
2238  $match .= $value;
2239  } else {
2240  if ($operator === 'ILIKE') {
2241  $value = strtolower($value);
2242  }
2243  $escaped = $db->escape($value);
2244  $match .= $db->escapePattern($escaped);
2245  }
2246  }
2247  $match .= "'";
2248  $match .= $this->patternEscapeString();
2249 
2250  return $match;
2251  }
2252 
2253 
2257  public function patternEscapeString()
2258  {
2259  return '';
2260  }
2261 
2262 
2267  public function mapNativeDatatype($field)
2268  {
2269  $db = $this->getDBInstance();
2270  $db_type = strtok($field['type'], '(), ');
2271  if (!empty($db->options['nativetype_map_callback'][$db_type])) {
2272  return call_user_func_array($db->options['nativetype_map_callback'][$db_type], array( $db, $field ));
2273  }
2274 
2275  return $this->mapNativeDatatypeInternal($field);
2276  }
2277 
2278 
2284  abstract protected function mapNativeDatatypeInternal($field);
2285 
2286 
2291  public function mapPrepareDatatype($type)
2292  {
2293  $db = $this->getDBInstance();
2294 
2295  if (!empty($db->options['datatype_map'][$type])) {
2296  $type = $db->options['datatype_map'][$type];
2297  if (!empty($db->options['datatype_map_callback'][$type])) {
2298  $parameter = array( 'type' => $type );
2299 
2300  return call_user_func_array($db->options['datatype_map_callback'][$type], array( &$db, __FUNCTION__, $parameter ));
2301  }
2302  }
2303 
2304  return $type;
2305  }
2306 }
compareCLOBDefinition($current, $previous)
compareTimestampDefinition($current, $previous)
quoteDate($value, $quote, $escape_wildcards)
quote($value, $type=null, $quote=true, $escape_wildcards=false)
$result
$type
baseConvertResult($value, $type, $rtrim=true)
quoteLOB($value, $quote, $escape_wildcards)
quoteInteger($value, $quote, $escape_wildcards)
quoteTimestamp($value, $quote, $escape_wildcards)
compareBLOBDefinition($current, $previous)
Class ilDBPdoFieldDefinition.
quoteDecimal($value, $quote, $escape_wildcards)
compareBooleanDefinition($current, $previous)
compareFloatDefinition($current, $previous)
Class ilDatabaseException.
compareDateDefinition($current, $previous)
compareTextDefinition($current, $previous)
quoteFloat($value, $quote, $escape_wildcards)
matchPattern($pattern, $operator=null, $field=null)
quoteCLOB($value, $quote, $escape_wildcards)
$default
Definition: build.php:20
$row
quoteBoolean($value, $quote, $escape_wildcards)
quoteText($value, $quote, $escape_wildcards)
Class ilMySQLQueryUtils.
$i
Definition: disco.tpl.php:19
quoteBLOB($value, $quote, $escape_wildcards)
compareIntegerDefinition($current, $previous)
quoteTime($value, $quote, $escape_wildcards)
__construct(\ilDBInterface $ilDBInterface)
ilDBPdoFieldDefinition constructor.
if(! $in) $columns
Definition: Utf8Test.php:45
$key
Definition: croninfo.php:18
convertResultRow($types, $row, $rtrim=true)
compareTimeDefinition($current, $previous)
mapNativeDatatypeInternal($field)
convertResult($value, $type, $rtrim=true)
compareDecimalDefinition($current, $previous)