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 <= " 
 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 ));
 
An exception for terminatinating execution or to throw for unit testing.
Class ilDBPdoFieldDefinition.
const DEFINITION_TABLE_NAME
getIntegerDeclaration($name, $field)
quoteText($value, $quote, $escape_wildcards)
quoteFloat($value, $quote, $escape_wildcards)
compareIntegerDefinition($current, $previous)
setReservedPostgres($reserved_postgres)
checkTableName($table_name)
quoteDecimal($value, $quote, $escape_wildcards)
quoteTime($value, $quote, $escape_wildcards)
destroyLOBInternal(&$lob)
getDeclaration($type, $name, $field)
compareDecimalDefinition($current, $previous)
getCLOBDeclaration($name, $field)
compareBLOBDefinition($current, $previous)
getTimestampDeclaration($name, $field)
compareCLOBDefinition($current, $previous)
setAllowedAttributes($allowed_attributes)
compareDefinition($current, $previous)
__construct(\ilDBInterface $ilDBInterface)
ilDBPdoFieldDefinition constructor.
getTypeDeclaration($field)
const SEQUENCE_COLUMNS_NAME
getBLOBDeclaration($name, $field)
implodeArray($array, $type=false)
quote($value, $type=null, $quote=true, $escape_wildcards=false)
getBooleanDeclaration($name, $field)
compareTextDefinition($current, $previous)
quoteBLOB($value, $quote, $escape_wildcards)
getDeclarationOptions($field)
mapPrepareDatatype($type)
compareFloatDefinition($current, $previous)
quoteBoolean($value, $quote, $escape_wildcards)
const DEFAULT_TEXT_LENGTH
compareTimestampDefinition($current, $previous)
isAllowedAttribute($attribute, $type)
getCollationFieldDeclaration($collation)
convertResult($value, $type, $rtrim=true)
mapNativeDatatype($field)
getTextDeclaration($name, $field)
checkColumnDefinition($a_def)
getDecimalDeclaration($name, $field)
setMaxLength($max_length)
const DEFINITION_COLUMN_NAME
quoteLOB($value, $quote, $escape_wildcards)
compareDateDefinition($current, $previous)
writeLOBToFile($lob, $file)
getDateDeclaration($name, $field)
mapNativeDatatypeInternal($field)
const DEFAULT_DECIMAL_PLACES
matchPattern($pattern, $operator=null, $field=null)
setAvailableTypes($available_types)
getFloatDeclaration($name, $field)
convertResultRow($types, $row, $rtrim=true)
quoteInteger($value, $quote, $escape_wildcards)
quoteTimestamp($value, $quote, $escape_wildcards)
checkColumnName($column_name)
baseConvertResult($value, $type, $rtrim=true)
quoteDate($value, $quote, $escape_wildcards)
setReservedMysql($reserved_mysql)
compareBooleanDefinition($current, $previous)
compareTimeDefinition($current, $previous)
getInternalDeclaration($name, $field)
sortResultFieldTypes($columns, $types)
quoteCLOB($value, $quote, $escape_wildcards)
getTimeDeclaration($name, $field)
getCharsetFieldDeclaration($charset)
Class ilDatabaseException.