3 declare(strict_types=1);
    49         self::T_TEXT => [
'length', 
'notnull', 
'default', 
'fixed'],
    50         self::T_INTEGER => [
'length', 
'notnull', 
'default', 
'unsigned'],
    51         self::T_FLOAT => [
'notnull', 
'default'],
    52         self::T_DATE => [
'notnull', 
'default'],
    53         self::T_TIME => [
'notnull', 
'default'],
    54         self::T_TIMESTAMP => [
'notnull', 
'default'],
    55         self::T_CLOB => [
'notnull', 
'default'],
    56         self::T_BLOB => [
'notnull', 
'default'],
    62         "text" => [
"length", 
"notnull", 
"default", 
"fixed"],
    63         "integer" => [
"length", 
"notnull", 
"default", 
"unsigned"],
    64         "float" => [
"notnull", 
"default"],
    65         "date" => [
"notnull", 
"default"],
    66         "time" => [
"notnull", 
"default"],
    67         "timestamp" => [
"notnull", 
"default"],
    68         "clob" => [
"length", 
"notnull", 
"default"],
    69         "blob" => [
"length", 
"notnull", 
"default"],
    73         self::T_INTEGER => [1, 2, 3, 4, 8],
   173         "CONSTRAINT_CATALOG",
   287         "GEOMETRYCOLLECTION",
   376         "MASTER_AUTO_POSITION",
   378         "MASTER_CONNECT_RETRY",
   380         "MASTER_HEARTBEAT_PERIOD",
   386         "MASTER_RETRY_COUNT",
   394         "MASTER_SSL_CRLPATH",
   396         "MASTER_SSL_VERIFY_SERVER_CERT",
   397         "MASTER_TLS_VERSION",
   401         "MAX_CONNECTIONS_PER_HOUR",
   402         "MAX_QUERIES_PER_HOUR",
   405         "MAX_STATEMENT_TIME",
   406         "MAX_UPDATES_PER_HOUR",
   407         "MAX_USER_CONNECTIONS",
   419         "MINUTE_MICROSECOND",
   448         "NO_WRITE_TO_BINLOG",
   531         "REPLICATE_DO_TABLE",
   532         "REPLICATE_IGNORE_DB",
   533         "REPLICATE_IGNORE_TABLE",
   534         "REPLICATE_REWRITE_DB",
   535         "REPLICATE_WILD_DO_TABLE",
   536         "REPLICATE_WILD_IGNORE_TABLE",
   566         "SECOND_MICROSECOND",
   598         "SQL_AFTER_MTS_GAPS",
   603         "SQL_CALC_FOUND_ROWS",
   622         "STATS_SAMPLE_PAGES",
   829         $this->db_instance = $ilDBInterface;
   834         if ($this->query_utils === null) {
   847         'timestamp' => 
'1970-01-01 00:00:00',
   848         'time' => 
'00:00:00',
   849         'date' => 
'1970-01-01',
   859         if (!preg_match(self::DEFINITION_TABLE_NAME, $table_name)) {
   860             throw new ilDatabaseException(
'Table name must only contain _a-z0-9 and must start with a-z.');
   864             throw new ilDatabaseException(
"Invalid table name '" . $table_name . 
"' (Reserved Word).");
   867         if (stripos($table_name, 
"sys_") === 0) {
   868             throw new ilDatabaseException(
"Invalid table name '" . $table_name . 
"'. Name must not start with 'sys_'.");
   871         if (strlen($table_name) > 22) {
   872             throw new ilDatabaseException(
"Invalid table name '" . $table_name . 
"'. Maximum table identifer length is 22 bytes.");
   913         if (!preg_match(
"/^[a-z]+[_a-z0-9]*$/", $column_name)) {
   915                 . 
"'. Column name must only contain _a-z0-9 and must start with a-z.");
   919             throw new ilDatabaseException(
"Invalid column name '" . $column_name . 
"' (Reserved Word).");
   922         if (stripos($column_name, 
"sys_") === 0) {
   923             throw new ilDatabaseException(
"Invalid column name '" . $column_name . 
"'. Name must not start with 'sys_'.");
   926         if (strlen($column_name) > 30) {
   927             throw new ilDatabaseException(
"Invalid column name '" . $column_name . 
"'. Maximum column identifer length is 30 bytes.");
   938         if (!preg_match(
"/^[a-z]+[_a-z0-9]*$/", $a_name)) {
   939             throw new ilDatabaseException(
"Invalid column name '" . $a_name . 
"'. Column name must only contain _a-z0-9 and must start with a-z.");
   946         if (strlen($a_name) > 3) {
   947             throw new ilDatabaseException(
"Invalid index name '" . $a_name . 
"'. Maximum index identifer length is 3 bytes.");
   960             switch ($a_def[
"type"]) {
   962                     throw new ilDatabaseException(
"Invalid column type '" . $a_def[
"type"] . 
"'. Use integer(1) instead.");
   965                     throw new ilDatabaseException(
"Invalid column type '" . $a_def[
"type"] . 
"'. Use float or integer instead.");
   968                     throw new ilDatabaseException(
"Invalid column type '" . $a_def[
"type"] . 
"'. Allowed types are: "   975         foreach (array_keys($a_def) as $k) {
   976             if ($k !== 
"type" && !in_array($k, $allowed_attributes[$a_def[
"type"]], 
true)) {
   977                 throw new ilDatabaseException(
"Attribute '" . $k . 
"' is not allowed for column type '" . $a_def[
"type"] . 
"'.");
   983         switch ($a_def[
"type"]) {
   985                 if ((!isset($a_def[
"length"]) || $a_def[
"length"] < 1 || $a_def[
"length"] > $max_length[self::T_TEXT]) && isset($a_def[
"length"])) {
   986                     throw new ilDatabaseException(
"Invalid length '" . $a_def[
"length"] . 
"' for type text." . 
" Length must be >=1 and <= "   987                         . $max_length[self::T_TEXT] . 
".");
   991             case self::T_INTEGER:
   992                 if (isset($a_def[
"length"]) && !in_array((
int) $a_def[
"length"], $max_length[self::T_INTEGER], 
true)) {
   993                     throw new ilDatabaseException(
"Invalid length '" . $a_def[
"length"] . 
"' for type integer." . 
" Length must be "   994                         . implode(
', ', $max_length[self::T_INTEGER]) . 
" (bytes).");
   996                 if ($a_def[
"unsigned"] ?? null) {
  1007         return in_array($attribute, $this->allowed_attributes[$type], 
true);
  1065         if (!empty($db->options[
'datatype_map'])) {
  1066             foreach ($db->options[
'datatype_map'] as $type => $mapped_type) {
  1067                 if (array_key_exists($mapped_type, $types)) {
  1068                     $types[$type] = $types[$mapped_type];
  1069                 } elseif (!empty($db->options[
'datatype_map_callback'][$type])) {
  1070                     $parameter = array(
'type' => $type, 
'mapped_type' => $mapped_type);
  1071                     $default = call_user_func_array(
  1072                         $db->options[
'datatype_map_callback'][$type],
  1073                         array(&$db, __FUNCTION__, $parameter)
  1075                     $types[$type] = $default;
  1093         if (!empty($db->options[
'datatype_map'][$type])) {
  1094             $type = $db->options[
'datatype_map'][$type];
  1095             if (!empty($db->options[
'datatype_map_callback'][$type])) {
  1096                 $parameter = array(
'type' => $type, 
'name' => $name, 
'field' => $field);
  1098                 return call_user_func_array(
  1099                     $db->options[
'datatype_map_callback'][$type],
  1100                     array(&$db, __FUNCTION__, $parameter)
  1103             $field[
'type'] = $type;
  1106         if (!method_exists($this, 
"get{$type}Declaration")) {
  1110         return $this->{
"get{$type}Declaration"}($name, $field);
  1117         switch ($field[
'type']) {
  1119                 $length = empty($field[
'length']) ? $db->options[
'default_text_field_length'] : $field[
'length'];
  1120                 $fixed = empty($field[
'fixed']) ? false : $field[
'fixed'];
  1122                     return $length ? 
'CHAR(' . $length . 
')' : 
'CHAR(' . $db->options[
'default_text_field_length'] . 
')';
  1125                 return $length ? 
'VARCHAR(' . $length . 
')' : 
'TEXT';
  1135                 return 'CHAR (' . strlen(
'YYYY-MM-DD') . 
')';
  1137                 return 'CHAR (' . strlen(
'HH:MM:SS') . 
')';
  1139                 return 'CHAR (' . strlen(
'YYYY-MM-DD HH:MM:SS') . 
')';
  1149         $name = $db->quoteIdentifier($name, 
true);
  1150         $declaration_options = 
'';
  1151         $fd = $db->getFieldDefinition();
  1153             $declaration_options = $fd->getDeclarationOptions($field);
  1167         if (array_key_exists(
'default', $field)) {
  1168             if ($field[
'default'] === 
'') {
  1171                 if (empty($field[
'notnull'])) {
  1172                     $field[
'default'] = null;
  1175                     $field[
'default'] = $valid_default_values[$field[
'type']];
  1177                 if ($field[
'default'] === 
''  1178                     && isset($db->options[
"portability"])
  1179                     && ($db->options[
'portability'] & 32)
  1181                     $field[
'default'] = 
' ';
  1184             $default = 
' DEFAULT ' . $this->
quote($field[
'default'], $field[
'type']);
  1185         } elseif (empty($field[
'notnull'])) {
  1186             $default = 
' DEFAULT NULL';
  1189         $notnull = empty($field[
'notnull']) ? 
'' : 
' NOT NULL';
  1191         if (isset($field[
"notnull"]) && $field[
'notnull'] === 
false) {
  1198         return $charset . $default . $notnull . $collation;
  1231         $notnull = empty($field[
'notnull']) ? 
'' : 
' NOT NULL';
  1232         $name = $db->quoteIdentifier($name, 
true);
  1241         $notnull = empty($field[
'notnull']) ? 
'' : 
' NOT NULL';
  1242         $name = $db->quoteIdentifier($name, 
true);
  1284         $type = empty($current[
'type']) ? null : $current[
'type'];
  1286         if (!method_exists($this, 
"compare{$type}Definition")) {
  1289             if (!empty($db->options[
'datatype_map_callback'][$type])) {
  1290                 $parameter = array(
'current' => $current, 
'previous' => $previous);
  1292                 return call_user_func_array(
  1293                     $db->options[
'datatype_map_callback'][$type],
  1294                     array(&$db, __FUNCTION__, $parameter)
  1301         if (empty($previous[
'type']) || $previous[
'type'] != $type) {
  1305         $change = $this->{
"compare{$type}Definition"}($current, $previous);
  1307         if ($previous[
'type'] != $type) {
  1308             $change[
'type'] = 
true;
  1311         $previous_notnull = empty($previous[
'notnull']) ? false : $previous[
'notnull'];
  1312         $notnull = empty($current[
'notnull']) ? false : $current[
'notnull'];
  1313         if ($previous_notnull !== $notnull) {
  1314             $change[
'notnull'] = 
true;
  1317         $alt = $previous_notnull ? 
'' : null;
  1318         $previous_default = array_key_exists(
  1321         ) ? $previous[
'default'] : $alt;
  1322         $alt = $notnull ? 
'' : null;
  1323         $default = array_key_exists(
'default', $current) ? $current[
'default'] : $alt;
  1324         if ($previous_default !== $default) {
  1325             $change[
'default'] = 
true;
  1337         $previous_unsigned = empty($previous[
'unsigned']) ? false : $previous[
'unsigned'];
  1338         $unsigned = empty($current[
'unsigned']) ? false : $current[
'unsigned'];
  1339         if ($previous_unsigned != $unsigned) {
  1340             $change[
'unsigned'] = 
true;
  1342         $previous_autoincrement = empty($previous[
'autoincrement']) ? false : $previous[
'autoincrement'];
  1343         $autoincrement = empty($current[
'autoincrement']) ? false : $current[
'autoincrement'];
  1344         if ($previous_autoincrement != $autoincrement) {
  1345             $change[
'autoincrement'] = 
true;
  1357         $previous_length = empty($previous[
'length']) ? 0 : $previous[
'length'];
  1358         $length = empty($current[
'length']) ? 0 : $current[
'length'];
  1359         if ($previous_length != $length) {
  1360             $change[
'length'] = 
true;
  1362         $previous_fixed = empty($previous[
'fixed']) ? 0 : $previous[
'fixed'];
  1363         $fixed = empty($current[
'fixed']) ? 0 : $current[
'fixed'];
  1364         if ($previous_fixed != $fixed) {
  1365             $change[
'fixed'] = 
true;
  1420     public function quote($value, ?
string $type = null, 
bool $quote = 
true, 
bool $escape_wildcards = 
false): string
  1430         return (
int) $value;
  1433     protected function quoteText(
string $value, 
bool $quote, 
bool $escape_wildcards): string
  1441         $value = $db->escape($value, $escape_wildcards);
  1443         return "'" . $value . 
"'";
  1452         if (is_string($value) && preg_match(
'/^(\w+:\/\/)(.*)$/', $value, $match)) {
  1454             if ($match[1] === 
'file://') {
  1458             #$value = @fopen($value, 'r');  1461         if (is_resource($value)) {
  1466             while (!@feof($fp)) {
  1467                 $value .= @fread($fp, $db->options[
'lob_buffer_length']);
  1480     protected function quoteLOB($value, 
bool $quote, 
bool $escape_wildcards): string
  1484         return $this->
quoteText($value, $quote, $escape_wildcards);
  1489     protected function quoteCLOB($value, 
bool $quote, 
bool $escape_wildcards): string
  1491         return $this->
quoteLOB($value, $quote, $escape_wildcards);
  1496     protected function quoteBLOB($value, 
bool $quote, 
bool $escape_wildcards): string
  1498         return $this->
quoteLOB($value, $quote, $escape_wildcards);
  1503         return ($value ? 1 : 0);
  1506     protected function quoteDate(
string $value, 
bool $quote, 
bool $escape_wildcards): string
  1508         if ($value === 
'CURRENT_DATE') {
  1509             return 'CURRENT_DATE';
  1512         return $this->
quoteText($value, $quote, $escape_wildcards);
  1518     protected function quoteTimestamp(
int $value, 
bool $quote, 
bool $escape_wildcards): string
  1526     protected function quoteTime(
int $value, 
bool $quote, 
bool $escape_wildcards): string
  1531     protected function quoteFloat(
string $value, 
bool $quote, 
bool $escape_wildcards): ?string
  1533         if (preg_match(
'/^(.*)e([-+])(\d+)$/i', $value, $matches)) {
  1534             $decimal = $this->
quoteDecimal($matches[1], $quote, $escape_wildcards);
  1535             $sign = $matches[2];
  1536             $exponent = str_pad($matches[3], 2, 
'0', STR_PAD_LEFT);
  1537             $value = $decimal . 
'E' . $sign . $exponent;
  1539             $value = $this->
quoteDecimal($value, $quote, $escape_wildcards);
  1545     protected function quoteDecimal(
string $value, 
bool $quote, 
bool $escape_wildcards): ?string
  1547         $value = preg_replace(
'/[^\d\.,\-+eE]/', 
'', $value);
  1548         if (preg_match(
'/[^.0-9]/', $value) && strpos($value, 
',')) {
  1550             if (!strpos($value, 
'.')) {
  1552                 $value = strrev(str_replace(
',', 
'.', strrev($value)));
  1554             } elseif (strpos($value, 
'.') && strpos($value, 
'.') < strpos($value, 
',')) {
  1555                 $value = str_replace(
'.', 
'', $value);
  1557                 $value = strrev(str_replace(
',', 
'.', strrev($value)));
  1560                 $value = str_replace(
',', 
'', $value);
  1576         if (preg_match(
'/^(\w+:\/\/)(.*)$/', $file, $match) && $match[1] === 
'file://') {
  1580         $fp = @fopen($file, 
'wb');
  1581         while (!@feof($lob)) {
  1582             $result = @fread($lob, $db->options[
'lob_buffer_length']);
  1583             $read = strlen($result);
  1584             if (@fwrite($fp, $result, $read) !== $read) {
  1597         if (is_null($lob[
'value'])) {
  1598             $lob[
'value'] = $lob[
'resource'];
  1600         $lob[
'loaded'] = 
true;
  1605     protected function readLOB(array $lob, 
int $length): string
  1607         return substr($lob[
'value'], $lob[
'position'], $length);
  1615         return $lob[
'endOfLOB'];
  1623         $lob_data = stream_get_meta_data($lob);
  1624         $lob_index = $lob_data[
'wrapper_data']->lob_index;
  1626         if (isset($this->lobs[$lob_index])) {
  1627             unset($this->lobs[$lob_index]);
  1637     public function matchPattern(array $pattern, $operator = null, $field = null): string
  1642         if (!is_null($operator)) {
  1643             $operator = strtoupper($operator);
  1644             switch ($operator) {
  1647                     if (is_null($field)) {
  1648                         throw new ilDatabaseException(
'case insensitive LIKE matching requires passing the field name');
  1650                     $db->loadModule(
'Function');
  1651                     $match = $db->lower($field) . 
' LIKE ';
  1655                     $match = is_null($field) ? 
'LIKE ' : $field . 
' LIKE ';
  1662         foreach ($pattern as 
$key => $value) {
  1663             if (
$key % 2 !== 0) {
  1666                 if ($operator === 
'ILIKE') {
  1667                     $value = strtolower($value);
  1669                 $escaped = $db->escape($value);
  1670                 $match .= $db->escapePattern($escaped);
  1690         $db_type = strtok($field[
'type'], 
'(), ');
  1691         if (!empty($db->options[
'nativetype_map_callback'][$db_type])) {
  1692             return call_user_func_array($db->options[
'nativetype_map_callback'][$db_type], array($db, $field));
  1710         if (!empty($db->options[
'datatype_map'][$type])) {
  1711             $type = $db->options[
'datatype_map'][$type];
  1712             if (!empty($db->options[
'datatype_map_callback'][$type])) {
  1713                 $parameter = array(
'type' => $type);
  1715                 return call_user_func_array(
  1716                     $db->options[
'datatype_map_callback'][$type],
  1717                     array(&$db, __FUNCTION__, $parameter)
 compareIntegerDefinition(array $current, array $previous)
 
compareDecimalDefinition(array $current, array $previous)
 
compareBooleanDefinition(array $current, array $previous)
 
getIntegerDeclaration(string $name, array $field)
 
quoteBoolean(bool $value, bool $quote, bool $escape_wildcards)
 
compareTimeDefinition(array $current, array $previous)
 
isAllowedAttribute(string $attribute, string $type)
 
quoteCLOB($value, bool $quote, bool $escape_wildcards)
 
quoteFloat(string $value, bool $quote, bool $escape_wildcards)
 
mapNativeDatatype(array $field)
 
getTimeDeclaration(string $name, array $field)
 
compareDefinition(array $current, array $previous)
 
quoteInteger($value, bool $quote, bool $escape_wildcards)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
getTextDeclaration(string $name, array $field)
 
array $valid_default_values
 
array checkTableName(string $table_name)
 
compareCLOBDefinition(array $current, array $previous)
 
getTimestampDeclaration(string $name, array $field)
 
const DEFINITION_COLUMN_NAME
 
getInternalDeclaration(string $name, array $field)
 
quoteDecimal(string $value, bool $quote, bool $escape_wildcards)
 
setAvailableTypes(array $available_types)
 
mapNativeDatatypeInternal(array $field)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
mapPrepareDatatype(string $type)
 
getDeclarationOptions(array $field)
 
quoteBLOB($value, bool $quote, bool $escape_wildcards)
 
getCharsetFieldDeclaration(string $charset)
 
quoteLOB($value, bool $quote, bool $escape_wildcards)
 
getFloatDeclaration(string $name, array $field)
 
array ilDBInterface $db_instance
 
checkColumnName(string $column_name)
 
compareTextDefinition(array $current, array $previous)
 
compareTimestampDefinition(array $current, array $previous)
 
writeLOBToFile($lob, string $file)
 
getDecimalDeclaration(string $name, array $field)
 
checkIndexName(string $a_name)
 
compareFloatDefinition(array $current, array $previous)
 
setAllowedAttributes(array $allowed_attributes)
 
checkColumnDefinition(array $a_def)
 
array $allowed_attributes_old
 
const DEFAULT_DECIMAL_PLACES
 
quoteText(string $value, bool $quote, bool $escape_wildcards)
 
const SEQUENCE_COLUMNS_NAME
 
getCLOBDeclaration(string $name, array $field)
 
readLOB(array $lob, int $length)
 
getBooleanDeclaration(string $name, array $field)
 
array $allowed_attributes
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
matchPattern(array $pattern, $operator=null, $field=null)
 
quoteTime(int $value, bool $quote, bool $escape_wildcards)
 
getDateDeclaration(string $name, array $field)
 
setReservedMysql(array $reserved_mysql)
 
quoteTimestamp(int $value, bool $quote, bool $escape_wildcards)
 
quoteDate(string $value, bool $quote, bool $escape_wildcards)
 
compareDateDefinition(array $current, array $previous)
 
getTypeDeclaration(array $field)
 
setMaxLength(array $max_length)
 
quote($value, ?string $type=null, bool $quote=true, bool $escape_wildcards=false)
 
__construct(\ilDBInterface $ilDBInterface)
ilDBPdoFieldDefinition constructor. 
 
const DEFINITION_TABLE_NAME
 
compareBLOBDefinition(array $current, array $previous)
 
getDeclaration(string $type, string $name, $field)
 
isReserved(string $table_name)
 
ilMySQLQueryUtils $query_utils
 
const DEFAULT_TEXT_LENGTH
 
getBLOBDeclaration(string $name, array $field)
 
getCollationFieldDeclaration(string $collation)
 
static ilDBPdoFieldDefinition $instance