ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilDBPdoFieldDefinition.php
Go to the documentation of this file.
1<?php
2
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;
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 {
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 {
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 {
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}
$result
if(! $in) $columns
Definition: Utf8Test.php:45
$default
Definition: build.php:20
An exception for terminatinating execution or to throw for unit testing.
Class ilDBPdoFieldDefinition.
quoteText($value, $quote, $escape_wildcards)
quoteFloat($value, $quote, $escape_wildcards)
compareIntegerDefinition($current, $previous)
quoteDecimal($value, $quote, $escape_wildcards)
quoteTime($value, $quote, $escape_wildcards)
compareDecimalDefinition($current, $previous)
compareBLOBDefinition($current, $previous)
compareCLOBDefinition($current, $previous)
__construct(\ilDBInterface $ilDBInterface)
ilDBPdoFieldDefinition constructor.
quote($value, $type=null, $quote=true, $escape_wildcards=false)
compareTextDefinition($current, $previous)
quoteBLOB($value, $quote, $escape_wildcards)
compareFloatDefinition($current, $previous)
quoteBoolean($value, $quote, $escape_wildcards)
compareTimestampDefinition($current, $previous)
convertResult($value, $type, $rtrim=true)
quoteLOB($value, $quote, $escape_wildcards)
compareDateDefinition($current, $previous)
mapNativeDatatypeInternal($field)
matchPattern($pattern, $operator=null, $field=null)
convertResultRow($types, $row, $rtrim=true)
quoteInteger($value, $quote, $escape_wildcards)
quoteTimestamp($value, $quote, $escape_wildcards)
baseConvertResult($value, $type, $rtrim=true)
quoteDate($value, $quote, $escape_wildcards)
compareBooleanDefinition($current, $previous)
compareTimeDefinition($current, $previous)
quoteCLOB($value, $quote, $escape_wildcards)
Class ilDatabaseException.
Class ilMySQLQueryUtils.
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
Interface ilDBInterface.
$row
$type