protected function executeShowDatabases(ShowJob $statement, array $parameters = array()) { $result = new TemporaryResult(['DATABASE']); $list = $this->schemaManager->listSchemas(); sort($list); foreach ($list as $schemaId) { $result->addRow([$schemaId]); } return $result; }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement UseStatement */ $executionContext = new ExecutionContext($this->schemaManager, $statement, $parameters); $databaseValue = $statement->getDatabase(); $databaseName = $this->valueResolver->resolveValue($databaseValue, $executionContext); $this->schemaManager->setCurrentlyUsedDatabaseId($databaseName); $result = new TemporaryResult(); $result->setIsSuccess($this->schemaManager->getCurrentlyUsedDatabaseId() === $databaseName); return $result; }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement CreateDatabaseStatement */ $executionContext = new ExecutionContext($this->schemaManager, $statement, $parameters); $name = $this->valueResolver->resolveValue($statement->getName(), $executionContext); $this->schemaManager->createSchema($name); foreach ($this->tableManager->getTableFactories() as $tableFactory) { /* @var $tableFactory TableFactoryInterface */ if ($tableFactory instanceof InformationSchemaTableFactory) { $tableFactory->clearCache(); } } ### CREATE RESULTSET $result = new TemporaryResult(); $result->setIsSuccess($this->schemaManager->schemaExists($name)); return $result; }
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; }
protected function executeDropTable(DropStatement $statement, ExecutionContext $context) { foreach ($statement->getSubjects() as $tableNameValue) { $tableName = $this->valueResolver->resolveValue($tableNameValue, $context); $this->schemaManager->dropTable($tableName); } $databaseSchema = $this->schemaManager->getSchema(); $result = new TemporaryResult(); $result->setIsSuccess(!$databaseSchema->tableExists($tableName)); return $result; }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement SelectStatement */ $defaultSchema = $this->schemaManager->getSchema(); $executionContext = new ExecutionContext($this->schemaManager, $statement, $parameters); ### COLLECT SOURCE TABLES if (!is_null($statement->getJoinDefinition())) { foreach ($statement->getJoinDefinition()->getTables() as $joinTable) { /* @var $joinTable TableJoin */ /* @var $dataSource ParenthesisPart */ $dataSource = $joinTable->getDataSource(); $tableResource = null; $alias = $dataSource->getAlias(); $dataSource = $dataSource->getContain(); if ($dataSource instanceof TableInterface) { $tableResource = $dataSource; if (is_null($alias)) { $alias = $tableResource->getName(); } } if ($dataSource instanceof SelectStatement) { /* @var $subQueryResult TemporaryResult */ $tableResource = $this->executeJob($dataSource, $parameters); } if ($dataSource instanceof TableSpecifier) { if (!is_null($dataSource->getDatabase())) { if (!$this->schemaManager->schemaExists($dataSource->getDatabase())) { throw new InvalidArgumentException("Database '{$dataSource->getDatabase()}' does not exist!"); } $schema = $this->schemaManager->getSchema($dataSource->getDatabase()); } else { $schema = $defaultSchema; } if (!$schema->tableExists($dataSource->getTable())) { throw new InvalidArgumentException("Table '{$dataSource}' does not exist!"); } if (is_null($alias)) { $alias = $dataSource->getTable(); } $tableResource = $this->tableManager->getTable($dataSource->getTable(), $dataSource->getDatabase()); } $executionContext->setTable($tableResource, (string) $alias); } } ### INIT RESULTSET $resultColumns = array(); foreach ($statement->getColumns() as $column) { if ($column === '*') { foreach ($executionContext->getTables() as $alias => $table) { /* @var $table Table */ /* @var $tableSchema TableSchema */ $tableSchema = $table->getTableSchema(); foreach ($tableSchema->getColumnIterator() as $columnPage) { /* @var $columnPage ColumnSchema */ $columnName = $columnPage->getName(); if (count($executionContext->getTables()) > 1) { $columnName = "{$alias}.{$columnName}"; } $resultColumns[] = $columnName; } } } elseif ($column instanceof ValuePart) { $resultColumns[] = $column->getAlias(); } } $result = new TemporaryResult($resultColumns); $executionContext->setCurrentResultSet(new TemporaryResult($resultColumns)); $executionContext->setCurrentSourceSet(new TemporaryResult()); ### PRE-FILTER SOURCE COLUMNS (currently not implemented) if (!is_null($statement->getCondition())) { /* @var $condition ValuePart */ $condition = $statement->getCondition(); $tableConditions = $this->findFixedConditions($condition); foreach ($executionContext->getTables() as $alias => $table) { /* @var $table TableInterface */ /* @var $tableSchema TableSchema */ $tableSchema = $table->getTableSchema(); $tableIterator = $table; $indexes = $this->findIndexesForTableConditions($tableConditions, $table, $alias); if (!empty($indexes)) { # TODO: actually choose the best index instead of using the first usable index # (We probably need table-statistics to do that.) $index = $indexes[0]; /* @var $indexSchema IndexSchema */ $indexSchema = $index->getIndexSchema(); $indexecColumns = array(); foreach ($indexSchema->getColumns() as $columnId) { $columnName = $tableSchema->getColumn($columnId)->getName(); $indexecColumns[$columnId] = $columnName; } $tableIterator = new FilteredResourceIterator($tableIterator, $condition, $this->valueResolver, $executionContext, $index, $indexecColumns); } if ($tableIterator !== $table) { $executionContext->setTable($tableIterator, $alias); } } } /* @var $joinDefinition Join */ $joinDefinition = $statement->getJoinDefinition(); if (!is_null($joinDefinition)) { ### BUILD JOIN if (count($joinDefinition->getTables()) > 1) { $iterator = new JoinIterator($joinDefinition, $executionContext, $this, $this->valueResolver, $statement, null); } else { /* @var $tableJoin TableJoin */ $tableJoin = $joinDefinition->getTables()[0]; $tableSource = $tableJoin->getDataSource(); $alias = null; while ($tableSource instanceof ParenthesisPart) { if (is_null($alias)) { $alias = $tableSource->getAlias(); } $tableSource = $tableSource->getContain(); } if ($tableSource instanceof TableSpecifier) { if (is_null($alias)) { $alias = $tableSource->getTable(); } $iterator = $executionContext->getTable($alias); } elseif ($tableSource instanceof SelectStatement) { $iterator = $this->executeJob($tableSource); } else { throw new ErrorException("Unexpected object given as source for join!"); } $iterator = new AliasedResourceIterator($iterator, $alias); } ### FILTER RESULT // WHERE condition $condition = $statement->getCondition(); if (!is_null($condition)) { if ($iterator instanceof IteratorAggreagte) { $iterator = $iterator->getIterator(); } $iterator = new FilteredResourceIterator($iterator, $condition, $this->valueResolver, $executionContext); } // ON/USING conditions from joins foreach ($joinDefinition->getTables() as $joinTable) { /* @var $joinTable TableJoin */ $joinCondition = $joinTable->getCondition(); if (!is_null($joinCondition)) { if ($iterator instanceof IteratorAggreagte) { $iterator = $iterator->getIterator(); } $iterator = new FilteredResourceIterator($iterator, $joinCondition, $this->valueResolver, $executionContext); } } ### SET UP SORTING $orderColumns = $statement->getOrderColumns(); if (count($orderColumns) > 0) { $innerIterator = $iterator; $iterator = new SortedResourceIterator($iterator, $this->valueResolver); $iterator->setTemporaryBuildChildIteratorByValue($orderColumns, $innerIterator, $executionContext); } ### WRITE RESULTSET foreach ($iterator as $dataRow) { if ($iterator instanceof UsesBinaryDataInterface && $iterator->usesBinaryData()) { $dataRow = $iterator->convertDataRowToStringRow($dataRow); } $executionContext->getCurrentSourceSet()->addRow($dataRow); $executionContext->setCurrentSourceRow($dataRow); $resolvedRow = $this->valueResolver->resolveSourceRow($statement->getColumns(), $executionContext); $executionContext->getCurrentResultSet()->addRow($resolvedRow); } } else { // no joining (something like "SELECT 5+5 as foo") $resolvedRow = $this->valueResolver->resolveSourceRow($statement->getColumns(), $executionContext); $executionContext->getCurrentResultSet()->addRow($resolvedRow); } ### UNLOCK TABLES foreach ($executionContext->getTables() as $table) { # TODO: unlock tables } ### APPLY GROUPING $groupings = $statement->getGroupings(); if (count($groupings) > 0) { foreach ($groupings as $groupingDefinition) { /* @var $groupingDefinition GroupingDefinition */ /* @var $groupingValue ValuePart */ $groupingValue = $groupingDefinition->getValue(); $beforeSourceRow = $executionContext->getCurrentSourceRow(); $groupedRows = array(); foreach ($executionContext->getCurrentSourceSet() as $row) { $executionContext->setCurrentSourceRow($row); $groupId = $this->valueResolver->resolveValue($groupingValue, $executionContext); if (!isset($groupedRows[$groupId])) { $groupedRows[$groupId] = array(); } $groupedRows[$groupId][] = $row; } $groupedResultSet = new TemporaryResult($resultColumns); foreach ($groupedRows as $groupId => $rows) { if ($groupingDefinition->getDirection() === SqlToken::T_ASC()) { $groupingMainRow = reset($rows); } else { $groupingMainRow = end($rows); } $currentGroupResultSet = new TemporaryResult(); foreach ($rows as $row) { $currentGroupResultSet->addRow($row); } $executionContext->setCurrentSourceRow($groupingMainRow); $executionContext->setCurrentSourceSet($currentGroupResultSet); $resolvedRow = $this->valueResolver->resolveSourceRow($statement->getColumns(), $executionContext); $groupedResultSet->addRow($resolvedRow); } $executionContext->setCurrentSourceRow($beforeSourceRow); $executionContext->setCurrentResultSet($groupedResultSet); } } ### APPLY RESULT-FILTER (HAVING) /* @var $resultFilter ConditionJob */ $resultFilter = $statement->getResultFilter(); if (!is_null($resultFilter)) { $filteredResult = new TemporaryResult($resultColumns); foreach ($executionContext->getCurrentResultSet() as $row) { $executionContext->setCurrentSourceRow($row); $passesFilter = (bool) $this->valueResolver->resolveValue($resultFilter, $executionContext); if ($passesFilter) { $filteredResult->addRow($row); } } $executionContext->setCurrentResultSet($filteredResult); } ### APPEND UNIONED SELECT $unionSelect = $statement->getUnionSelect(); if (!is_null($unionSelect)) { $unionResult = $this->executeJob($unionSelect, $parameters); foreach ($unionResult as $unionRow) { $executionContext->getCurrentResultSet()->addRow($unionRow); } } return $executionContext->getCurrentResultSet(); }
public function executeJob(StatementJob $statement, array $parameters = array()) { /* @var $statement CreateTableStatement */ $context = new ExecutionContext($this->schemaManager, $statement, $parameters); /* @var $databaseSchema Schema */ $databaseSchema = $this->schemaManager->getSchema(); $schemaId = $this->schemaManager->getCurrentlyUsedDatabaseId(); $tableName = $this->valueResolver->resolveValue($statement->getName(), $context); $schemaPage = new DatabaseSchemaPage(); $schemaPage->setName($tableName); $schemaPage->setType(Type::TABLE()); $schemaPage->setEngine(Engine::factory($statement->getEngine()->getName())); $schemaPage->setCollation(strtoupper($statement->getCollate())); $schemaPage->setUseChecksum($statement->getUseChecksum()); $schemaPage->setMaxRows($statement->getMaximumRows()); $schemaPage->setMinRows($statement->getMinimumRows()); $schemaPage->setPackKeys($statement->getPackKeys()); $schemaPage->setDelayKeyWrite($statement->getDelayKeyWrite()); $schemaPage->setRowFormat(RowFormat::factory($statement->getRowFormat())); $schemaPage->setInsertMethod(InsertMethod::factory($statement->getInsertMethod())); $databaseSchema->registerTableSchema($schemaPage); /* @var $tableSchema TableSchema */ $tableSchema = $this->schemaManager->getTableSchema($tableName); assert($tableSchema instanceof TableSchema); ### WRITE COLUMNS switch (true) { case is_array($statement->getColumnDefinition()): foreach ($statement->getColumnDefinition() as $name => $column) { /* @var $column ColumnDefinition */ $columnPage = new ColumnSchema(); $columnPage->setName($name); $columnPage->setDataType(DataType::factory($column->getDataType()->getName())); /* @var $dataType DataType */ $dataType = $columnPage->getDataType(); $flags = 0; if ($column->getIsPrimaryKey()) { $flags = $flags ^ ColumnSchema::EXTRA_PRIMARY_KEY; } if ($column->getIsUnique()) { $flags = $flags ^ ColumnSchema::EXTRA_UNIQUE_KEY; } if (!$column->getIsNullable()) { $flags = $flags ^ ColumnSchema::EXTRA_NOT_NULL; } if ($column->getIsAutoIncrement()) { $flags = $flags ^ ColumnSchema::EXTRA_AUTO_INCREMENT; } $columnPage->setExtraFlags($flags); /* @var $dataType DataType */ $dataType = $column->getDataType(); $columnPage->setLength($dataType->getByteLength()); $columnPage->setSecondLength($dataType->getSecondByteLength()); if (!is_null($column->getDataTypeLength())) { $columnPage->setLength($column->getDataTypeLength()); } if (!is_null($column->getDataTypeSecondLength())) { $columnPage->setSecondLength($column->getDataTypeSecondLength()); } if (!is_null($column->getDefaultValue()) && !$columnPage->isDefaultValueInFile()) { $columnPage->setDefaultValue($column->getDefaultValue()); } $columnIndex = $tableSchema->addColumnSchema($columnPage); if (!is_null($column->getDefaultValue()) && $columnPage->isDefaultValueInFile()) { $defaultValueFilepath = sprintf(FilePathes::FILEPATH_DEFAULT_VALUE, $schemaId, $tableName, $columnIndex); $this->tableManager->getFilesystem()->putFileContents($defaultValueFilepath, $column->getDefaultValue()); } } break; case $statement->getColumnDefinition() instanceof Select: break; case $statement->getColumnDefinition() instanceof TableInterface: break; } foreach ($statement->getIndexes() as $indexName => $index) { /* @var $index Index */ $indexSchemaPage = new IndexSchema(); $indexSchemaPage->setName($indexName); $indexSchemaPage->setEngine(IndexEngine::BTREE()); switch (true) { case $index->getIsPrimary(): $indexSchemaPage->setType(IndexType::PRIMARY()); break; case $index->getIsUnique(): $indexSchemaPage->setType(IndexType::UNIQUE()); break; default: $indexSchemaPage->setType(IndexType::INDEX()); break; } $method = ForeignKeyMethod::factory($index->getForeignKeyOnDeleteReferenceOption()->getName()); $indexSchemaPage->setForeignKeyOnDeleteMethod($method); $method = ForeignKeyMethod::factory($index->getForeignKeyOnUpdateReferenceOption()->getName()); $indexSchemaPage->setForeignKeyOnUpdateMethod($method); $keyLength = 0; $columns = array(); foreach ($index->getColumns() as $indexColumnName) { $indexColumnId = $tableSchema->getColumnIndex((string) $indexColumnName); if (strlen($indexColumnId) <= 0) { throw new ErrorException("Could not find index column '{$indexColumnName}' in table-schema!"); } $columns[] = $indexColumnId; $keyLength += $statement->getColumnDefinition()[(string) $indexColumnName]->getDataSize(); } $indexSchemaPage->setColumns($columns); $indexSchemaPage->setKeyLength($keyLength); $tableSchema->addIndexSchema($indexSchemaPage); } foreach ($this->tableManager->getTableFactories() as $tableFactory) { /* @var $tableFactory TableFactoryInterface */ if ($tableFactory instanceof InformationSchemaTableFactory) { $tableFactory->clearCache(); } } ### RESULT $result = new TemporaryResult(); $result->setIsSuccess(true); return $result; }
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; }