public function __construct(FileInterface $file, TableSchemaInterface $tableSchema, IndexSchema $indexPage = null, $forkRate = 33) { $keyLength = 0; foreach ($indexPage->getColumns() as $columnId) { /* @var $columnPage ColumnSchema */ $columnPage = $tableSchema->getColumn($columnId); assert(!is_null($columnPage)); $keyLength += $columnPage->getCellSize(); } if ($keyLength < 4) { $keyLength = 4; } if (!is_numeric($forkRate)) { throw new \ErrorException("Forkrate has to specified as integer!"); } $forkRate = (int) $forkRate; $this->file = $file; $this->setKeyLength($keyLength); $this->forkRate = $forkRate; $this->tableSchema = $tableSchema; $this->indexPage = $indexPage; // if file is empty, initialize it if ($file->getLength() <= 1) { $file->setData(str_pad("", $keyLength * 8, "")); $rootNode = new BTreeNodePage(); $rootNode->setKeyLength($keyLength); $rootNode->setForkRate($this->forkRate); // make sure root-reference is in index 1, not 0. // that way we can use reference 0 as 'not defined'/'not used' $this->setRootReference(1); $this->writeNode($rootNode, 1); } }
public function setUp() { $forkRate = 16; $file = new FileResourceProxy(fopen("php://memory", "w")); $doublesFile = new FileResourceProxy(fopen("php://memory", "w")); $tableSchemaFile = new FileResourceProxy(fopen("php://memory", "w")); $indexSchemaFile = new FileResourceProxy(fopen("php://memory", "w")); $tableSchema = new TableSchema($tableSchemaFile, $indexSchemaFile); $columnPageA = new ColumnSchema(); $columnPageA->setName("columnB"); $columnPageA->setIndex(0); $columnPageA->setDataType(DataType::INT()); $columnPageA->setLength(4); $tableSchema->addColumnSchema($columnPageA); $columnPageB = new ColumnSchema(); $columnPageB->setName("columnC"); $columnPageB->setIndex(1); $columnPageB->setDataType(DataType::VARCHAR()); $columnPageB->setLength(4); $tableSchema->addColumnSchema($columnPageB); $indexPage = new IndexSchema(); $indexPage->setName("test-index"); $indexPage->setColumns([0, 1]); $indexPage->setType(Type::INDEX()); $indexPage->setEngine(IndexEngine::BTREE()); $this->btree = new BTree($file, $tableSchema, $indexPage, $forkRate); $this->btree->setDoublesFile($doublesFile); $this->btree->setIsDevelopmentMode(true); }
public function createIndex($schemaId, $tableId, $indexId, TableSchemaInterface $tableSchema, IndexSchema $indexSchema) { $indexDataFilepath = sprintf(FilePathes::FILEPATH_INDEX_DATA, $schemaId, $tableId, $indexId); $indexDataFile = $this->filesystem->getFile($indexDataFilepath); $filePath = sprintf(FilePathes::FILEPATH_TABLE_COLUMN_INDEX, $schemaId, $tableId, $indexId); $indexDoublesFilepath = ""; $indexDoublesFile = null; if (!$indexSchema->isUnique()) { $indexDoublesFilepath = sprintf(FilePathes::FILEPATH_INDEX_DOUBLES, $schemaId, $tableId, $indexId); $indexDoublesFile = $this->filesystem->getFile($indexDoublesFilepath); } $engine = $indexSchema->getEngine(); /* @var $index IndexInterface */ $index = null; if ($this->hasIndexFactory($engine)) { /* @var $indexFactory IndexFactoryInterface */ $indexFactory = $this->getIndexFactory($engine); $index = $indexFactory->createIndex($schemaId, $tableId, $indexId, $tableSchema, $indexSchema); } else { switch ($engine) { default: case IndexEngine::RTREE(): $engineName = "UNKNOWN"; if (is_object($indexSchema->getEngine())) { $engineName = $indexSchema->getEngine()->getName(); } trigger_error("Requested unimplemented INDEX-ENGINE {$engineName}, using B-TREE instead!", E_USER_NOTICE); # Use B-TREE instead of unimplemented index-engine # Use B-TREE instead of unimplemented index-engine case IndexEngine::BTREE(): $index = new BTree($indexDataFile, $tableSchema, $indexSchema); if (!$indexSchema->isUnique()) { $index->setDoublesFile($indexDoublesFile); } break; case IndexEngine::HASH(): $index = new HashTable($indexDataFile, $indexSchema->getKeyLength()); if (!$indexSchema->isUnique()) { $index->setDoublesFile($indexDoublesFile); } break; } } return $index; }
public function setUp() { $columnSchemaA = new ColumnSchema(); $columnSchemaA->setName("foo"); $columnSchemaA->setDataType(DataType::INTEGER()); $columnSchemaA->setLength(4); $columnSchemaA->setExtraFlags(ColumnSchema::EXTRA_PRIMARY_KEY); $columnSchemaB = new ColumnSchema(); $columnSchemaB->setName("baz"); $columnSchemaB->setDataType(DataType::VARCHAR()); $columnSchemaB->setLength(12); $columnSchemaC = new ColumnSchema(); $columnSchemaC->setName("bar"); $columnSchemaC->setDataType(DataType::DATETIME()); $columnSchemaC->setLength(19); $indexSchema = new IndexSchema(); $indexSchema->setName("idx_foo"); $indexSchema->setColumns([0]); # n'th index in $columnData's $indexSchema->setEngine(IndexEngine::BTREE()); $indexSchema->setType(Type::UNIQUE()); $indexSchema->setKeyLength(4); $tableSchema = new TableSchema(new FileResourceProxy(fopen("php://memory", "w")), new FileResourceProxy(fopen("php://memory", "w"))); $tableSchema->addColumnSchema($columnSchemaA); $tableSchema->addColumnSchema($columnSchemaB); $tableSchema->addColumnSchema($columnSchemaC); $tableSchema->addIndexSchema($indexSchema); $this->table = new Table($tableSchema, [new ColumnData(new FileResourceProxy(fopen("php://memory", "w")), $columnSchemaA), new ColumnData(new FileResourceProxy(fopen("php://memory", "w")), $columnSchemaB), new ColumnData(new FileResourceProxy(fopen("php://memory", "w")), $columnSchemaC)], [new BTree(new FileResourceProxy(fopen("php://memory", "w")), $tableSchema, $indexSchema)], new FileResourceProxy(fopen("php://memory", "w")), new FileResourceProxy(fopen("php://memory", "w"))); }
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 getIndexSchema($index) { $file = $this->getIndexFile(); $file->seek($index * IndexSchema::PAGE_SIZE, SEEK_SET); $data = $file->read(IndexSchema::PAGE_SIZE); if (strlen($data) !== IndexSchema::PAGE_SIZE) { return null; } $indexSchema = new IndexSchema(); $indexSchema->setData($data); $indexSchema->setId($index); return $indexSchema; }