public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement DescribeStatement */ $result = new TemporaryResult(['Field', 'Type', 'Null', 'Key', 'Default', 'Extra']); $schemaId = $this->schemaManager->getCurrentlyUsedDatabaseId(); /* @var $tableSchema TableSchema */ $tableSchema = $this->schemaManager->getTableSchema($statement->getTable()->getTable(), $statement->getTable()->getDatabase()); if (is_null($tableSchema)) { throw new InvalidArgumentException("Table '{$statement->getTable()}' not found!"); } foreach ($tableSchema->getColumnIterator() as $columnId => $columnPage) { /* @var $columnPage ColumnSchema */ $fieldName = $columnPage->getName(); $dataType = $columnPage->getDataType(); $length = $columnPage->getLength(); $hasIndex = !is_null($tableSchema->getIndexIdByColumns([$columnId])); $typeString = strtolower($dataType->getName()); if ($dataType->hasLength()) { if ($columnPage->getSecondLength() > 0) { $length = "{$length},{$columnPage->getSecondLength()}"; } $typeString .= "({$length})"; } $null = $columnPage->isNotNull() ? 'NO' : 'YES'; $key = ''; if ($hasIndex) { $key = 'MUL'; if ($columnPage->isUniqueKey()) { $key = 'UNI'; } if ($columnPage->isPrimaryKey()) { $key = 'PRI'; } } $default = ""; if ($columnPage->hasDefaultValue()) { if ($columnPage->isDefaultValueInFile()) { $defaultValueFilepath = sprintf(FilePathes::FILEPATH_DEFAULT_VALUE, $schemaId, $statement->getTable(), $columnId); $this->schemaManager->getFilesystem()->getFileContents($defaultValueFilepath); } else { $default = $columnPage->getDefaultValue(); } if (!$dataType->mustResolveDefaultValue()) { $default = $this->dataConverter->convertBinaryToString($default, $dataType); } } $extraArray = array(); if ($columnPage->isAutoIncrement()) { $extraArray[] = "auto_increment"; } $result->addRow([$fieldName, $typeString, $null, $key, $default, implode(" ", $extraArray)]); } return $result; }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement CreateIndexStatement */ /* @var $tableSpecifier TableSpecifier */ $tableSpecifier = $statement->getTable(); ### WRITE INDEX PAGE /* @var $tableResource TableInterface */ $tableResource = $this->tableManager->getTable($tableSpecifier->getTable(), $tableSpecifier->getDatabase()); /* @var $tableSchema TableSchema */ $tableSchema = $tableResource->getTableSchema(); $indexPage = new Index(); $indexPage->setName($statement->getName()); $indexPage->setEngine(IndexEngine::factory($statement->getIndexType()->getName())); $columnIds = array(); $keyLength = 0; foreach ($statement->getColumns() as $columnDataset) { $columnSpecifier = $columnDataset['column']; /* @var $columnSpecifier Column */ $columnId = $tableSchema->getColumnIndex($columnSpecifier->getColumn()); if (is_null($columnId)) { throw new InvalidArgumentException("Cannot create index for unknown column '{$columnSpecifier->getColumn()}'!"); } if (!is_null($columnDataset['length'])) { $keyLength += (int) $columnDataset['length']; } else { $keyLength += $tableSchema->getColumn($columnId)->getLength(); } $columnIds[] = $columnId; } $indexPage->setColumns($columnIds); $indexPage->setKeyLength($keyLength); if ($statement->getIsPrimary()) { $indexPage->setType(Type::PRIMARY()); } elseif ($statement->getIsUnique()) { $indexPage->setType(Type::UNIQUE()); } else { $indexPage->setType(Type::INDEX()); } $tableSchema->addIndexSchema($indexPage); ### PHSICALLY BUILD INDEX /* @var $tableResource TableInterface */ $tableResource = $this->tableManager->getIndex($indexPage->getName(), $tableSpecifier->getTable(), $tableSpecifier->getDatabase()); foreach ($tableResource->getIterator() as $rowId => $row) { $indexResource->insert($row, $rowId); } foreach ($this->tableManager->getTableFactories() as $tableFactory) { /* @var $tableFactory TableFactoryInterface */ if ($tableFactory instanceof InformationSchemaTableFactory) { $tableFactory->clearCache(); } } }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement InsertStatement */ $result = new TemporaryResult(); $context = new ExecutionContext($this->schemaManager, $statement, $parameters); $tableName = (string) $statement->getTable(); /* @var $table TableInterface */ $table = $this->tableManager->getTable($tableName); /* @var $tableSchema TableSchema */ $tableSchema = $table->getTableSchema(); ### BUILD COLUMN MAP $columnNameToIdMap = array(); foreach ($tableSchema->getColumnIterator() as $columnId => $columnPage) { /* @var $columnPage Column */ $columnName = $columnPage->getName(); $columnNameToIdMap[$columnName] = $columnId; } ### GET INDICES $indices = array(); foreach ($tableSchema->getIndexIterator() as $indexId => $indexPage) { /* @var $indexPage Index */ /* @var $index Index */ $index = $table->getIndex($indexId); $indices[$indexId] = $index; } ### BUILD ROW DATA $rowDatas = array(); switch (true) { case $statement->getDataSource() instanceof Select: $subResult = $this->selectExecutor->executeJob($statement->getDataSource(), $parameters); foreach ($subResult as $subResultRow) { $rowData = array(); foreach ($subResultRow as $columnName => $value) { $columnId = $columnNameToIdMap[$columnName]; $rowData[$columnId] = $value; } $rowDatas[] = $rowData; } break; case is_array($statement->getDataSource()): foreach ($statement->getDataSource() as $row) { $sourceRow = array(); foreach ($statement->getColumns() as $sourceColumnId => $sourceColumn) { /* @var $sourceColumn Column */ $sourceColumnName = (string) $sourceColumn; $sourceRow[$sourceColumnName] = $row[$sourceColumnId]; } $rowData = array(); foreach ($statement->getColumns() as $sourceColumnId => $sourceColumn) { /* @var $sourceColumn Column */ $columnName = (string) $sourceColumn; if (!isset($columnNameToIdMap[$columnName])) { throw new ErrorException("Unknown column '{$columnName}' in statement!"); } $columnId = $columnNameToIdMap[$columnName]; if (isset($sourceRow[$columnName])) { $value = $sourceRow[$columnName]; $value = $this->valueResolver->resolveValue($value, $context); } else { $value = null; } /* @var $columnPage Column */ $columnPage = $tableSchema->getColumn($columnId); if (is_null($value) && $columnPage->isAutoIncrement()) { $value = $table->getAutoIncrementId(); $table->incrementAutoIncrementId(); } if ($columnPage->isNotNull() && is_null($value)) { $columnName = $tableSchema->getColumn($columnId)->getName(); throw new ErrorException("Column '{$columnName}' cannot be NULL!"); } $rowData[$columnId] = $value; } $primaryKey = array(); // fill up missing columns foreach ($columnNameToIdMap as $columnName => $columnId) { /* @var $columnPage Column */ $columnPage = $tableSchema->getColumn($columnId); if (!isset($rowData[$columnId])) { if ($columnPage->isNotNull()) { if ($columnPage->isAutoIncrement()) { $rowData[$columnId] = $table->getAutoIncrementId(); $table->incrementAutoIncrementId(); } elseif ($columnPage->hasDefaultValue()) { if ($columnPage->isDefaultValueInFile()) { $defaultValueReference = $columnPage->getDefaultValue(); $defaultValueFilePath = sprintf(FilePathes::FILEPATH_DEFAULT_VALUE, $schemaId, $tableName, $columnId); } else { $rowData[$columnId] = $columnPage->getDefaultValue(); } } else { throw new ErrorException("Column '{$columnName}' cannot be NULL!"); } } } if ($columnPage->isPrimaryKey()) { $primaryKey[$columnName] = $rowData[$columnId]; } } $result->setLastInsertId($primaryKey); $rowData = $table->convertStringRowToDataRow($rowData); foreach ($indices as $indexId => $index) { /* @var $index Index */ if (!$index->getIndexSchema()->isUnique()) { continue; } if (count($index->searchRow($rowData)) > 0) { $rowDataString = implode(", ", $rowData); throw new ErrorException("Cannot insert because row '{$rowDataString}' collides " . "with unique key '{$index->getIndexSchema()->getName()}'!"); } } $rowDatas[] = $rowData; } break; } ### INSERT DATA $insertedRowIds = array(); $success = false; try { foreach ($rowDatas as $rowData) { // check unique keys foreach ($indices as $indexId => $index) { if (!$index->getIndexSchema()->isUnique()) { continue; } if (count($index->searchRow($rowData)) > 0) { throw new ErrorException("Cannot insert because of unique key '{$index->getIndexSchema()->getName()}'!"); } } $rowId = $table->addRowData($rowData); $insertedRowIds[] = $rowId; // insert into indicies foreach ($indices as $indexId => $index) { $index->insertRow($rowData, $this->decstr($rowId)); } } $success = true; } catch (Exception $exception) { ### ROLLBACK foreach ($insertedRowIds as $rowId) { $table->removeRow($rowId); // remove from indicies foreach ($indices as $indexId => $index) { $index->removeRow($row, $this->decstr($rowId)); } } throw new ErrorException("Exception in INSERT statement, rollback executed.", null, null, null, 0, $exception); } ### RESULT $result->setIsSuccess((bool) $success); return $result; }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement AlterStatement */ $executionContext = new ExecutionContext($this->schemaManager, $statement, $parameters); /* @var $tableSpecifier TableSpecifier */ $tableSpecifier = $statement->getTable(); /* @var $table TableInterface */ $table = $this->tableManager->getTable($tableSpecifier->getTable(), $tableSpecifier->getDatabase()); $tableId = $this->tableManager->getTableIdByName($tableSpecifier->getTable(), $tableSpecifier->getDatabase()); /* @var $tableSchema TableSchema */ $tableSchema = $table->getTableSchema(); foreach ($statement->getDataChanges() as $dataChange) { /* @var $dataChange DataChange */ switch ($dataChange->getAttribute()) { case AlterAttributeType::ADD(): /* @var $columnDefinition ColumnDefinition */ $columnDefinition = $dataChange->getSubject(); /* @var $columnSchema ColumnSchema */ $columnSchema = $this->convertColumnDefinitionToColumnSchema($columnDefinition, $executionContext); $columnId = $tableSchema->addColumnSchema($columnSchema); /* @var $tableFactory TableFactoryInterface */ $tableFactory = $this->tableManager->getTableFactoryByTable($tableSpecifier->getTable(), $tableSpecifier->getDatabase()); $tableFactory->addColumnToTable($tableSpecifier->getDatabase(), $tableId, $columnId, $table, $columnSchema); break; case AlterAttributeType::DROP(): /* @var $columnSpecifier ColumnSpecifier */ $columnSpecifier = $dataChange->getSubject(); $columnId = $tableSchema->getColumnIndex($columnSpecifier->getColumn()); $tableSchema->removeColumn($columnId); break; case AlterAttributeType::SET_AFTER(): case AlterAttributeType::SET_FIRST(): case AlterAttributeType::MODIFY(): /* @var $columnDefinition ColumnDefinition */ $columnDefinition = $dataChange->getSubject(); /* @var $columnSchema ColumnSchema */ $columnSchema = $this->convertColumnDefinitionToColumnSchema($columnDefinition, $executionContext); $columnId = $tableSchema->getColumnIndex($columnSchema->getName()); /* @var $oldColumnSchema ColumnSchema */ $oldColumnSchema = $tableSchema->getColumn($columnId); $columnSchema->setIndex($oldColumnSchema->getIndex()); $tableSchema->writeColumn($columnId, $columnSchema); /* @var $tableFactory TableFactoryInterface */ $tableFactory = $this->tableManager->getTableFactoryByTable($tableSpecifier->getTable(), $tableSpecifier->getDatabase()); $tableFactory->modifyColumnOnTable($tableSpecifier->getDatabase(), $tableId, $columnId, $table, $columnSchema); if ($dataChange->getAttribute() === AlterAttributeType::SET_FIRST()) { $subjectColumnIndex = $tableSchema->getColumnIndex($columnDefinition->getName()); $subjectColumnSchema = $tableSchema->getColumn($subjectColumnIndex); $oldIndex = $subjectColumnSchema->getIndex(); foreach ($tableSchema->getColumnIterator() as $columnIndex => $columnPage) { if ($columnPage->getIndex() < $oldIndex) { $columnPage->setIndex($columnPage->getIndex() + 1); $tableSchema->writeColumn($columnIndex, $columnPage); } } $subjectColumnSchema->setIndex(0); $tableSchema->writeColumn($subjectColumnIndex, $subjectColumnSchema); } elseif ($dataChange->getAttribute() === AlterAttributeType::SET_AFTER()) { /* @var $afterColumn ColumnSpecifier */ $afterColumn = $dataChange->getValue(); $afterColumnIndex = $tableSchema->getColumnIndex($afterColumn->getColumn()); $afterColumnSchema = $tableSchema->getColumn($afterColumnIndex); $subjectColumnIndex = $tableSchema->getColumnIndex($columnDefinition->getName()); $subjectColumnSchema = $tableSchema->getColumn($subjectColumnIndex); if ($afterColumnSchema->getIndex() < $subjectColumnSchema->getIndex()) { foreach ($tableSchema->getColumnIterator() as $columnIndex => $columnPage) { if ($columnPage->getIndex() > $afterColumnSchema->getIndex() && $columnPage->getIndex() < $subjectColumnSchema->getIndex()) { $columnPage->setIndex($columnPage->getIndex() + 1); $tableSchema->writeColumn($columnIndex, $columnPage); } } $subjectColumnSchema->setIndex($afterColumnSchema->getIndex() + 1); $tableSchema->writeColumn($subjectColumnIndex, $subjectColumnSchema); } else { foreach ($tableSchema->getColumnIterator() as $columnIndex => $columnPage) { if ($columnPage->getIndex() > $afterColumnSchema->getIndex() && $columnPage->getIndex() < $subjectColumnSchema->getIndex()) { $columnPage->setIndex($columnPage->getIndex() - 1); $tableSchema->writeColumn($columnIndex, $columnPage); } } $subjectColumnSchema->setIndex($afterColumnSchema->getIndex()); $tableSchema->writeColumn($subjectColumnIndex, $subjectColumnSchema); $afterColumnSchema->setIndex($afterColumnSchema->getIndex() - 1); $tableSchema->writeColumn($afterColumnSchema, $afterColumnSchema); } } break; case AlterAttributeType::RENAME(): $databaseSchema = $this->schemaManager->getSchema($tableSpecifier->getDatabase()); /* @var $tablePage SchemaPage */ $tableIndex = $databaseSchema->getTableIndex($tableSpecifier->getTable()); $tablePage = $databaseSchema->getTablePage($tableIndex); $tablePage->setName($dataChange->getValue()); $databaseSchema->registerTableSchema($tablePage, $tableIndex); break; case AlterAttributeType::CHARACTER_SET(): break; case AlterAttributeType::COLLATE(): break; case AlterAttributeType::CONVERT(): break; case AlterAttributeType::DEFAULT_VALUE(): break; case AlterAttributeType::ORDER_BY_ASC(): break; case AlterAttributeType::ORDER_BY_DESC(): break; } } foreach ($this->tableManager->getTableFactories() as $tableFactory) { /* @var $tableFactory TableFactoryInterface */ if ($tableFactory instanceof InformationSchemaTableFactory) { $tableFactory->clearCache(); } } $result = new TemporaryResult(); return $result; }