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' ),
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" ),
64 self::T_INTEGER => array( 1, 2, 3, 4, 8 ),
164 "CONSTRAINT_CATALOG",
278 "GEOMETRYCOLLECTION",
367 "MASTER_AUTO_POSITION",
369 "MASTER_CONNECT_RETRY",
371 "MASTER_HEARTBEAT_PERIOD",
377 "MASTER_RETRY_COUNT",
385 "MASTER_SSL_CRLPATH",
387 "MASTER_SSL_VERIFY_SERVER_CERT",
388 "MASTER_TLS_VERSION",
392 "MAX_CONNECTIONS_PER_HOUR",
393 "MAX_QUERIES_PER_HOUR",
396 "MAX_STATEMENT_TIME",
397 "MAX_UPDATES_PER_HOUR",
398 "MAX_USER_CONNECTIONS",
410 "MINUTE_MICROSECOND",
439 "NO_WRITE_TO_BINLOG",
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",
557 "SECOND_MICROSECOND",
589 "SQL_AFTER_MTS_GAPS",
594 "SQL_CALC_FOUND_ROWS",
613 "STATS_SAMPLE_PAGES",
823 $this->db_instance = $ilDBInterface;
832 if (!$this->query_utils) {
849 'timestamp' =>
'1970-01-01 00:00:00',
850 'time' =>
'00:00:00',
851 'date' =>
'1970-01-01',
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.');
869 throw new ilDatabaseException(
"Invalid table name '" . $table_name .
"' (Reserved Word).");
872 if (strtolower(substr($table_name, 0, 4)) ==
"sys_") {
873 throw new ilDatabaseException(
"Invalid table name '" . $table_name .
"'. Name must not start with 'sys_'.");
876 if (strlen($table_name) > 22) {
877 throw new ilDatabaseException(
"Invalid table name '" . $table_name .
"'. Maximum table identifer length is 22 bytes.");
946 if (!preg_match(
"/^[a-z]+[_a-z0-9]*$/", $column_name)) {
948 .
"'. Column name must only contain _a-z0-9 and must start with a-z.");
952 throw new ilDatabaseException(
"Invalid column name '" . $column_name .
"' (Reserved Word).");
955 if (strtolower(substr($column_name, 0, 4)) ==
"sys_") {
956 throw new ilDatabaseException(
"Invalid column name '" . $column_name .
"'. Name must not start with 'sys_'.");
959 if (strlen($column_name) > 30) {
960 throw new ilDatabaseException(
"Invalid column name '" . $column_name .
"'. Maximum column identifer length is 30 bytes.");
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.");
982 if (strlen($a_name) > 3) {
983 throw new ilDatabaseException(
"Invalid index name '" . $a_name .
"'. Maximum index identifer length is 3 bytes.");
999 switch ($a_def[
"type"]) {
1001 throw new ilDatabaseException(
"Invalid column type '" . $a_def[
"type"] .
"'. Use integer(1) instead.");
1005 throw new ilDatabaseException(
"Invalid column type '" . $a_def[
"type"] .
"'. Use float or integer instead.");
1009 throw new ilDatabaseException(
"Invalid column type '" . $a_def[
"type"] .
"'. Allowed types are: " 1016 foreach ($a_def as $k => $v) {
1018 throw new ilDatabaseException(
"Attribute '" . $k .
"' is not allowed for column type '" . $a_def[
"type"] .
"'.");
1024 switch ($a_def[
"type"]) {
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 <= " 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).");
1041 if ($a_def[
"unsigned"]) {
1058 return in_array($attribute, $this->allowed_attributes[
$type]);
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 ));
1156 $types = is_array($types) ? $types : array( $types );
1158 if (!isset($this->valid_default_values[
$type])) {
1160 if (empty($db->options[
'datatype_map'][$type])) {
1183 $value = rtrim($value);
1188 return intval($value);
1190 return !empty($value);
1194 return doubleval($value);
1203 $this->lobs[] = array(
1206 'lob_index' => null,
1207 'endOfLOB' =>
false,
1208 'resource' => $value,
1213 $lob_index = key($this->lobs);
1214 $this->lobs[$lob_index][
'lob_index'] = $lob_index;
1216 return fopen(
'MDB2LOB://' . $lob_index .
'@' . $this->db_index,
'r+');
1233 if (is_null($value)) {
1238 if (!empty($db->options[
'datatype_map'][
$type])) {
1240 if (!empty($db->options[
'datatype_map_callback'][
$type])) {
1241 $parameter = array(
'type' =>
$type,
'value' => $value,
'rtrim' => $rtrim );
1243 return call_user_func_array($db->options[
'datatype_map_callback'][
$type], array( &$db, __FUNCTION__, $parameter ));
1262 if (empty($types[
$key])) {
1284 $n_types = count($types);
1285 if ($n_cols > $n_types) {
1286 for (
$i = $n_cols - $n_types;
$i >= 0;
$i--) {
1290 $sorted_types = array();
1292 $sorted_types[$col] = null;
1295 if (array_key_exists(
$name, $sorted_types)) {
1297 unset($types[
$name]);
1302 if (count($types)) {
1304 foreach (array_keys($sorted_types) as $k) {
1305 if (is_null($sorted_types[$k])) {
1306 $sorted_types[$k] = current($types);
1312 return $sorted_types;
1327 if (!empty($db->options[
'datatype_map'][
$type])) {
1329 if (!empty($db->options[
'datatype_map_callback'][
$type])) {
1330 $parameter = array(
'type' =>
$type,
'name' =>
$name,
'field' => $field );
1332 return call_user_func_array($db->options[
'datatype_map_callback'][
$type], array( &$db, __FUNCTION__, $parameter ));
1334 $field[
'type'] =
$type;
1337 if (!method_exists($this,
"get{$type}Declaration")) {
1341 return $this->{
"get{$type}Declaration"}(
$name, $field);
1353 switch ($field[
'type']) {
1355 $length = !empty($field[
'length']) ? $field[
'length'] : $db->options[
'default_text_field_length'];
1356 $fixed = !empty($field[
'fixed']) ? $field[
'fixed'] :
false;
1358 return $fixed ? ($length ?
'CHAR(' . $length .
')' :
'CHAR(' . $db->options[
'default_text_field_length']
1359 .
')') : ($length ?
'VARCHAR(' . $length .
')' :
'TEXT');
1369 return 'CHAR (' . strlen(
'YYYY-MM-DD') .
')';
1371 return 'CHAR (' . strlen(
'HH:MM:SS') .
')';
1373 return 'CHAR (' . strlen(
'YYYY-MM-DD HH:MM:SS') .
')';
1394 $declaration_options = $db->getFieldDefinition()->getDeclarationOptions($field);
1410 if (array_key_exists(
'default', $field)) {
1411 if ($field[
'default'] ===
'') {
1414 if (empty($field[
'notnull'])) {
1415 $field[
'default'] = null;
1420 if ($field[
'default'] ===
'' 1421 && ($db->options[
'portability'] & 32)
1423 $field[
'default'] =
' ';
1426 $default =
' DEFAULT ' . $this->
quote($field[
'default'], $field[
'type']);
1427 } elseif (empty($field[
'notnull'])) {
1431 $notnull = empty($field[
'notnull']) ?
'' :
' NOT NULL';
1433 if ($field[
'notnull'] ===
false) {
1440 return $charset .
$default . $notnull . $collation;
1472 if (!empty($field[
'unsigned'])) {
1475 $db->warnings[] =
"unsigned integer field \"$name\" is being declared as signed integer";
1503 $notnull = empty($field[
'notnull']) ?
'' :
' NOT NULL';
1519 $notnull = empty($field[
'notnull']) ?
'' :
' NOT NULL';
1602 if (!method_exists($this,
"compare{$type}Definition")) {
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 ));
1615 if (empty($previous[
'type']) || $previous[
'type'] !=
$type) {
1619 $change = $this->{
"compare{$type}Definition"}(
$current, $previous);
1621 if ($previous[
'type'] !=
$type) {
1622 $change[
'type'] =
true;
1625 $previous_notnull = !empty($previous[
'notnull']) ? $previous[
'notnull'] :
false;
1627 if ($previous_notnull != $notnull) {
1628 $change[
'notnull'] =
true;
1631 $previous_default = array_key_exists(
'default', $previous) ? $previous[
'default'] : ($previous_notnull ?
'' : null);
1633 if ($previous_default !==
$default) {
1634 $change[
'default'] =
true;
1649 $previous_unsigned = !empty($previous[
'unsigned']) ? $previous[
'unsigned'] :
false;
1651 if ($previous_unsigned != $unsigned) {
1652 $change[
'unsigned'] =
true;
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;
1672 $previous_length = !empty($previous[
'length']) ? $previous[
'length'] : 0;
1674 if ($previous_length != $length) {
1675 $change[
'length'] =
true;
1677 $previous_fixed = !empty($previous[
'fixed']) ? $previous[
'fixed'] : 0;
1679 if ($previous_fixed != $fixed) {
1680 $change[
'fixed'] =
true;
1783 public function quote($value,
$type = null, $quote =
true, $escape_wildcards =
false)
1787 return $db->quote($value,
$type);
1790 || ($value ===
'' && $db->options[
'portability'])
1799 if (is_null(
$type)) {
1800 switch (gettype($value)) {
1813 $value = serialize($value);
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)) {
1823 } elseif (preg_match(
'/^\d{4}-\d{2}-\d{2}$/', $value)) {
1830 } elseif (!empty($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 );
1835 return call_user_func_array($db->options[
'datatype_map_callback'][
$type], array( &$db, __FUNCTION__, $parameter ));
1839 if (!method_exists($this,
"quote{$type}")) {
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']
1861 return (
int) $value;
1871 protected function quoteText($value, $quote, $escape_wildcards)
1879 $value = $db->escape($value, $escape_wildcards);
1881 return "'" . $value .
"'";
1892 if (preg_match(
'/^(\w+:\/\/)(.*)$/', $value, $match)) {
1894 if ($match[1] ==
'file://') {
1898 #$value = @fopen($value, 'r'); 1901 if (is_resource($value)) {
1906 while (!@feof($fp)) {
1907 $value .= @fread($fp, $db->options[
'lob_buffer_length']);
1924 protected function quoteLOB($value, $quote, $escape_wildcards)
1928 return $this->
quoteText($value, $quote, $escape_wildcards);
1938 protected function quoteCLOB($value, $quote, $escape_wildcards)
1940 return $this->
quoteLOB($value, $quote, $escape_wildcards);
1950 protected function quoteBLOB($value, $quote, $escape_wildcards)
1952 return $this->
quoteLOB($value, $quote, $escape_wildcards);
1964 return ($value ? 1 : 0);
1974 protected function quoteDate($value, $quote, $escape_wildcards)
1976 if ($value ===
'CURRENT_DATE') {
1979 return 'CURRENT_DATE';
1982 return $this->
quoteText($value, $quote, $escape_wildcards);
1995 if ($value ===
'CURRENT_TIMESTAMP') {
1998 if (isset($db->function) && is_a($db->function,
'MDB2_Driver_Function_Common')) {
1999 return $db->function->now(
'timestamp');
2002 return 'CURRENT_TIMESTAMP';
2005 return $this->
quoteText($value, $quote, $escape_wildcards);
2015 protected function quoteTime($value, $quote, $escape_wildcards)
2018 if ($value ===
'CURRENT_TIME') {
2021 if (isset($db->function) && is_a($db->function,
'MDB2_Driver_Function_Common')) {
2022 return $db->function->now(
'time');
2025 return 'CURRENT_TIME';
2028 return $this->
quoteText($value, $quote, $escape_wildcards);
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;
2046 $value = $this->
quoteDecimal($value, $quote, $escape_wildcards);
2061 $value = (string) $value;
2062 $value = preg_replace(
'/[^\d\.,\-+eE]/',
'', $value);
2063 if (preg_match(
'/[^.0-9]/', $value)) {
2064 if (strpos($value,
',')) {
2066 if (!strpos($value,
'.')) {
2068 $value = strrev(str_replace(
',',
'.', strrev($value)));
2070 } elseif (strpos($value,
'.') && strpos($value,
'.') < strpos($value,
',')) {
2071 $value = str_replace(
'.',
'', $value);
2073 $value = strrev(str_replace(
',',
'.', strrev($value)));
2076 $value = str_replace(
',',
'', $value);
2095 if (preg_match(
'/^(\w+:\/\/)(.*)$/', $file, $match)) {
2096 if ($match[1] ==
'file://') {
2101 $fp = @
fopen($file,
'wb');
2102 while (!@feof($lob)) {
2103 $result = @fread($lob, $db->options[
'lob_buffer_length']);
2105 if (@fwrite($fp,
$result, $read) != $read) {
2123 if (is_null($lob[
'value'])) {
2124 $lob[
'value'] = $lob[
'resource'];
2126 $lob[
'loaded'] =
true;
2139 return substr($lob[
'value'], $lob[
'position'], $length);
2149 return $lob[
'endOfLOB'];
2159 $lob_data = stream_get_meta_data($lob);
2160 $lob_index = $lob_data[
'wrapper_data']->lob_index;
2162 if (isset($this->lobs[$lob_index])) {
2164 unset($this->lobs[$lob_index]);
2189 if (!is_array($array) || empty($array)) {
2193 foreach ($array as $value) {
2200 return implode(
', ', $return);
2216 if (!is_null($operator)) {
2217 $operator = strtoupper($operator);
2218 switch ($operator) {
2221 if (is_null($field)) {
2222 throw new ilDatabaseException(
'case insensitive LIKE matching requires passing the field name');
2224 $db->loadModule(
'Function', null,
true);
2225 $match = $db->function->lower($field) .
' LIKE ';
2229 $match = is_null($field) ?
'LIKE ' : $field .
' LIKE ';
2236 foreach ($pattern as
$key => $value) {
2240 if ($operator ===
'ILIKE') {
2241 $value = strtolower($value);
2243 $escaped = $db->escape($value);
2244 $match .= $db->escapePattern($escaped);
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 ));
2295 if (!empty($db->options[
'datatype_map'][
$type])) {
2297 if (!empty($db->options[
'datatype_map_callback'][
$type])) {
2298 $parameter = array(
'type' =>
$type );
2300 return call_user_func_array($db->options[
'datatype_map_callback'][
$type], array( &$db, __FUNCTION__, $parameter ));
compareCLOBDefinition($current, $previous)
compareTimestampDefinition($current, $previous)
setAllowedAttributes($allowed_attributes)
quoteDate($value, $quote, $escape_wildcards)
getDateDeclaration($name, $field)
quote($value, $type=null, $quote=true, $escape_wildcards=false)
isAllowedAttribute($attribute, $type)
baseConvertResult($value, $type, $rtrim=true)
quoteLOB($value, $quote, $escape_wildcards)
quoteInteger($value, $quote, $escape_wildcards)
implodeArray($array, $type=false)
quoteTimestamp($value, $quote, $escape_wildcards)
compareBLOBDefinition($current, $previous)
Class ilDBPdoFieldDefinition.
quoteDecimal($value, $quote, $escape_wildcards)
compareBooleanDefinition($current, $previous)
compareFloatDefinition($current, $previous)
const DEFINITION_COLUMN_NAME
getCLOBDeclaration($name, $field)
getFloatDeclaration($name, $field)
mapNativeDatatype($field)
getCharsetFieldDeclaration($charset)
getDecimalDeclaration($name, $field)
Class ilDatabaseException.
getDeclaration($type, $name, $field)
checkColumnDefinition($a_def)
compareDateDefinition($current, $previous)
writeLOBToFile($lob, $file)
setReservedMysql($reserved_mysql)
getTypeDeclaration($field)
compareTextDefinition($current, $previous)
quoteFloat($value, $quote, $escape_wildcards)
checkTableName($table_name)
getTimeDeclaration($name, $field)
matchPattern($pattern, $operator=null, $field=null)
mapPrepareDatatype($type)
const DEFAULT_DECIMAL_PLACES
setReservedPostgres($reserved_postgres)
const SEQUENCE_COLUMNS_NAME
quoteCLOB($value, $quote, $escape_wildcards)
quoteBoolean($value, $quote, $escape_wildcards)
quoteText($value, $quote, $escape_wildcards)
getBLOBDeclaration($name, $field)
getIntegerDeclaration($name, $field)
getDeclarationOptions($field)
destroyLOBInternal(&$lob)
compareDefinition($current, $previous)
getInternalDeclaration($name, $field)
getCollationFieldDeclaration($collation)
getTextDeclaration($name, $field)
quoteBLOB($value, $quote, $escape_wildcards)
compareIntegerDefinition($current, $previous)
quoteTime($value, $quote, $escape_wildcards)
getTimestampDeclaration($name, $field)
sortResultFieldTypes($columns, $types)
__construct(\ilDBInterface $ilDBInterface)
ilDBPdoFieldDefinition constructor.
convertResultRow($types, $row, $rtrim=true)
const DEFINITION_TABLE_NAME
getBooleanDeclaration($name, $field)
compareTimeDefinition($current, $previous)
setMaxLength($max_length)
checkColumnName($column_name)
mapNativeDatatypeInternal($field)
convertResult($value, $type, $rtrim=true)
compareDecimalDefinition($current, $previous)
const DEFAULT_TEXT_LENGTH
setAvailableTypes($available_types)