2 namespace TYPO3\CMS\Dbal\Database;
172 MYSQLI_TYPE_TINY =>
'tinyint',
173 MYSQLI_TYPE_CHAR =>
'tinyint',
174 MYSQLI_TYPE_SHORT =>
'smallint',
175 MYSQLI_TYPE_LONG =>
'int',
176 MYSQLI_TYPE_FLOAT =>
'float',
177 MYSQLI_TYPE_DOUBLE =>
'double',
178 MYSQLI_TYPE_TIMESTAMP =>
'timestamp',
179 MYSQLI_TYPE_LONGLONG =>
'bigint',
180 MYSQLI_TYPE_INT24 =>
'mediumint',
181 MYSQLI_TYPE_DATE =>
'date',
182 MYSQLI_TYPE_NEWDATE =>
'date',
183 MYSQLI_TYPE_TIME =>
'time',
184 MYSQLI_TYPE_DATETIME =>
'datetime',
185 MYSQLI_TYPE_YEAR =>
'year',
186 MYSQLI_TYPE_BIT =>
'bit',
187 MYSQLI_TYPE_INTERVAL =>
'interval',
188 MYSQLI_TYPE_ENUM =>
'enum',
189 MYSQLI_TYPE_SET =>
'set',
190 MYSQLI_TYPE_TINY_BLOB =>
'blob',
191 MYSQLI_TYPE_MEDIUM_BLOB =>
'blob',
192 MYSQLI_TYPE_LONG_BLOB =>
'blob',
193 MYSQLI_TYPE_BLOB =>
'blob',
194 MYSQLI_TYPE_VAR_STRING =>
'varchar',
195 MYSQLI_TYPE_STRING =>
'char',
196 MYSQLI_TYPE_DECIMAL =>
'decimal',
197 MYSQLI_TYPE_NEWDECIMAL =>
'decimal',
198 MYSQLI_TYPE_GEOMETRY =>
'geometry'
217 $this->conf =
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'dbal'];
228 if (isset($this->conf[
'mapping'])) {
229 $this->mapping = $this->conf[
'mapping'];
231 if (isset($this->conf[
'table2handlerKeys'])) {
232 $this->table2handlerKeys = $this->conf[
'table2handlerKeys'];
235 $specificsClassName = Specifics\NullSpecifics::class;
236 if (isset($this->conf[
'handlerCfg'])) {
237 $this->handlerCfg = $this->conf[
'handlerCfg'];
239 if (isset($this->handlerCfg[
'_DEFAULT'][
'config'][
'driver'])) {
241 $driver = $this->handlerCfg[
'_DEFAULT'][
'config'][
'driver'];
242 $className =
'TYPO3\\CMS\\Dbal\\Database\\Specifics\\' . ucfirst(strtolower($driver)) .
'Specifics';
243 if (class_exists($className)) {
244 if (!is_subclass_of($className, Specifics\AbstractSpecifics::class)) {
245 throw new \InvalidArgumentException($className .
' must inherit from ' . Specifics\AbstractSpecifics::class, 1416919866);
247 $specificsClassName = $className;
254 $this->printErrors = !empty($this->conf[
'debugOptions'][
'printErrors']);
255 $this->
debug = !empty($this->conf[
'debugOptions'][
'enabled']);
296 if ($phpCodeCache->has($this->cacheIdentifier)) {
297 $fieldInformation = $phpCodeCache->requireOnce($this->cacheIdentifier);
298 $this->cache_autoIncFields = $fieldInformation[
'incFields'];
299 $this->cache_fieldType = $fieldInformation[
'fieldTypes'];
300 $this->cache_primaryKeys = $fieldInformation[
'primaryKeys'];
305 $phpCodeCache->set($this->cacheIdentifier, $this->
getCacheableString($completeFieldInformation), array(
'DatabaseConnection'));
319 $this->
parseAndAnalyzeSql($schemaService->getCachingFrameworkRequiredDatabaseSchema());
330 if (isset(
$GLOBALS[
'TYPO3_LOADED_EXT']) && (is_array(
$GLOBALS[
'TYPO3_LOADED_EXT']) ||
$GLOBALS[
'TYPO3_LOADED_EXT'] instanceof \ArrayAccess)) {
331 foreach (
$GLOBALS[
'TYPO3_LOADED_EXT'] as $extensionConfiguration) {
332 $isArray = (is_array($extensionConfiguration) || $extensionConfiguration instanceof \ArrayAccess);
333 if (!$isArray || ($isArray && !isset($extensionConfiguration[
'ext_tables.sql']))) {
336 $extensionsSql = file_get_contents($extensionConfiguration[
'ext_tables.sql']);
350 $parsedSql = $this->installerSql->getFieldDefinitions_fileContent($sql);
362 return array(
'incFields' => $this->cache_autoIncFields,
'fieldTypes' => $this->cache_fieldType,
'primaryKeys' => $this->cache_primaryKeys);
374 $cacheString =
'return ';
375 $cacheString .= var_export($fieldInformation,
true);
388 foreach ($parsedExtSQL as $table => $tdef) {
390 if (isset($this->mapping[$table])) {
391 $table = $this->mapping[$table][
'mapTableName'];
393 if (is_array($tdef[
'fields'])) {
394 foreach ($tdef[
'fields'] as $field => $fdefString) {
395 $fdef = $this->SQLparser->parseFieldDef($fdefString);
396 $fieldType = isset($fdef[
'fieldType']) ? $fdef[
'fieldType'] :
'';
397 $this->cache_fieldType[$table][$field][
'type'] = $fieldType;
398 $this->cache_fieldType[$table][$field][
'metaType'] = $this->dbmsSpecifics->getMetaFieldType($fieldType);
399 $this->cache_fieldType[$table][$field][
'notnull'] = isset($fdef[
'featureIndex'][
'NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef[
'featureIndex']) ? 1 : 0;
400 if (isset($fdef[
'featureIndex'][
'DEFAULT'])) {
401 $default = $fdef[
'featureIndex'][
'DEFAULT'][
'value'][0];
402 if (isset($fdef[
'featureIndex'][
'DEFAULT'][
'value'][1])) {
403 $default = $fdef[
'featureIndex'][
'DEFAULT'][
'value'][1] . $default . $fdef[
'featureIndex'][
'DEFAULT'][
'value'][1];
405 $this->cache_fieldType[$table][$field][
'default'] = $default;
407 if (isset($fdef[
'featureIndex'][
'AUTO_INCREMENT'])) {
408 $this->cache_autoIncFields[$table] = $field;
410 if (isset($tdef[
'keys'][
'PRIMARY'])) {
411 $this->cache_primaryKeys[$table] = substr($tdef[
'keys'][
'PRIMARY'], 13, -1);
428 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'dbal'][
'mapping'])) {
429 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'dbal'][
'mapping'] as $mappedTable => $mappedConf) {
430 if (array_key_exists($mappedTable, $fieldInfo[
'incFields'])) {
431 $mappedTableAlias = $mappedConf[
'mapTableName'];
432 if (isset($mappedConf[
'mapFieldNames'][$fieldInfo[
'incFields'][$mappedTable]])) {
433 $fieldInfo[
'incFields'][$mappedTableAlias] = $mappedConf[
'mapFieldNames'][$fieldInfo[
'incFields'][$mappedTable]];
435 $fieldInfo[
'incFields'][$mappedTableAlias] = $fieldInfo[
'incFields'][$mappedTable];
438 if (array_key_exists($mappedTable, $fieldInfo[
'fieldTypes'])) {
439 $tempMappedFieldConf = array();
440 foreach ($fieldInfo[
'fieldTypes'][$mappedTable] as $field => $fieldConf) {
441 $tempMappedFieldConf[$mappedConf[
'mapFieldNames'][$field]] = $fieldConf;
443 $fieldInfo[
'fieldTypes'][$mappedConf[
'mapTableName']] = $tempMappedFieldConf;
445 if (array_key_exists($mappedTable, $fieldInfo[
'primaryKeys'])) {
446 $mappedTableAlias = $mappedConf[
'mapTableName'];
447 if (isset($mappedConf[
'mapFieldNames'][$fieldInfo[
'primaryKeys'][$mappedTable]])) {
448 $fieldInfo[
'primaryKeys'][$mappedTableAlias] = $mappedConf[
'mapFieldNames'][$fieldInfo[
'primaryKeys'][$mappedTable]];
450 $fieldInfo[
'primaryKeys'][$mappedTableAlias] = $fieldInfo[
'primaryKeys'][$mappedTable];
489 $ORIG_tableName = $table;
492 $fields_values = $this->
map_assocArray($fields_values, $tableArray);
494 if ($this->mapping[$table][
'mapTableName']) {
495 $table = $this->mapping[$table][
'mapTableName'];
500 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
504 $this->lastQuery = $this->
INSERTquery($table, $fields_values, $no_quote_fields);
505 if (is_string($this->lastQuery)) {
506 $sqlResult = $this->
query($this->lastQuery);
508 $sqlResult = $this->
query($this->lastQuery[0]);
510 $where = $this->cache_autoIncFields[$table] .
'=' . $new_id;
511 foreach ($this->lastQuery[1] as $field => $content) {
520 if (isset($this->cache_autoIncFields[$table])) {
521 if (!isset($fields_values[$this->cache_autoIncFields[$table]]) && !$this->handlerInstance[$this->lastHandlerKey]->hasInsertID) {
524 $fields_values[$this->cache_autoIncFields[$table]] = $this->handlerInstance[
$this->lastHandlerKey]->GenID($table .
'_' . $this->cache_autoIncFields[$table], $this->handlerInstance[$this->lastHandlerKey]->sequenceStart);
527 $this->lastQuery = $this->
INSERTquery($table, $fields_values, $no_quote_fields);
528 if (is_string($this->lastQuery)) {
533 if ((
string)$this->lastQuery[0] !==
'') {
537 if (is_array($this->lastQuery[1])) {
538 foreach ($this->lastQuery[1] as $field => $content) {
539 if (empty($content)) {
542 if (isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
544 }
elseif (isset($this->cache_primaryKeys[$table])) {
546 $pks = explode(
',', $this->cache_primaryKeys[$table]);
547 foreach ($pks as $pk) {
548 if (isset($fields_values[$pk])) {
549 $where .= $pk .
'=' . $this->
fullQuoteStr($fields_values[$pk], $table) .
' AND ';
557 throw new \RuntimeException(
'Could not update BLOB >>>> no WHERE clause found!', 1321860519);
561 if (is_array($this->lastQuery[2])) {
562 foreach ($this->lastQuery[2] as $field => $content) {
563 if (empty($content)) {
566 if (isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
568 }
elseif (isset($this->cache_primaryKeys[$table])) {
570 $pks = explode(
',', $this->cache_primaryKeys[$table]);
571 foreach ($pks as $pk) {
572 if (isset($fields_values[$pk])) {
573 $where .= $pk .
'=' . $this->
fullQuoteStr($fields_values[$pk], $table) .
' AND ';
581 throw new \RuntimeException(
'Could not update CLOB >>>> no WHERE clause found!', 1310027337);
589 $sqlResult = $this->handlerInstance[
$this->lastHandlerKey]->exec_INSERTquery($table, $fields_values, $no_quote_fields);
592 if ($this->printErrors && $this->
sql_error()) {
596 $this->
debugHandler(
'exec_INSERTquery', GeneralUtility::milliseconds() - $pt, array(
597 'handlerType' => $hType,
598 'args' => array($table, $fields_values),
599 'ORIG_tablename' => $ORIG_tableName
602 foreach ($this->postProcessHookObjects as $hookObject) {
603 $hookObject->exec_INSERTquery_postProcessAction($table, $fields_values, $no_quote_fields, $this);
621 if ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type'] ===
'native') {
623 $res = $this->
query(parent::INSERTmultipleRows($table, $fields, $rows, $no_quote_fields));
625 foreach ($rows as $row) {
626 $fields_values = array();
627 foreach ($fields as $key => $value) {
628 $fields_values[$value] = $row[$key];
633 foreach ($this->postProcessHookObjects as $hookObject) {
634 $hookObject->exec_INSERTmultipleRows_postProcessAction($table, $fields, $rows, $no_quote_fields, $this);
653 $ORIG_tableName = $table;
656 $fields_values = $this->
map_assocArray($fields_values, $tableArray);
658 $whereParts = $this->SQLparser->parseWhereClause($where);
659 $this->
map_sqlParts($whereParts, $tableArray[0][
'table']);
660 $where = $this->SQLparser->compileWhereClause($whereParts,
false);
662 if ($this->mapping[$table][
'mapTableName']) {
663 $table = $this->mapping[$table][
'mapTableName'];
668 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
672 $this->lastQuery = $this->
UPDATEquery($table, $where, $fields_values, $no_quote_fields);
673 if (is_string($this->lastQuery)) {
674 $sqlResult = $this->
query($this->lastQuery);
676 $sqlResult = $this->
query($this->lastQuery[0]);
677 foreach ($this->lastQuery[1] as $field => $content) {
684 $this->lastQuery = $this->
UPDATEquery($table, $where, $fields_values, $no_quote_fields);
685 if (is_string($this->lastQuery)) {
689 if ((
string)$this->lastQuery[0] !==
'') {
692 if (is_array($this->lastQuery[1])) {
693 foreach ($this->lastQuery[1] as $field => $content) {
697 if (is_array($this->lastQuery[2])) {
698 foreach ($this->lastQuery[2] as $field => $content) {
706 $sqlResult = $this->handlerInstance[
$this->lastHandlerKey]->exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields);
709 if ($this->printErrors && $this->
sql_error()) {
713 $this->
debugHandler(
'exec_UPDATEquery', GeneralUtility::milliseconds() - $pt, array(
714 'handlerType' => $hType,
715 'args' => array($table, $where, $fields_values),
716 'ORIG_from_table' => $ORIG_tableName
719 foreach ($this->postProcessHookObjects as $hookObject) {
720 $hookObject->exec_UPDATEquery_postProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
737 $ORIG_tableName = $table;
740 $whereParts = $this->SQLparser->parseWhereClause($where);
741 $this->
map_sqlParts($whereParts, $tableArray[0][
'table']);
742 $where = $this->SQLparser->compileWhereClause($whereParts,
false);
744 if ($this->mapping[$table][
'mapTableName']) {
745 $table = $this->mapping[$table][
'mapTableName'];
750 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
754 $this->lastQuery = $this->
DELETEquery($table, $where);
755 $sqlResult = $this->
query($this->lastQuery);
758 $this->lastQuery = $this->
DELETEquery($table, $where);
765 if ($this->printErrors && $this->
sql_error()) {
769 $this->
debugHandler(
'exec_DELETEquery', GeneralUtility::milliseconds() - $pt, array(
770 'handlerType' => $hType,
771 'args' => array($table, $where),
772 'ORIG_from_table' => $ORIG_tableName
775 foreach ($this->postProcessHookObjects as $hookObject) {
776 $hookObject->exec_DELETEquery_postProcessAction($table, $where, $this);
795 public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy =
'', $orderBy =
'', $limit =
'')
799 $ORIG_tableName = $from_table;
801 $parsedFromTable = array();
802 $remappedParameters = array();
803 if ($tableArray = $this->
map_needMapping($ORIG_tableName,
false, $parsedFromTable)) {
804 $from = $parsedFromTable ? $parsedFromTable : $from_table;
808 if (!empty($remappedParameters)) {
810 $fromTable = $mappedQueryParts[1];
812 $fromTable = $from_table;
815 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
819 if (!empty($remappedParameters)) {
820 list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->
compileSelectParameters($remappedParameters);
822 $this->lastQuery = $this->
SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
823 $sqlResult = $this->
query($this->lastQuery);
824 $this->resourceIdToTableNameMap[serialize($sqlResult)] = $ORIG_tableName;
830 if ($splitLimit[1]) {
832 $numrows = $splitLimit[1];
833 $offset = $splitLimit[0];
835 $numrows = $splitLimit[0];
838 if (!empty($remappedParameters)) {
841 $sqlResult = $this->handlerInstance[
$this->lastHandlerKey]->SelectLimit($this->
SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy), $numrows, $offset);
843 $this->lastQuery = $sqlResult->sql;
845 if (!empty($remappedParameters)) {
848 $this->lastQuery = $this->
SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
852 if (!is_object($sqlResult)) {
853 throw new \RuntimeException(
'ADOdb could not run this query: ' . $this->lastQuery, 1421053336);
855 $sqlResult->TYPO3_DBAL_handlerType =
'adodb';
857 $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
860 if (!empty($remappedParameters)) {
861 list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->
compileSelectParameters($remappedParameters);
863 $sqlResult = $this->handlerInstance[
$this->lastHandlerKey]->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
864 if (is_object($sqlResult)) {
865 $sqlResult->TYPO3_DBAL_handlerType =
'userdefined';
867 $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
871 if ($this->printErrors && $this->
sql_error()) {
876 'handlerType' => $hType,
877 'args' => array($from_table, $select_fields, $where_clause, $groupBy, $orderBy, $limit),
878 'ORIG_from_table' => $ORIG_tableName
880 if ($this->conf[
'debugOptions'][
'numberRows']) {
883 $this->
debugHandler(
'exec_SELECTquery', GeneralUtility::milliseconds() - $pt, $data);
899 $ORIG_tableName = $table;
902 if ($this->mapping[$table][
'mapTableName']) {
903 $table = $this->mapping[$table][
'mapTableName'];
908 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
913 $sqlResult = $this->
query($this->lastQuery);
923 if ($this->printErrors && $this->
sql_error()) {
927 $this->
debugHandler(
'exec_TRUNCATEquery', GeneralUtility::milliseconds() - $pt, array(
928 'handlerType' => $hType,
929 'args' => array($table),
930 'ORIG_from_table' => $ORIG_tableName
933 foreach ($this->postProcessHookObjects as $hookObject) {
934 $hookObject->exec_TRUNCATEquery_postProcessAction($table, $this);
950 switch ($queryParts[
'type']) {
952 $selectFields = $this->SQLparser->compileFieldList($queryParts[
'SELECT']);
953 $fromTables = $this->SQLparser->compileFromTables($queryParts[
'FROM']);
954 $whereClause = isset($queryParts[
'WHERE']) ? $this->SQLparser->compileWhereClause($queryParts[
'WHERE']) :
'1=1';
955 $groupBy = isset($queryParts[
'GROUPBY']) ? $this->SQLparser->compileFieldList($queryParts[
'GROUPBY']) :
'';
956 $orderBy = isset($queryParts[
'ORDERBY']) ? $this->SQLparser->compileFieldList($queryParts[
'ORDERBY']) :
'';
957 $limit = isset($queryParts[
'LIMIT']) ? $queryParts[
'LIMIT'] :
'';
958 return $this->
exec_SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy, $limit);
960 $table = $queryParts[
'TABLE'];
962 foreach ($queryParts[
'FIELDS'] as $fN => $fV) {
963 $fields[$fN] = $fV[0];
965 $whereClause = isset($queryParts[
'WHERE']) ? $this->SQLparser->compileWhereClause($queryParts[
'WHERE']) :
'1=1';
968 $table = $queryParts[
'TABLE'];
970 if (isset($queryParts[
'VALUES_ONLY']) && is_array($queryParts[
'VALUES_ONLY'])) {
971 $fields =
$GLOBALS[
'TYPO3_DB']->cache_fieldType[$table];
973 foreach ($fields as $fn => $fd) {
974 $values[$fn] = $queryParts[
'VALUES_ONLY'][$fc++][0];
977 foreach ($queryParts[
'FIELDS'] as $fN => $fV) {
978 $values[$fN] = $fV[0];
983 $table = $queryParts[
'TABLE'];
984 $whereClause = isset($queryParts[
'WHERE']) ? $this->SQLparser->compileWhereClause($queryParts[
'WHERE']) :
'1=1';
986 case 'TRUNCATETABLE':
987 $table = $queryParts[
'TABLE'];
1022 public function INSERTquery($table, $fields_values, $no_quote_fields =
false)
1025 if (!is_array($fields_values) || empty($fields_values)) {
1028 foreach ($this->preProcessHookObjects as $hookObject) {
1029 $hookObject->INSERTquery_preProcessAction($table, $fields_values, $no_quote_fields, $this);
1031 if (is_string($no_quote_fields)) {
1032 $no_quote_fields = explode(
',', $no_quote_fields);
1033 }
elseif (!is_array($no_quote_fields)) {
1034 $no_quote_fields = array();
1036 $blobFields = $clobFields = array();
1039 $quoteClob = isset($this->handlerCfg[$handlerKey][
'config'][
'quoteClob']) ? $this->handlerCfg[$handlerKey][
'config'][
'quoteClob'] :
false;
1040 foreach ($fields_values as $k => $v) {
1051 if ($mt[0] ==
'I') {
1053 }
elseif ($mt[0] ==
'F') {
1059 if (!empty($blobFields) || !empty($clobFields)) {
1061 if (!empty($nArr)) {
1065 ', array_keys($nArr)) .
'
1071 if (!empty($blobFields)) {
1072 $query[1] = $blobFields;
1074 if (!empty($clobFields)) {
1075 $query[2] = $clobFields;
1077 if (isset($query[0]) && ($this->debugOutput || $this->store_lastBuiltQuery)) {
1078 $this->debug_lastBuiltQuery = $query[0];
1084 ', array_keys($nArr)) .
'
1089 if ($this->debugOutput || $this->store_lastBuiltQuery) {
1090 $this->debug_lastBuiltQuery = $query;
1107 if ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type'] ===
'native') {
1108 return parent::INSERTmultipleRows($table, $fields, $rows, $no_quote_fields);
1111 foreach ($rows as $row) {
1112 $fields_values = array();
1113 foreach ($fields as $key => $value) {
1114 $fields_values[$value] = $row[$key];
1116 $rowQuery = $this->
INSERTquery($table, $fields_values, $no_quote_fields);
1117 if (is_array($rowQuery)) {
1118 $result[] = $rowQuery;
1120 $result[][0] = $rowQuery;
1137 public function UPDATEquery($table, $where, $fields_values, $no_quote_fields =
false)
1140 if (is_string($where)) {
1141 foreach ($this->preProcessHookObjects as $hookObject) {
1142 $hookObject->UPDATEquery_preProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
1144 $blobFields = $clobFields = array();
1146 if (is_array($fields_values) && !empty($fields_values)) {
1147 if (is_string($no_quote_fields)) {
1148 $no_quote_fields = explode(
',', $no_quote_fields);
1149 }
elseif (!is_array($no_quote_fields)) {
1150 $no_quote_fields = array();
1153 $quoteClob = isset($this->handlerCfg[$handlerKey][
'config'][
'quoteClob']) ? $this->handlerCfg[$handlerKey][
'config'][
'quoteClob'] :
false;
1154 foreach ($fields_values as $k => $v) {
1165 if ($mt[0] ==
'I') {
1167 }
elseif ($mt[0] ==
'F') {
1174 if (!empty($blobFields) || !empty($clobFields)) {
1176 if (!empty($nArr)) {
1180 ', $nArr) . ($where !==
'' ?
'
1184 if (!empty($blobFields)) {
1185 $query[1] = $blobFields;
1187 if (!empty($clobFields)) {
1188 $query[2] = $clobFields;
1191 $this->debug_lastBuiltQuery = $query[0];
1197 ', $nArr) . ($where !==
'' ?
'
1200 if ($this->debugOutput || $this->store_lastBuiltQuery) {
1201 $this->debug_lastBuiltQuery = $query;
1206 throw new \InvalidArgumentException(
'TYPO3 Fatal Error: "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !', 1270853887);
1220 if (is_string($where)) {
1221 foreach ($this->preProcessHookObjects as $hookObject) {
1222 $hookObject->DELETEquery_preProcessAction($table, $where, $this);
1226 $query =
'DELETE FROM ' . $table . ($where !==
'' ?
' WHERE ' . $where :
'');
1227 if ($this->debugOutput || $this->store_lastBuiltQuery) {
1228 $this->debug_lastBuiltQuery = $query;
1232 throw new \InvalidArgumentException(
'TYPO3 Fatal Error: "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !', 1310027383);
1247 public function SELECTquery($select_fields, $from_table, $where_clause, $groupBy =
'', $orderBy =
'', $limit =
'')
1250 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
1255 if ($splitLimit[1]) {
1257 $numrows = $splitLimit[1];
1258 $offset = $splitLimit[0];
1259 $limit = $numrows .
' OFFSET ' . $offset;
1267 $this->dbmsSpecifics->transformQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
1269 $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
1270 if ($this->debugOutput || $this->store_lastBuiltQuery) {
1271 $this->debug_lastBuiltQuery = $query;
1289 if (!empty($params[2])) {
1293 if (!empty($params[3])) {
1297 if (!empty($params[4])) {
1301 list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->
compileSelectParameters($params);
1302 $this->dbmsSpecifics->transformQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
1304 $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
1305 if ($this->debugOutput || $this->store_lastBuiltQuery) {
1306 $this->debug_lastBuiltQuery = $query;
1320 $select_fields = $this->SQLparser->compileFieldList($params[0]);
1321 $from_table = $this->SQLparser->compileFromTables($params[1]);
1322 $where_clause = !empty($params[2]) ? $this->SQLparser->compileWhereClause($params[2]) :
'';
1323 $groupBy = !empty($params[3]) ? $this->SQLparser->compileFieldList($params[3]) :
'';
1324 $orderBy = !empty($params[4]) ? $this->SQLparser->compileFieldList($params[4]) :
'';
1325 return array($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
1336 foreach ($this->preProcessHookObjects as $hookObject) {
1337 $hookObject->TRUNCATEquery_preProcessAction($table, $this);
1341 $query =
'TRUNCATE TABLE ' . $table;
1342 if ($this->debugOutput || $this->store_lastBuiltQuery) {
1343 $this->debug_lastBuiltQuery = $query;
1365 public function prepare_SELECTquery($select_fields, $from_table, $where_clause, $groupBy =
'', $orderBy =
'', $limit =
'', array $input_parameters = array())
1368 $precompiledParts = array();
1369 if ($this->queryCache) {
1370 $cacheKey =
'prepare_SELECTquery-' . \TYPO3\CMS\Dbal\QueryCache::getCacheKey(array(
1371 'selectFields' => $select_fields,
1372 'fromTable' => $from_table,
1373 'whereClause' => $where_clause,
1374 'groupBy' => $groupBy,
1375 'orderBy' => $orderBy,
1378 if ($this->queryCache->has($cacheKey)) {
1379 $precompiledParts = $this->queryCache->get($cacheKey);
1382 'args' => array($from_table, $select_fields, $where_clause, $groupBy, $orderBy, $limit, $input_parameters),
1383 'precompiledParts' => $precompiledParts
1385 $this->
debugHandler(
'prepare_SELECTquery (cache hit)', GeneralUtility::milliseconds() - $pt, $data);
1389 $ORIG_tableName =
'';
1390 if (empty($precompiledParts)) {
1392 $ORIG_tableName = $from_table;
1394 $parsedFromTable = array();
1395 $queryComponents = array();
1396 if ($tableArray = $this->
map_needMapping($ORIG_tableName,
false, $parsedFromTable)) {
1397 $from = $parsedFromTable ? $parsedFromTable : $from_table;
1399 $queryComponents[
'SELECT'] = $components[0];
1400 $queryComponents[
'FROM'] = $components[1];
1401 $queryComponents[
'WHERE'] = $components[2];
1402 $queryComponents[
'GROUPBY'] = $components[3];
1403 $queryComponents[
'ORDERBY'] = $components[4];
1404 $queryComponents[
'parameters'] = $components[5];
1406 $queryComponents = $this->
getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
1408 $queryComponents[
'ORIG_tableName'] = $ORIG_tableName;
1411 $queryComponents[
'SELECT'] = $this->
_quoteFieldNames($queryComponents[
'SELECT']);
1412 $queryComponents[
'FROM'] = $this->
_quoteFromTables($queryComponents[
'FROM']);
1413 $queryComponents[
'WHERE'] = $this->
_quoteWhereClause($queryComponents[
'WHERE']);
1414 $queryComponents[
'GROUPBY'] = $this->
_quoteGroupBy($queryComponents[
'GROUPBY']);
1415 $queryComponents[
'ORDERBY'] = $this->
_quoteOrderBy($queryComponents[
'ORDERBY']);
1418 if ($this->queryCache) {
1420 $this->queryCache->set($cacheKey, $precompiledParts);
1421 }
catch (\TYPO3\CMS\Core\Cache\Exception $e) {
1428 $preparedStatement =
GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\PreparedStatement::class,
'', $from_table, $precompiledParts);
1431 foreach ($input_parameters as $key => $value) {
1432 $preparedStatement->bindValue($key, $value, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_AUTOTYPE);
1436 'args' => array($from_table, $select_fields, $where_clause, $groupBy, $orderBy, $limit, $input_parameters),
1437 'ORIG_from_table' => $ORIG_tableName
1439 $this->
debugHandler(
'prepare_SELECTquery', GeneralUtility::milliseconds() - $pt, $data);
1442 return $preparedStatement;
1457 protected function getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit)
1459 $queryComponents = array(
1466 'parameters' => array()
1469 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
1474 if ($splitLimit[1]) {
1476 $numrows = $splitLimit[1];
1477 $offset = $splitLimit[0];
1478 $limit = $numrows .
' OFFSET ' . $offset;
1481 $queryComponents[
'LIMIT'] = $limit;
1482 $queryComponents[
'SELECT'] = $this->SQLparser->parseFieldList($select_fields);
1483 if ($this->SQLparser->parse_error) {
1484 throw new \InvalidArgumentException($this->SQLparser->parse_error, 1310027408);
1486 $queryComponents[
'FROM'] = $this->SQLparser->parseFromTables($from_table);
1487 $queryComponents[
'WHERE'] = $this->SQLparser->parseWhereClause($where_clause,
'', $queryComponents[
'parameters']);
1488 if (!is_array($queryComponents[
'WHERE'])) {
1489 throw new \InvalidArgumentException(
'Could not parse where clause', 1310027427);
1491 $queryComponents[
'GROUPBY'] = $this->SQLparser->parseFieldList($groupBy);
1492 $queryComponents[
'ORDERBY'] = $this->SQLparser->parseFieldList($orderBy);
1494 return $queryComponents;
1505 $parameterWrap =
'__' . dechex(time()) .
'__';
1506 foreach ($components[
'parameters'] as $key => $params) {
1508 foreach ($params as $index => $param) {
1509 $components[
'parameters'][$key][$index][0] = $parameterWrap . $param[0] . $parameterWrap;
1512 $components[
'parameters'][$key][0] = $parameterWrap . $params[0] . $parameterWrap;
1515 $select_fields = $this->SQLparser->compileFieldList($components[
'SELECT']);
1516 $from_table = $this->SQLparser->compileFromTables($components[
'FROM']);
1517 $where_clause = $this->SQLparser->compileWhereClause($components[
'WHERE']);
1518 $groupBy = $this->SQLparser->compileFieldList($components[
'GROUPBY']);
1519 $orderBy = $this->SQLparser->compileFieldList($components[
'ORDERBY']);
1520 $limit = $components[
'LIMIT'];
1521 $precompiledParts = array();
1523 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
1524 $precompiledParts[
'handler'] = $hType;
1525 $precompiledParts[
'ORIG_tableName'] = $components[
'ORIG_tableName'];
1528 $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
1529 $precompiledParts[
'queryParts'] = explode($parameterWrap, $query);
1532 $this->dbmsSpecifics->transformQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
1533 $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
1534 $precompiledParts[
'queryParts'] = explode($parameterWrap, $query);
1535 $precompiledParts[
'LIMIT'] = $limit;
1538 $precompiledParts[
'queryParts'] = array(
1539 'SELECT' => $select_fields,
1540 'FROM' => $from_table,
1541 'WHERE' => $where_clause,
1542 'GROUPBY' => $groupBy,
1543 'ORDERBY' => $orderBy,
1548 return $precompiledParts;
1564 $preparedStatement = null;
1565 switch ($queryComponents[
'handler']) {
1567 $this->lastQuery = $query;
1568 $preparedStatement = parent::prepare_PREPAREDquery($this->lastQuery, $queryComponents);
1569 $this->resourceIdToTableNameMap[serialize($preparedStatement)] = $queryComponents[
'ORIG_tableName'];
1573 $preparedStatement =
GeneralUtility::makeInstance(\TYPO3\CMS\Dbal\Database\AdodbPreparedStatement::class, $query, $queryComponents, $this);
1574 if (!$preparedStatement->prepare()) {
1575 $preparedStatement =
false;
1579 throw new \RuntimeException(
'prepare_PREPAREDquery is not implemented for userdefined handlers', 1394620167);
1591 if ($this->printErrors && $this->
sql_error()) {
1596 'handlerType' => $queryComponents[
'handler'],
1597 'args' => $queryComponents,
1598 'ORIG_from_table' => $queryComponents[
'ORIG_tableName']
1600 $this->
debugHandler(
'prepare_PREPAREDquery', GeneralUtility::milliseconds() - $pt, $data);
1603 return $preparedStatement;
1634 if ($select_fields ==
'') {
1638 return $select_fields;
1640 $select_fields = $this->SQLparser->parseFieldList($select_fields);
1641 if ($this->SQLparser->parse_error) {
1642 throw new \InvalidArgumentException($this->SQLparser->parse_error, 1310027490);
1645 return $this->SQLparser->compileFieldList($select_fields);
1657 foreach ($select_fields as $k => $v) {
1658 if ($select_fields[$k][
'field'] !=
'' && $select_fields[$k][
'field'] !=
'*' && !is_numeric($select_fields[$k][
'field'])) {
1659 $select_fields[$k][
'field'] = $this->
quoteName($select_fields[$k][
'field']);
1661 if ($select_fields[$k][
'table'] !=
'' && !is_numeric($select_fields[$k][
'table'])) {
1662 $select_fields[$k][
'table'] = $this->
quoteName($select_fields[$k][
'table']);
1664 if ($select_fields[$k][
'as'] !=
'') {
1665 $select_fields[$k][
'as'] = $this->
quoteName($select_fields[$k][
'as']);
1667 if (isset($select_fields[$k][
'func_content.']) && $select_fields[$k][
'func_content.'][0][
'func_content'] !=
'*') {
1668 $select_fields[$k][
'func_content.'][0][
'func_content'] = $this->
quoteFieldNames($select_fields[$k][
'func_content.'][0][
'func_content']);
1669 $select_fields[$k][
'func_content'] = $this->
quoteFieldNames($select_fields[$k][
'func_content']);
1671 if (isset($select_fields[$k][
'flow-control'])) {
1673 if ($select_fields[$k][
'flow-control'][
'type'] ===
'CASE') {
1674 if (isset($select_fields[$k][
'flow-control'][
'case_field'])) {
1675 $select_fields[$k][
'flow-control'][
'case_field'] = $this->
quoteFieldNames($select_fields[$k][
'flow-control'][
'case_field']);
1677 foreach ($select_fields[$k][
'flow-control'][
'when'] as $key => $when) {
1678 $select_fields[$k][
'flow-control'][
'when'][$key][
'when_value'] = $this->
_quoteWhereClause($when[
'when_value']);
1683 return $select_fields;
1694 if ($from_table ===
'') {
1700 $from_table = $this->SQLparser->parseFromTables($from_table);
1702 return $this->SQLparser->compileFromTables($from_table);
1714 foreach ($from_table as $k => $v) {
1715 $from_table[$k][
'table'] = $this->
quoteName($from_table[$k][
'table']);
1716 if ($from_table[$k][
'as'] !=
'') {
1717 $from_table[$k][
'as'] = $this->
quoteName($from_table[$k][
'as']);
1719 if (is_array($v[
'JOIN'])) {
1720 foreach ($v[
'JOIN'] as $joinCnt => $join) {
1721 $from_table[$k][
'JOIN'][$joinCnt][
'withTable'] = $this->
quoteName($join[
'withTable']);
1722 $from_table[$k][
'JOIN'][$joinCnt][
'as'] = $join[
'as'] ? $this->
quoteName($join[
'as']) :
'';
1723 foreach ($from_table[$k][
'JOIN'][$joinCnt][
'ON'] as &$condition) {
1724 $condition[
'left'][
'table'] = $condition[
'left'][
'table'] ? $this->
quoteName($condition[
'left'][
'table']) :
'';
1725 $condition[
'left'][
'field'] = $this->
quoteName($condition[
'left'][
'field']);
1726 $condition[
'right'][
'table'] = $condition[
'right'][
'table'] ? $this->
quoteName($condition[
'right'][
'table']) :
'';
1727 $condition[
'right'][
'field'] = $this->
quoteName($condition[
'right'][
'field']);
1745 return $where_clause;
1747 $where_clause = $this->SQLparser->parseWhereClause($where_clause);
1748 if (is_array($where_clause)) {
1750 $where_clause = $this->SQLparser->compileWhereClause($where_clause);
1752 throw new \InvalidArgumentException(
'Could not parse where clause', 1310027511);
1754 return $where_clause;
1766 foreach ($where_clause as $k => $v) {
1768 if (is_array($where_clause[$k][
'sub'])) {
1770 }
elseif (isset($v[
'func'])) {
1771 switch ($where_clause[$k][
'func'][
'type']) {
1773 $where_clause[$k][
'func'][
'subquery'] = $this->
quoteSELECTsubquery($v[
'func'][
'subquery']);
1777 $pattern = str_replace($where_clause[$k][
'func'][
'str'][1],
'\\' . $where_clause[$k][
'func'][
'str'][1], $where_clause[$k][
'func'][
'str'][0]);
1780 $patternForLike = $this->
escapeStrForLike($pattern, $where_clause[$k][
'func'][
'table']);
1781 $where_clause[$k][
'func'][
'str_like'] = $patternForLike;
1782 if ($where_clause[$k][
'func'][
'table'] !==
'') {
1783 if ($this->dbmsSpecifics->getSpecific(Specifics\AbstractSpecifics::CAST_FIND_IN_SET)) {
1784 $where_clause[$k][
'func'][
'table'] =
'CAST(' . $this->
quoteName($v[
'func'][
'table']);
1786 $where_clause[$k][
'func'][
'table'] = $this->
quoteName($v[
'func'][
'table']);
1789 if ($where_clause[$k][
'func'][
'field'] !==
'') {
1790 if ($this->dbmsSpecifics->getSpecific(Specifics\AbstractSpecifics::CAST_FIND_IN_SET)) {
1791 if($where_clause[$k][
'func'][
'table'] !==
'') {
1792 $where_clause[$k][
'func'][
'field'] = $this->
quoteName($v[
'func'][
'field']) .
' AS CHAR)';
1794 $where_clause[$k][
'func'][
'field'] =
'CAST(' . $this->
quoteName($v[
'func'][
'field']) .
' AS CHAR)';
1797 $where_clause[$k][
'func'][
'field'] = $this->
quoteName($v[
'func'][
'field']);
1804 if ($where_clause[$k][
'func'][
'table'] !=
'') {
1805 $where_clause[$k][
'func'][
'table'] = $this->
quoteName($v[
'func'][
'table']);
1807 if ($where_clause[$k][
'func'][
'field'] !=
'') {
1808 $where_clause[$k][
'func'][
'field'] = $this->
quoteName($v[
'func'][
'field']);
1813 if ($where_clause[$k][
'table'] !=
'') {
1814 $where_clause[$k][
'table'] = $this->
quoteName($where_clause[$k][
'table']);
1816 if (!is_numeric($where_clause[$k][
'field'])) {
1817 $where_clause[$k][
'field'] = $this->
quoteName($where_clause[$k][
'field']);
1819 if (isset($where_clause[$k][
'calc_table'])) {
1820 if ($where_clause[$k][
'calc_table'] !=
'') {
1821 $where_clause[$k][
'calc_table'] = $this->
quoteName($where_clause[$k][
'calc_table']);
1823 if ($where_clause[$k][
'calc_field'] !=
'') {
1824 $where_clause[$k][
'calc_field'] = $this->
quoteName($where_clause[$k][
'calc_field']);
1828 if ($where_clause[$k][
'comparator']) {
1829 if (isset($v[
'value'][
'operator'])) {
1830 foreach ($where_clause[$k][
'value'][
'args'] as $argK => $fieldDef) {
1831 $where_clause[$k][
'value'][
'args'][$argK][
'table'] = $this->
quoteName($fieldDef[
'table']);
1832 $where_clause[$k][
'value'][
'args'][$argK][
'field'] = $this->
quoteName($fieldDef[
'field']);
1836 if (
GeneralUtility::inList(
'NOTIN,IN', strtoupper(str_replace(array(
' ', LF, CR, TAB),
'', $where_clause[$k][
'comparator'])))) {
1837 if (isset($v[
'subquery'])) {
1842 (!isset($where_clause[$k][
'value'][1]) || $where_clause[$k][
'value'][1] ==
'')
1843 && is_string($where_clause[$k][
'value'][0]) && strstr($where_clause[$k][
'value'][0],
'.')
1845 $where_clause[$k][
'value'][0] = $this->
quoteFieldNames($where_clause[$k][
'value'][0]);
1847 $where_clause[$k][
'value'][0] = substr($this->handlerInstance[$this->lastHandlerKey]->qstr($where_clause[$k][
'value'][0]), 1, -1);
1853 return $where_clause;
1865 if ($groupBy ===
'') {
1871 $groupBy = $this->SQLparser->parseFieldList($groupBy);
1873 return $this->SQLparser->compileFieldList($groupBy);
1885 foreach ($groupBy as $k => $v) {
1886 $groupBy[$k][
'field'] = $this->
quoteName($groupBy[$k][
'field']);
1887 if ($groupBy[$k][
'table'] !=
'') {
1888 $groupBy[$k][
'table'] = $this->
quoteName($groupBy[$k][
'table']);
1903 if ($orderBy ===
'') {
1909 $orderBy = $this->SQLparser->parseFieldList($orderBy);
1911 return $this->SQLparser->compileFieldList($orderBy);
1923 foreach ($orderBy as $k => $v) {
1924 if ($orderBy[$k][
'table'] ===
'' && $v[
'field'] !==
'' && ctype_digit($v[
'field'])) {
1927 $orderBy[$k][
'field'] = $this->
quoteName($orderBy[$k][
'field']);
1928 if ($orderBy[$k][
'table'] !==
'') {
1929 $orderBy[$k][
'table'] = $this->
quoteName($orderBy[$k][
'table']);
1951 if ($allowNull && $str === null) {
1954 return '\'' . $this->
quoteStr($str, $table) .
'\'';
1971 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
1973 if ($this->handlerInstance[$this->lastHandlerKey][
'link']) {
1980 $str = str_replace(
'\'',
'\\\'', $str);
1987 $str = substr($this->handlerInstance[$this->lastHandlerKey]->qstr($str), 1, -1);
1993 throw new \RuntimeException(
'No handler found!!!', 1310027655);
2006 public function quoteName($name, $handlerKey = null, $useBackticks =
false)
2009 $useNameQuote = isset($this->handlerCfg[$handlerKey][
'config'][
'useNameQuote']) ? $this->handlerCfg[$handlerKey][
'config'][
'useNameQuote'] :
false;
2010 if ($useNameQuote) {
2012 if (!is_object($this->handlerInstance[$handlerKey]->DataDictionary)) {
2013 $this->handlerInstance[$handlerKey]->DataDictionary = NewDataDictionary($this->handlerInstance[$handlerKey]);
2015 return $this->handlerInstance[$handlerKey]->DataDictionary->NameQuote($name);
2017 $quote = $useBackticks ?
'`' : $this->handlerInstance[$handlerKey]->nameQuote;
2018 return $quote . $name . $quote;
2032 public function MetaType($type, $table, $maxLength = -1)
2035 return $this->
getMetadata($type, $table,
'dummyFieldToBypassCache', $maxLength);
2052 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
2057 if (!empty($this->cache_fieldType[$table][$field])) {
2058 $str = $this->cache_fieldType[$table][$field][
'metaType'];
2061 $str = $rs->MetaType($type, $maxLength);
2068 throw new \RuntimeException(
'No handler found!!!', 1310027685);
2083 return $this->dbmsSpecifics->getMetaFieldType($t);
2096 return $this->dbmsSpecifics->getNativeFieldType($meta);
2108 if ($table ===
'tx_dbal_debuglog') {
2112 if (isset($fieldValues[$this->cache_autoIncFields[$table]])) {
2113 $newId = $fieldValues[$this->cache_autoIncFields[$table]];
2114 }
elseif ($this->handlerInstance[$this->lastHandlerKey]->hasInsertID && !empty($this->cache_autoIncFields[$table])) {
2116 $newId = $this->handlerInstance[
$this->lastHandlerKey]->Insert_ID($table, $this->cache_autoIncFields[$table]);
2118 if ($newId !== null) {
2138 if ($this->dbmsSpecifics->specificExists(Specifics\AbstractSpecifics::PARTIAL_STRING_INDEX) && (bool)$this->dbmsSpecifics->getSpecific(Specifics\AbstractSpecifics::PARTIAL_STRING_INDEX)) {
2142 $strippedIndexSQL = preg_replace_callback(
2143 '/\A([^(]+)\((.*)\)\Z/',
2144 function ($matches) {
2145 return $matches[1] .
'(' . preg_replace(
'/\((\d+)\)/',
'', $matches[2]) .
')';
2150 return $strippedIndexSQL === null ? $indexSQL : $strippedIndexSQL;
2162 if (!preg_match(
'/^([a-z0-9]+)(\(([^\)]+)\))?(.*)/', $fieldSQL, $components)) {
2166 $metaType = $this->dbmsSpecifics->getMetaFieldType($components[1]);
2167 $replacementType = $this->dbmsSpecifics->getNativeFieldType($metaType);
2168 $replacementLength = $components[2];
2169 $replacementExtra =
'';
2174 if (substr($metaType, 0, 1) ===
'I') {
2175 $replacementLength = $this->dbmsSpecifics->getNativeFieldLength($replacementType, $components[3]);
2181 if ($components[1] ===
'tinytext') {
2182 $replacementLength =
'(255)';
2183 if (
false !== stripos($components[0],
' NOT NULL')) {
2184 $replacementExtra =
' default \'\'';
2186 $replacementExtra =
' default NULL';
2190 return str_replace($components[1] . $components[2], strtolower($replacementType) . $replacementLength, $components[0]) . $replacementExtra;
2207 switch ($this->handlerCfg[$this->lastHandlerKey][
'type']) {
2229 switch ($this->handlerCfg[$this->lastHandlerKey][
'type']) {
2251 if ($res ===
false) {
2256 switch ($handlerType) {
2258 $output = $res->num_rows;
2261 $output = method_exists($res,
'RecordCount') ? $res->RecordCount() : 0;
2264 $output = $res->sql_num_rows();
2283 $output = $res->fetch_assoc();
2284 $key = serialize($res);
2285 $tableList = $this->resourceIdToTableNameMap[$key];
2286 unset($this->resourceIdToTableNameMap[$key]);
2293 if (method_exists($res,
'FetchRow')) {
2294 $output = $res->FetchRow();
2295 $tableList = $res->TYPO3_DBAL_tableList;
2301 if (is_array($output)) {
2304 foreach ($output as $key => $value) {
2305 if ($value ===
' ') {
2310 foreach ($output as $key => $value) {
2311 if (is_integer($key)) {
2312 unset($output[$key]);
2320 $output = $res->sql_fetch_assoc();
2321 $tableList = $res->TYPO3_DBAL_tableList;
2326 if (is_array($output)) {
2331 if ($output === null) {
2352 $output = $res->fetch_row();
2353 if ($output === null) {
2362 if (method_exists($res,
'FetchRow')) {
2363 $output = $res->FetchRow();
2368 if (is_array($output)) {
2370 foreach ($output as $key => $value) {
2371 unset($output[$key]);
2373 $output[$keyIndex] = $value;
2374 if ($value ===
' ') {
2376 $output[$keyIndex] =
'';
2385 $output = $res->sql_fetch_row();
2388 if ($output === null) {
2404 if ($res ===
false) {
2413 if (method_exists($res,
'Close')) {
2436 if (is_object($res) && !$res instanceof \mysqli_result) {
2437 $handlerType = $res->TYPO3_DBAL_handlerType;
2438 }
elseif ($res instanceof \mysqli_result) {
2439 $handlerType =
'native';
2441 $handlerType =
false;
2443 return $handlerType;
2454 switch ($this->handlerCfg[$this->lastHandlerKey][
'type']) {
2476 switch ($this->handlerCfg[$this->lastHandlerKey][
'type']) {
2502 $output = $res->data_seek($seek);
2505 $output = $res->Move($seek);
2508 $output = $res->sql_data_seek($seek);
2526 foreach ($this->mapping as $tableName => $tableMapInfo) {
2527 if (isset($tableMapInfo[
'mapFieldNames'])) {
2528 foreach ($tableMapInfo[
'mapFieldNames'] as $fieldName => $fieldMapInfo) {
2529 if ($fieldMapInfo === $field) {
2531 $field = $fieldName;
2536 return $this->cache_fieldType[$table][$field][
'metaType'];
2549 if ($res === null) {
2550 debug(array(
'no res in sql_field_type!'));
2552 }
elseif (is_string($res)) {
2553 if ($res ===
'tx_dbal_debuglog') {
2556 $handlerType =
'adodb';
2561 switch ($handlerType) {
2563 $metaInfo = $res->fetch_field_direct($pointer);
2565 $output = $this->mysqlDataTypeMapping[$metaInfo->type];
2571 if (is_string($pointer)) {
2572 $output = $this->cache_fieldType[$res][$pointer][
'type'];
2576 $output = $res->sql_field_type($pointer);
2606 $globalConfig = unserialize(
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXT'][
'extConf'][
'dbal']);
2607 if ($globalConfig[
'sql_query.'][
'passthrough']) {
2608 return parent::sql_query($query);
2611 $queryParts = $this->SQLparser->parseSQL($query);
2612 if (is_array($queryParts) &&
GeneralUtility::inList(
'SELECT,UPDATE,INSERT,DELETE', $queryParts[
'type'])) {
2616 switch ($this->handlerCfg[
'_DEFAULT'][
'type']) {
2621 $sqlResult = $this->handlerInstance[
'_DEFAULT'][
'link']->query($query);
2624 $sqlResult = $this->handlerInstance[
'_DEFAULT']->Execute($query);
2625 $sqlResult->TYPO3_DBAL_handlerType =
'adodb';
2628 $sqlResult = $this->handlerInstance[
'_DEFAULT']->sql_query($query);
2629 $sqlResult->TYPO3_DBAL_handlerType =
'userdefined';
2632 $this->lastHandlerKey =
'_DEFAULT';
2633 if ($this->printErrors && $this->
sql_error()) {
2658 if ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type'] ===
'native') {
2662 GeneralUtility::sysLog(
2689 $this->lastHandlerKey =
'_DEFAULT';
2690 switch ($this->handlerCfg[
'_DEFAULT'][
'type']) {
2693 $db_list = $this->
query(
"SELECT SCHEMA_NAME FROM information_schema.SCHEMATA");
2695 while ($row = $db_list->fetch_object()) {
2698 $dbArr[] = $row->SCHEMA_NAME;
2707 if (method_exists($this->handlerInstance[
'_DEFAULT'],
'MetaDatabases')) {
2708 $sqlDBs = $this->handlerInstance[
'_DEFAULT']->MetaDatabases();
2709 if (is_array($sqlDBs)) {
2710 foreach ($sqlDBs as $k => $theDB) {
2717 $dbArr = $this->handlerInstance[
'_DEFAULT']->admin_get_tables();
2732 $whichTables = array();
2734 switch ($this->handlerCfg[
'_DEFAULT'][
'type']) {
2736 $tables_result = $this->
query(
'SHOW TABLE STATUS FROM `' . TYPO3_db .
'`');
2739 $whichTables[$theTable[
'Name']] = $theTable;
2742 $tables_result->free();
2747 if (method_exists($this->handlerInstance[
'_DEFAULT'],
'MetaTables')) {
2748 $sqlTables = $this->handlerInstance[
'_DEFAULT']->MetaTables(
'TABLES');
2749 foreach ($sqlTables as $k => $theTable) {
2750 if (preg_match(
'/BIN\\$/', $theTable)) {
2754 $whichTables[$theTable] = array(
'Name' => $theTable);
2759 $whichTables = $this->handlerInstance[
'_DEFAULT']->admin_get_tables();
2763 if (is_array($this->mapping) && !empty($this->mapping)) {
2766 foreach ($this->mapping as $tN => $tMapInfo) {
2767 if (isset($tMapInfo[
'mapTableName'])) {
2768 $tMap[$tMapInfo[
'mapTableName']] = $tN;
2773 foreach ($whichTables as $tN => $tDefinition) {
2774 if (isset($tMap[$tN])) {
2776 $tDefinition = array(
'Name' => $tN);
2778 $newList[$tN] = $tDefinition;
2780 $whichTables = $newList;
2783 if (is_array($this->table2handlerKeys)) {
2784 foreach ($this->table2handlerKeys as $key => $handlerKey) {
2785 $whichTables[$key] = array(
'Name' => $key);
2788 return $whichTables;
2806 $ORIG_tableName = $tableName;
2809 if ($this->mapping[$tableName][
'mapTableName']) {
2810 $tableName = $this->mapping[$tableName][
'mapTableName'];
2815 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
2818 $columns_res = $this->
query(
'SHOW columns FROM ' . $tableName);
2819 while ($fieldRow = $columns_res->fetch_assoc()) {
2820 $output[$fieldRow[
'Field']] = $fieldRow;
2822 $columns_res->free();
2826 if (is_array($fieldRows)) {
2827 foreach ($fieldRows as $k => $fieldRow) {
2828 settype($fieldRow,
'array');
2829 $metaType = $this->
getMetadata($fieldRow[
'type'], $tableName, $fieldRow[
'name']);
2830 $output[$fieldRow[
'name']] = $this->dbmsSpecifics->transformFieldRowToMySQL($fieldRow, $metaType);
2839 if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName][
'mapFieldNames'])) {
2840 $revFields = array_flip($this->mapping[$ORIG_tableName][
'mapFieldNames']);
2841 $newOutput = array();
2842 foreach ($output as $fN => $fInfo) {
2843 if (isset($revFields[$fN])) {
2844 $fN = $revFields[$fN];
2845 $fInfo[
'Field'] = $fN;
2847 $newOutput[$fN] = $fInfo;
2849 $output = $newOutput;
2865 $ORIG_tableName = $tableName;
2868 if ($this->mapping[$tableName][
'mapTableName']) {
2869 $tableName = $this->mapping[$tableName][
'mapTableName'];
2874 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
2877 $keyRes = $this->
query(
'SHOW keys FROM ' . $tableName);
2878 while ($keyRow = $keyRes->fetch_assoc()) {
2879 $output[] = $keyRow;
2885 if ($keyRows !==
false) {
2886 foreach ($keyRows as $k => $theKey) {
2887 $theKey[
'Table'] = $tableName;
2888 $theKey[
'Non_unique'] = (int)(!$theKey[
'unique']);
2889 $theKey[
'Key_name'] = str_replace(hash(
'crc32b', $tableName) .
'_',
'', $k);
2891 $theKey[
'Collation'] =
'';
2892 $theKey[
'Cardinality'] =
'';
2893 $theKey[
'Sub_part'] =
'';
2894 $theKey[
'Packed'] =
'';
2895 $theKey[
'Null'] =
'';
2896 $theKey[
'Index_type'] =
'';
2897 $theKey[
'Comment'] =
'';
2899 $keycols = $theKey[
'columns'];
2900 foreach ($keycols as $c => $theCol) {
2901 $theKey[
'Seq_in_index'] = $c + 1;
2902 $theKey[
'Column_name'] = $theCol;
2903 $output[] = $theKey;
2909 $theKey[
'Table'] = $tableName;
2910 $theKey[
'Non_unique'] = 0;
2911 $theKey[
'Key_name'] =
'PRIMARY';
2913 $theKey[
'Collation'] =
'';
2914 $theKey[
'Cardinality'] =
'';
2915 $theKey[
'Sub_part'] =
'';
2916 $theKey[
'Packed'] =
'';
2917 $theKey[
'Null'] =
'';
2918 $theKey[
'Index_type'] =
'';
2919 $theKey[
'Comment'] =
'';
2921 if ($priKeyRow !==
false) {
2922 foreach ($priKeyRow as $c => $theCol) {
2923 $theKey[
'Seq_in_index'] = $c + 1;
2924 $theKey[
'Column_name'] = $theCol;
2925 $output[] = $theKey;
2934 if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName][
'mapFieldNames'])) {
2935 $revFields = array_flip($this->mapping[$ORIG_tableName][
'mapFieldNames']);
2936 $newOutput = array();
2937 foreach ($output as $kN => $kInfo) {
2939 $kInfo[
'Table'] = $ORIG_tableName;
2941 if (isset($revFields[$kInfo[
'Column_name']])) {
2942 $kInfo[
'Column_name'] = $revFields[$kInfo[
'Column_name']];
2945 $newOutput[$kN] = $kInfo;
2947 $output = $newOutput;
2967 if ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type'] ===
'native') {
2969 $columns_res = $this->
query(
'SHOW CHARACTER SET');
2970 if ($columns_res !==
false) {
2971 while ($row = $columns_res->fetch_assoc()) {
2972 $output[$row[
'Charset']] = $row;
2974 $columns_res->free();
2989 $parsedQuery = $this->SQLparser->parseSQL($query);
2990 if (!is_array($parsedQuery)) {
2991 throw new \InvalidArgumentException(
'ERROR: Query could not be parsed: "' . htmlspecialchars($parsedQuery) .
'". Query: "' . htmlspecialchars($query) .
'"', 1310027793);
2993 $ORIG_table = $parsedQuery[
'TABLE'];
2995 switch ($parsedQuery[
'type']) {
2998 $this->createMappingsIfRequired($parsedQuery);
3006 case 'TRUNCATETABLE':
3009 case 'CREATEDATABASE':
3010 throw new \InvalidArgumentException(
'Creating a database with DBAL is not supported. Did you really read the manual?', 1310027716);
3013 throw new \InvalidArgumentException(
'ERROR: Invalid Query type (' . $parsedQuery[
'type'] .
') for ->admin_query() function!: "' . htmlspecialchars($query) .
'"', 1310027740);
3016 $this->lastParsedAndMappedQueryArray = $parsedQuery;
3020 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
3023 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
3024 if (in_array($this->lastParsedAndMappedQueryArray[
'type'], array(
'INSERT',
'DROPTABLE',
'ALTERTABLE'))) {
3025 $result = $this->
query($compiledQuery);
3027 $result = $this->
query($compiledQuery[0]);
3032 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
3033 switch ($this->lastParsedAndMappedQueryArray[
'type']) {
3035 $result = $this->
exec_INSERTquery($this->lastParsedAndMappedQueryArray[
'TABLE'], $compiledQuery);
3037 case 'TRUNCATETABLE':
3041 $result = $this->handlerInstance[
$this->lastHandlerKey]->DataDictionary->ExecuteSQLArray($compiledQuery);
3046 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
3070 if (!isset($this->cache_handlerKeyFromTableList[$key])) {
3072 $_tableList = $tableList;
3073 $tableArray = $this->SQLparser->parseFromTables($_tableList);
3075 if (is_array($tableArray) && !empty($tableArray)) {
3076 $outputHandlerKey =
'';
3077 foreach ($tableArray as $vArray) {
3079 $handlerKey = $this->table2handlerKeys[$vArray[
'table']] ? $this->table2handlerKeys[$vArray[
'table']] :
'_DEFAULT';
3081 if ($outputHandlerKey && $handlerKey != $outputHandlerKey) {
3082 throw new \RuntimeException(
'DBAL fatal error: Tables in this list "' . $tableList .
'" didn\'t use the same DB handler!', 1310027833);
3084 $outputHandlerKey = $handlerKey;
3087 if (!isset($this->handlerInstance[$outputHandlerKey])) {
3091 $this->cache_handlerKeyFromTableList[$key] = $outputHandlerKey;
3093 throw new \RuntimeException(
'DBAL fatal error: No handler found in handler_getFromTableList() for: "' . $tableList .
'" (' . $tableArray .
')', 1310027933);
3096 return $this->cache_handlerKeyFromTableList[$key];
3109 if (!isset($this->handlerCfg[$handlerKey]) || !is_array($this->handlerCfg[$handlerKey])) {
3110 throw new \RuntimeException(
'ERROR: No handler for key "' . $handlerKey .
'"', 1310028018);
3112 if ($handlerKey ===
'_DEFAULT') {
3117 $this->handlerCfg[$handlerKey][
'config'][
'port'] = (int)$this->databasePort;
3120 $cfgArray = $this->handlerCfg[$handlerKey];
3121 if (!$cfgArray[
'config'][
'database']) {
3127 switch ((
string)$cfgArray[
'type']) {
3129 $host = $cfgArray[
'config'][
'host'];
3130 if (!
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'no_pconnect']) {
3131 $host =
'p:' . $host;
3133 $link = mysqli_init();
3134 $connected =
$link->real_connect(
3136 $cfgArray[
'config'][
'username'],
3137 $cfgArray[
'config'][
'password'],
3138 $cfgArray[
'config'][
'database'],
3139 isset($cfgArray[
'config'][
'port']) ? $cfgArray[
'config'][
'port'] :
''
3143 $this->handlerInstance[$handlerKey] = array(
'handlerType' =>
'native',
'link' =>
$link);
3145 if (
$link->set_charset($this->connectionCharset) ===
false) {
3146 GeneralUtility::sysLog(
3147 'Error setting connection charset to "' . $this->connectionCharset .
'"',
3154 if ($handlerKey ===
'_DEFAULT') {
3155 $this->link =
$link;
3157 $this->lastHandlerKey = $handlerKey;
3158 foreach ($this->initializeCommandsAfterConnect as $command) {
3159 if ($this->
query($command) ===
false) {
3160 GeneralUtility::sysLog(
3161 'Could not initialize DB connection with query "' . $command .
'": ' . $this->
sql_error(),
3172 GeneralUtility::sysLog(
'Could not connect to MySQL server ' . $cfgArray[
'config'][
'host'] .
' with user ' . $cfgArray[
'config'][
'username'] .
'.',
'core',
GeneralUtility::SYSLOG_SEVERITY_FATAL);
3177 require_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath(
'adodb') .
'adodb/adodb.inc.php';
3178 if (!defined(
'ADODB_FORCE_NULLS')) {
3179 define(
'ADODB_FORCE_NULLS', 1);
3181 $GLOBALS[
'ADODB_FORCE_TYPE'] = ADODB_FORCE_VALUE;
3182 $GLOBALS[
'ADODB_FETCH_MODE'] = ADODB_FETCH_BOTH;
3183 $this->handlerInstance[$handlerKey] = ADONewConnection($cfgArray[
'config'][
'driver']);
3185 if (isset($cfgArray[
'config'][
'driverOptions'])) {
3186 foreach ($cfgArray[
'config'][
'driverOptions'] as $optionName => $optionValue) {
3187 $optionSetterName =
'set' . ucfirst($optionName);
3188 if (method_exists($this->handlerInstance[$handlerKey], $optionSetterName)) {
3189 $this->handlerInstance[$handlerKey]->{$optionSetterName}($optionValue);
3191 $this->handlerInstance[$handlerKey]->{$optionName} = $optionValue;
3195 if (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'no_pconnect']) {
3196 $this->handlerInstance[$handlerKey]->Connect($cfgArray[
'config'][
'host'] . (isset($cfgArray[
'config'][
'port']) ?
':' . $cfgArray[
'config'][
'port'] :
''), $cfgArray[
'config'][
'username'], $cfgArray[
'config'][
'password'], $cfgArray[
'config'][
'database']);
3198 $this->handlerInstance[$handlerKey]->PConnect($cfgArray[
'config'][
'host'] . (isset($cfgArray[
'config'][
'port']) ?
':' . $cfgArray[
'config'][
'port'] :
''), $cfgArray[
'config'][
'username'], $cfgArray[
'config'][
'password'], $cfgArray[
'config'][
'database']);
3200 if (!$this->handlerInstance[$handlerKey]->
isConnected()) {
3201 $dsn = $cfgArray[
'config'][
'driver'] .
'://' . $cfgArray[
'config'][
'username'] . ((string)$cfgArray[
'config'][
'password'] !==
'' ?
':XXXX@' :
'') . $cfgArray[
'config'][
'host'] . (isset($cfgArray[
'config'][
'port']) ?
':' . $cfgArray[
'config'][
'port'] :
'') .
'/' . $cfgArray[
'config'][
'database'] . (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'no_pconnect'] ?
'' :
'?persistent=1');
3202 GeneralUtility::sysLog(
'Could not connect to DB server using ADOdb on ' . $cfgArray[
'config'][
'host'] .
' with user ' . $cfgArray[
'config'][
'username'] .
'.',
'core',
GeneralUtility::SYSLOG_SEVERITY_FATAL);
3203 error_log(
'DBAL error: Connection to ' . $dsn .
' failed. Maybe PHP doesn\'t support the database?');
3206 $this->handlerInstance[$handlerKey]->DataDictionary = NewDataDictionary($this->handlerInstance[$handlerKey]);
3207 $this->handlerInstance[$handlerKey]->last_insert_id = 0;
3208 if (isset($cfgArray[
'config'][
'sequenceStart'])) {
3209 $this->handlerInstance[$handlerKey]->sequenceStart = $cfgArray[
'config'][
'sequenceStart'];
3211 $this->handlerInstance[$handlerKey]->sequenceStart = 1;
3217 if (isset($cfgArray[
'config'][
'classFile'])) {
3218 GeneralUtility::deprecationLog(
'The DBAL handler option "config.classFile" is deprecated since TYPO3 CMS 7, and will be removed with CMS 8. Make use of autoloading instead.');
3221 if (@is_file($fileName)) {
3222 require_once $fileName;
3224 throw new \RuntimeException(
'DBAL error: "' . $fileName .
'" was not a file to include.', 1310027975);
3229 $this->handlerInstance[$handlerKey]->init($cfgArray, $this);
3230 if (is_object($this->handlerInstance[$handlerKey])) {
3235 throw new \RuntimeException(
'ERROR: Invalid handler type: "' . $cfgArray[
'type'] .
'"', 1310027995);
3245 public function isConnected()
3248 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
3250 $result = isset($this->handlerCfg[$this->lastHandlerKey][
'link']);
3255 $result = is_object($this->handlerInstance[$this->lastHandlerKey]) && $this->handlerInstance[$this->lastHandlerKey]->isConnected();
3266 public function runningNative()
3268 return (
string)$this->handlerCfg[$this->lastHandlerKey][
'type'] ===
'native';
3277 public function runningADOdbDriver($driver)
3279 return strpos($this->handlerCfg[$this->lastHandlerKey][
'config'][
'driver'], $driver) !==
false;
3287 public function getServerVersion()
3290 switch ((
string)$this->handlerCfg[$this->lastHandlerKey][
'type']) {
3292 $result = $this->handlerInstance[$this->lastHandlerKey][
'link']->server_info;
3296 if (is_object($this->handlerInstance[$this->lastHandlerKey])) {
3297 $serverInfo = $this->handlerInstance[$this->lastHandlerKey]->ServerInfo();
3298 $result = $serverInfo[
'version'];
3318 protected function map_needMapping($tableList, $fieldMappingOnly =
false, array &$parsedTableList = array())
3320 $key = $tableList .
'|' . $fieldMappingOnly;
3321 if (!isset($this->cache_mappingFromTableList[$key])) {
3322 $this->cache_mappingFromTableList[$key] =
false;
3324 $tables = $this->SQLparser->parseFromTables($tableList);
3325 if (is_array($tables)) {
3326 $parsedTableList = $tables;
3327 foreach ($tables as $tableCfg) {
3328 if ($fieldMappingOnly) {
3329 if (is_array($this->mapping[$tableCfg[
'table']][
'mapFieldNames'])) {
3330 $this->cache_mappingFromTableList[$key] = $tables;
3331 }
elseif (is_array($tableCfg[
'JOIN'])) {
3332 foreach ($tableCfg[
'JOIN'] as $join) {
3333 if (is_array($this->mapping[$join[
'withTable']][
'mapFieldNames'])) {
3334 $this->cache_mappingFromTableList[$key] = $tables;
3340 if (is_array($this->mapping[$tableCfg[
'table']])) {
3341 $this->cache_mappingFromTableList[$key] = $tables;
3342 }
elseif (is_array($tableCfg[
'JOIN'])) {
3343 foreach ($tableCfg[
'JOIN'] as $join) {
3344 if (is_array($this->mapping[$join[
'withTable']])) {
3345 $this->cache_mappingFromTableList[$key] = $tables;
3354 return $this->cache_mappingFromTableList[$key];
3368 protected function map_assocArray($input, $tables, $rev =
false)
3371 foreach ($tables as $tableCfg) {
3372 $tableKey = $this->getMappingKey($tableCfg[
'table']);
3373 if (is_array($this->mapping[$tableKey][
'mapFieldNames'])) {
3376 $theMap = array_flip($this->mapping[$tableKey][
'mapFieldNames']);
3378 $theMap = $this->mapping[$tableKey][
'mapFieldNames'];
3382 foreach ($input as $fN => $value) {
3385 $newKey = $theMap[$fN];
3390 $output[$newKey] = $value;
3411 protected function map_remapSELECTQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy)
3414 $backupMapping = $this->mapping;
3416 $tables = is_array($from_table) ? $from_table : $this->SQLparser->parseFromTables($from_table);
3417 $defaultTable = $tables[0][
'table'];
3421 foreach ($tables as $k => $v) {
3422 if ($v[
'as'] && is_array($this->mapping[$v[
'table']][
'mapFieldNames'])) {
3423 $mappingKey = $this->getFreeMappingKey($v[
'as']);
3424 $this->mapping[$mappingKey][
'mapFieldNames'] =& $this->mapping[$v[
'table']][
'mapFieldNames'];
3426 if (is_array($v[
'JOIN'])) {
3427 foreach ($v[
'JOIN'] as $joinCnt => $join) {
3428 if ($join[
'as'] && is_array($this->mapping[$join[
'withTable']][
'mapFieldNames'])) {
3429 $mappingKey = $this->getFreeMappingKey($join[
'as']);
3430 $this->mapping[$mappingKey][
'mapFieldNames'] =& $this->mapping[$join[
'withTable']][
'mapFieldNames'];
3435 foreach ($tables as $k => $v) {
3436 $tableKey = $this->getMappingKey($v[
'table']);
3437 if ($this->mapping[$tableKey][
'mapTableName']) {
3438 $tables[$k][
'table'] = $this->mapping[$tableKey][
'mapTableName'];
3441 if (is_array($v[
'JOIN'])) {
3442 foreach ($v[
'JOIN'] as $joinCnt => $join) {
3444 $withTableKey = $this->getMappingKey($join[
'withTable']);
3445 if ($this->mapping[$withTableKey][
'mapTableName']) {
3446 $tables[$k][
'JOIN'][$joinCnt][
'withTable'] = $this->mapping[$withTableKey][
'mapTableName'];
3448 $onPartsArray = array();
3450 if (is_array($tables[$k][
'JOIN'][$joinCnt][
'ON'])) {
3451 foreach ($tables[$k][
'JOIN'][$joinCnt][
'ON'] as &$condition) {
3453 $leftTableKey = $this->getMappingKey($condition[
'left'][
'table']);
3454 if (isset($this->mapping[$leftTableKey][
'mapFieldNames'][$condition[
'left'][
'field']])) {
3455 $condition[
'left'][
'field'] = $this->mapping[$leftTableKey][
'mapFieldNames'][$condition[
'left'][
'field']];
3457 if (isset($this->mapping[$leftTableKey][
'mapTableName'])) {
3458 $condition[
'left'][
'table'] = $this->mapping[$leftTableKey][
'mapTableName'];
3461 $rightTableKey = $this->getMappingKey($condition[
'right'][
'table']);
3462 if (isset($this->mapping[$rightTableKey][
'mapFieldNames'][$condition[
'right'][
'field']])) {
3463 $condition[
'right'][
'field'] = $this->mapping[$rightTableKey][
'mapFieldNames'][$condition[
'right'][
'field']];
3465 if (isset($this->mapping[$rightTableKey][
'mapTableName'])) {
3466 $condition[
'right'][
'table'] = $this->mapping[$rightTableKey][
'mapTableName'];
3473 $fromParts = $tables;
3475 $parameterReferences = array();
3476 $whereParts = $this->SQLparser->parseWhereClause($where_clause,
'', $parameterReferences);
3477 $this->map_sqlParts($whereParts, $defaultTable);
3479 $selectParts = $this->SQLparser->parseFieldList($select_fields);
3480 $this->map_sqlParts($selectParts, $defaultTable);
3482 $groupByParts = $this->SQLparser->parseFieldList($groupBy);
3483 $this->map_sqlParts($groupByParts, $defaultTable);
3485 $orderByParts = $this->SQLparser->parseFieldList($orderBy);
3486 $this->map_sqlParts($orderByParts, $defaultTable);
3488 $this->mapping = $backupMapping;
3489 return array($selectParts, $fromParts, $whereParts, $groupByParts, $orderByParts, $parameterReferences);
3499 protected function getMappingKey($tableName)
3502 while (isset($this->mapping[
'*' . $tableName])) {
3503 $tableName =
'*' . $tableName;
3514 protected function getFreeMappingKey($tableName)
3516 while (isset($this->mapping[$tableName])) {
3517 $tableName =
'*' . $tableName;
3530 protected function map_sqlParts(&$sqlPartArray, $defaultTable)
3532 $defaultTableKey = $this->getMappingKey($defaultTable);
3534 if (is_array($sqlPartArray)) {
3535 foreach ($sqlPartArray as $k => $v) {
3536 if (isset($sqlPartArray[$k][
'type'])) {
3537 switch ($sqlPartArray[$k][
'type']) {
3538 case 'flow-control':
3539 $temp = array($sqlPartArray[$k][
'flow-control']);
3540 $this->map_sqlParts($temp, $defaultTable);
3542 $sqlPartArray[$k][
'flow-control'] = $temp[0];
3545 if (isset($sqlPartArray[$k][
'case_field'])) {
3546 $fieldArray = explode(
'.', $sqlPartArray[$k][
'case_field']);
3547 $fieldArrayCount = count($fieldArray);
3548 if ($fieldArrayCount === 1 && is_array($this->mapping[$defaultTableKey][
'mapFieldNames']) && isset($this->mapping[$defaultTableKey][
'mapFieldNames'][$fieldArray[0]])) {
3549 $sqlPartArray[$k][
'case_field'] = $this->mapping[$defaultTableKey][
'mapFieldNames'][$fieldArray[0]];
3550 }
elseif ($fieldArrayCount === 2) {
3552 $table = $fieldArray[0];
3553 $tableKey = $this->getMappingKey($table);
3554 if (isset($this->mapping[$tableKey][
'mapTableName'])) {
3555 $table = $this->mapping[$tableKey][
'mapTableName'];
3558 $field = $fieldArray[1];
3559 if (is_array($this->mapping[$tableKey][
'mapFieldNames']) && isset($this->mapping[$tableKey][
'mapFieldNames'][$fieldArray[1]])) {
3560 $field = $this->mapping[$tableKey][
'mapFieldNames'][$fieldArray[1]];
3562 $sqlPartArray[$k][
'case_field'] = $table .
'.' . $field;
3565 foreach ($sqlPartArray[$k][
'when'] as $key => $when) {
3566 $this->map_sqlParts($sqlPartArray[$k][
'when'][$key][
'when_value'], $defaultTable);
3572 if (is_array($sqlPartArray[$k][
'sub'])) {
3573 $this->map_sqlParts($sqlPartArray[$k][
'sub'], $defaultTable);
3574 }
elseif (isset($sqlPartArray[$k][
'func'])) {
3575 switch ($sqlPartArray[$k][
'func'][
'type']) {
3577 $this->map_subquery($sqlPartArray[$k][
'func'][
'subquery']);
3585 $t = $sqlPartArray[$k][
'func'][
'table'] ? $sqlPartArray[$k][
'func'][
'table'] : $defaultTable;
3586 $t = $this->getMappingKey($t);
3587 if (is_array($this->mapping[$t][
'mapFieldNames']) && $this->mapping[$t][
'mapFieldNames'][$sqlPartArray[$k][
'func'][
'field']]) {
3588 $sqlPartArray[$k][
'func'][
'field'] = $this->mapping[$t][
'mapFieldNames'][$sqlPartArray[$k][
'func'][
'field']];
3590 if ($this->mapping[$t][
'mapTableName']) {
3591 $sqlPartArray[$k][
'func'][
'table'] = $this->mapping[$t][
'mapTableName'];
3597 $t = $sqlPartArray[$k][
'table'] ? $sqlPartArray[$k][
'table'] : $defaultTable;
3598 $t = $this->getMappingKey($t);
3600 if (is_array($this->mapping[$t][
'mapFieldNames']) && isset($this->mapping[$t][
'mapFieldNames'][$sqlPartArray[$k][
'field']])) {
3601 $sqlPartArray[$k][
'field'] = $this->mapping[$t][
'mapFieldNames'][$sqlPartArray[$k][
'field']];
3604 if ($this->mapping[$t][
'mapFieldNames']) {
3605 $fieldArray = explode(
'.', $sqlPartArray[$k][
'func_content']);
3606 $fieldArrayCount = count($fieldArray);
3607 if ($fieldArrayCount === 1 && is_array($this->mapping[$t][
'mapFieldNames']) && isset($this->mapping[$t][
'mapFieldNames'][$fieldArray[0]])) {
3608 $sqlPartArray[$k][
'func_content.'][0][
'func_content'] = $this->mapping[$t][
'mapFieldNames'][$fieldArray[0]];
3609 $sqlPartArray[$k][
'func_content'] = $this->mapping[$t][
'mapFieldNames'][$fieldArray[0]];
3610 }
elseif ($fieldArrayCount === 2) {
3612 $table = $fieldArray[0];
3613 $tableKey = $this->getMappingKey($table);
3614 if (isset($this->mapping[$tableKey][
'mapTableName'])) {
3615 $table = $this->mapping[$tableKey][
'mapTableName'];
3618 $field = $fieldArray[1];
3619 if (is_array($this->mapping[$tableKey][
'mapFieldNames']) && isset($this->mapping[$tableKey][
'mapFieldNames'][$fieldArray[1]])) {
3620 $field = $this->mapping[$tableKey][
'mapFieldNames'][$fieldArray[1]];
3622 $sqlPartArray[$k][
'func_content.'][0][
'func_content'] = $table .
'.' . $field;
3623 $sqlPartArray[$k][
'func_content'] = $table .
'.' . $field;
3626 if (isset($sqlPartArray[$k][
'flow-control'])) {
3627 if (isset($sqlPartArray[$k][
'flow-control'][
'type'])) {
3628 $temp = array($sqlPartArray[$k][
'flow-control']);
3629 $this->map_sqlParts($temp, $t);
3631 $sqlPartArray[$k][
'flow-control'] = $temp[0];
3636 if (isset($v[
'value'][
'operator'])) {
3637 foreach ($sqlPartArray[$k][
'value'][
'args'] as $argK => $fieldDef) {
3638 $tableKey = $this->getMappingKey($fieldDef[
'table']);
3639 if (isset($this->mapping[$tableKey][
'mapTableName'])) {
3640 $sqlPartArray[$k][
'value'][
'args'][$argK][
'table'] = $this->mapping[$tableKey][
'mapTableName'];
3642 if (is_array($this->mapping[$tableKey][
'mapFieldNames']) && isset($this->mapping[$tableKey][
'mapFieldNames'][$fieldDef[
'field']])) {
3643 $sqlPartArray[$k][
'value'][
'args'][$argK][
'field'] = $this->mapping[$tableKey][
'mapFieldNames'][$fieldDef[
'field']];
3648 if (isset($sqlPartArray[$k][
'subquery'])) {
3649 $this->map_subquery($sqlPartArray[$k][
'subquery']);
3653 if (!is_numeric($sqlPartArray[$k][
'value'][0]) && !isset($sqlPartArray[$k][
'value'][1])) {
3654 $fieldArray = explode(
'.', $sqlPartArray[$k][
'value'][0]);
3655 $fieldArrayCount = count($fieldArray);
3656 if ($fieldArrayCount === 1 && is_array($this->mapping[$t][
'mapFieldNames']) && isset($this->mapping[$t][
'mapFieldNames'][$fieldArray[0]])) {
3657 $sqlPartArray[$k][
'value'][0] = $this->mapping[$t][
'mapFieldNames'][$fieldArray[0]];
3658 }
elseif ($fieldArrayCount === 2) {
3660 $table = $fieldArray[0];
3661 $tableKey = $this->getMappingKey($table);
3662 if (isset($this->mapping[$tableKey][
'mapTableName'])) {
3663 $table = $this->mapping[$tableKey][
'mapTableName'];
3666 $field = $fieldArray[1];
3667 if (is_array($this->mapping[$tableKey][
'mapFieldNames']) && isset($this->mapping[$tableKey][
'mapFieldNames'][$fieldArray[1]])) {
3668 $field = $this->mapping[$tableKey][
'mapFieldNames'][$fieldArray[1]];
3670 $sqlPartArray[$k][
'value'][0] = $table .
'.' . $field;
3674 $tableKey = $this->getMappingKey($sqlPartArray[$k][
'table']);
3675 if ($sqlPartArray[$k][
'table'] && $this->mapping[$tableKey][
'mapTableName']) {
3676 $sqlPartArray[$k][
'table'] = $this->mapping[$tableKey][
'mapTableName'];
3689 protected function map_subquery(&$parsedQuery)
3692 $backupMapping = $this->mapping;
3693 foreach ($parsedQuery[
'FROM'] as $k => $v) {
3694 $mappingKey = $v[
'table'];
3695 if ($v[
'as'] && is_array($this->mapping[$v[
'table']][
'mapFieldNames'])) {
3696 $mappingKey = $this->getFreeMappingKey($v[
'as']);
3700 if ($this->getMappingKey($v[
'table']) !== $v[
'table']) {
3701 $mappingKey = $this->getFreeMappingKey($v[
'table']);
3703 $this->mapping[$mappingKey][
'mapTableName'] =& $this->mapping[$v[
'table']][
'mapTableName'];
3706 if ($mappingKey !== $v[
'table']) {
3707 $this->mapping[$mappingKey][
'mapFieldNames'] =& $this->mapping[$v[
'table']][
'mapFieldNames'];
3711 $defaultTable = $parsedQuery[
'FROM'][0][
'table'];
3712 $this->map_sqlParts($parsedQuery[
'SELECT'], $defaultTable);
3713 $this->map_sqlParts($parsedQuery[
'FROM'], $defaultTable);
3714 $this->map_sqlParts($parsedQuery[
'WHERE'], $defaultTable);
3716 $this->mapping = $backupMapping;
3728 protected function map_genericQueryParsed(&$parsedQuery)
3731 $table = $parsedQuery[
'TABLE'];
3733 throw new \InvalidArgumentException(
'ERROR, mapping: No table found in parsed Query array...', 1310028048);
3736 if ($tableArray = $this->map_needMapping($table)) {
3738 if ($this->mapping[$table][
'mapTableName']) {
3739 $parsedQuery[
'TABLE'] = $this->mapping[$table][
'mapTableName'];
3742 switch ($parsedQuery[
'type']) {
3745 $newFieldName = $this->mapping[$table][
'mapFieldNames'][$parsedQuery[
'FIELD']];
3746 if ($newFieldName) {
3747 if ($parsedQuery[
'FIELD'] == $parsedQuery[
'newField']) {
3748 $parsedQuery[
'FIELD'] = ($parsedQuery[
'newField'] = $newFieldName);
3750 $parsedQuery[
'FIELD'] = $newFieldName;
3754 if (is_array($parsedQuery[
'fields'])) {
3755 $this->map_fieldNamesInArray($table, $parsedQuery[
'fields']);
3760 if (is_array($parsedQuery[
'FIELDS'])) {
3761 $newFieldsArray = array();
3762 foreach ($parsedQuery[
'FIELDS'] as $fN => $fInfo) {
3763 if ($this->mapping[$table][
'mapFieldNames'][$fN]) {
3764 $fN = $this->mapping[$table][
'mapFieldNames'][$fN];
3766 $newFieldsArray[$fN] = $fInfo;
3768 $parsedQuery[
'FIELDS'] = $newFieldsArray;
3771 if (is_array($parsedQuery[
'KEYS'])) {
3772 foreach ($parsedQuery[
'KEYS'] as $kN => $kInfo) {
3773 $this->map_fieldNamesInArray($table, $parsedQuery[
'KEYS'][$kN]);
3788 protected function map_fieldNamesInArray($table, &$fieldArray)
3790 if (is_array($this->mapping[$table][
'mapFieldNames'])) {
3791 foreach ($fieldArray as $k => $v) {
3792 if ($this->mapping[$table][
'mapFieldNames'][$v]) {
3793 $fieldArray[$k] = $this->mapping[$table][
'mapFieldNames'][$v];
3805 protected function createMappingsIfRequired($parsedQuery)
3808 !$this->dbmsSpecifics->specificExists(Specifics\AbstractSpecifics::TABLE_MAXLENGTH)
3809 && !$this->dbmsSpecifics->specificExists(Specifics\AbstractSpecifics::FIELD_MAXLENGTH)
3814 $mappingConfiguration = array();
3815 $table = $parsedQuery[
'TABLE'];
3816 if (!isset($this->mapping[$table])) {
3817 $truncatedTable = $this->dbmsSpecifics->truncateIdentifier($table, Specifics\AbstractSpecifics::TABLE_MAXLENGTH);
3818 if ($table !== $truncatedTable) {
3819 $mappingConfiguration[
'mapTableName'] = $truncatedTable;
3822 foreach ($parsedQuery[
'FIELDS'] as $field => $_) {
3823 if (!isset($this->mapping[$table][
'mapFieldNames'][$field])) {
3824 $truncatedField = $this->dbmsSpecifics->truncateIdentifier($field, Specifics\AbstractSpecifics::FIELD_MAXLENGTH);
3825 if ($field !== $truncatedField) {
3826 $mappingConfiguration[
'mapFieldNames'][$field] = $truncatedField;
3830 if (!empty($mappingConfiguration)) {
3832 $objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
3834 $configurationManager = $objectManager->get(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
3835 $configurationManager->setLocalConfigurationValueByPath(
3836 'EXTCONF/dbal/mapping/' . $table,
3837 $mappingConfiguration
3841 $this->mapping = array_merge($this->mapping, array($table => $mappingConfiguration));
3859 public function debugHandler($function, $execTime, $inData)
3862 $script = \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(PATH_thisScript);
3863 if (substr($script, -strlen(
'dbal/mod1/index.php')) !=
'dbal/mod1/index.php' && !strstr($inData[
'args'][0],
'tx_dbal_debuglog')) {
3867 if ($this->sql_error()) {
3868 $data[
'sqlError'] = $this->sql_error();
3872 if (empty($this->lastQuery)) {
3873 $query = implode(
' ', $inData[
'args']);
3875 $query = $this->lastQuery;
3877 if ($this->conf[
'debugOptions'][
'numberRows']) {
3878 switch ($function) {
3879 case 'exec_INSERTquery':
3881 case 'exec_UPDATEquery':
3883 case 'exec_DELETEquery':
3884 $data[
'numberRows'] = $this->sql_affected_rows();
3886 case 'exec_SELECTquery':
3887 $data[
'numberRows'] = $inData[
'numberRows'];
3891 if ($this->conf[
'debugOptions'][
'backtrace']) {
3892 $backtrace = debug_backtrace();
3893 unset($backtrace[0]);
3895 $data[
'backtrace'] = array_slice($backtrace, 0, $this->conf[
'debugOptions'][
'backtrace']);
3897 switch ($function) {
3898 case 'exec_INSERTquery':
3900 case 'exec_UPDATEquery':
3902 case 'exec_DELETEquery':
3903 $this->debug_log($query, $execTime, $data, $joinTable, $errorFlag, $script);
3905 case 'exec_SELECTquery':
3907 if ($this->conf[
'debugOptions'][
'EXPLAIN'] && GeneralUtility::inList(
'adodb,native', $inData[
'handlerType'])) {
3908 $data[
'EXPLAIN'] = $this->debug_explain($this->lastQuery);
3911 if ($this->conf[
'debugOptions'][
'parseQuery']) {
3912 $parseResults = array();
3913 $parseResults[
'SELECT'] = $this->SQLparser->debug_parseSQLpart(
'SELECT', $inData[
'args'][1]);
3914 $parseResults[
'FROM'] = $this->SQLparser->debug_parseSQLpart(
'FROM', $inData[
'args'][0]);
3915 $parseResults[
'WHERE'] = $this->SQLparser->debug_parseSQLpart(
'WHERE', $inData[
'args'][2]);
3916 $parseResults[
'GROUPBY'] = $this->SQLparser->debug_parseSQLpart(
'SELECT', $inData[
'args'][3]);
3918 $parseResults[
'ORDERBY'] = $this->SQLparser->debug_parseSQLpart(
'SELECT', $inData[
'args'][4]);
3920 foreach ($parseResults as $k => $v) {
3922 unset($parseResults[$k]);
3925 if (!empty($parseResults)) {
3926 $data[
'parseError'] = $parseResults;
3931 if ($this->conf[
'debugOptions'][
'joinTables']) {
3932 if (count(explode(
',', $inData[
'ORIG_from_table'])) > 1) {
3933 $joinTable = $inData[
'args'][0];
3937 $this->debug_log($query, $execTime, $data, $joinTable, $errorFlag, $script);
3938 if (!empty($inData[
'args'][2])) {
3939 $this->debug_WHERE($inData[
'args'][0], $inData[
'args'][2], $script);
3954 public function debug_WHERE($table, $where, $script =
'')
3956 $insertArray = array(
3958 'beuser_id' => (
int)
$GLOBALS[
'BE_USER']->user[
'uid'],
3959 'script' => $script,
3960 'tablename' => $table,
3961 'whereclause' => $where
3963 $this->exec_INSERTquery(
'tx_dbal_debuglog_where', $insertArray);
3977 public function debug_log($query, $ms, $data, $join, $errorFlag, $script =
'')
3979 if (is_array($query)) {
3980 $queryToLog = $query[0] .
' -- ';
3981 if (!empty($query[1])) {
3982 $queryToLog .= count($query[1]) .
' BLOB FIELDS: ' . implode(
', ', array_keys($query[1]));
3984 if (!empty($query[2])) {
3985 $queryToLog .= count($query[2]) .
' CLOB FIELDS: ' . implode(
', ', array_keys($query[2]));
3988 $queryToLog = $query;
3990 $insertArray = array(
3992 'beuser_id' => (
int)
$GLOBALS[
'BE_USER']->user[
'uid'],
3993 'script' => $script,
3995 'table_join' => $join,
3996 'serdata' => serialize($data),
3997 'query' => $queryToLog,
3998 'errorFlag' => $errorFlag
4000 $this->exec_INSERTquery(
'tx_dbal_debuglog', $insertArray);
4009 public function debug_explain($query)
4012 $hType = (string)$this->handlerCfg[$this->lastHandlerKey][
'type'];
4015 $res = $this->sql_query(
'EXPLAIN ' . $query);
4016 while ($row = $this->sql_fetch_assoc($res)) {
4021 switch ($this->handlerCfg[
'_DEFAULT'][
'config'][
'driver']) {
4023 $this->sql_query(
'EXPLAIN PLAN ' . $query);
4024 $output[] =
'EXPLAIN PLAN data logged to default PLAN_TABLE';
4027 $res = $this->sql_query(
'EXPLAIN ' . $query);
4028 while ($row = $this->sql_fetch_assoc($res)) {