Example #1
0
 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);
 }
Example #2
0
 public function setUp()
 {
     $file = new FileResourceProxy(fopen("php://memory", "w"));
     $columnSchema = new ColumnSchema();
     $columnSchema->setName("test_column");
     $columnSchema->setIndex(0);
     $columnSchema->setDataType(DataType::VARCHAR());
     $columnSchema->setLength(10);
     $this->columnData = new ColumnData($file, $columnSchema);
 }
Example #3
0
 public function setUp()
 {
     $file = new FileResourceProxy(fopen("php://memory", "w"));
     $column1 = new ColumnSchema();
     $column1->setName("foo");
     $column1->setDataType(DataType::INTEGER());
     $column1->setLength(4);
     $column2 = new ColumnSchema();
     $column2->setName("bar");
     $column2->setDataType(DataType::VARCHAR());
     $column2->setLength(12);
     $columns = [[$column1, 'ASC'], [$column2, 'DESC']];
     $this->index = new QuickSort($file, $columns);
 }
 public function createTableSchema($tableSchemaFile, $indexSchemaFile, $tableName)
 {
     $tableSchema = new TableSchema(new FileResourceProxy(fopen("php://memory", "w")), new FileResourceProxy(fopen("php://memory", "w")));
     $columns = array();
     if (isset($this->columnsMap[$tableName])) {
         $columns = $this->columnsMap[$tableName];
     }
     foreach ($columns as $index => list($name, $type, $length)) {
         $columnSchema = new ColumnSchema();
         $columnSchema->setName($name);
         $columnSchema->setIndex($index);
         $columnSchema->setDataType(DataType::getByValue($type));
         $columnSchema->setLength($length);
         $tableSchema->addColumnSchema($columnSchema);
     }
     return $tableSchema;
 }
Example #5
0
 public function getSortIndexByColumns(array $orderColumns)
 {
     $insertionSortFile = new FileResourceProxy(fopen("php://memory", "w"));
     $columnPage = new ColumnSchema();
     $columnPages = array();
     foreach ($orderColumns as $columnIndex => $columnDataset) {
         if ($columnDataset instanceof Column) {
             $direction = 'ASC';
             $columnPage = $columnDataset;
         } else {
             $direction = $columnDataset['direction'] === SqlToken::T_ASC() ? 'ASC' : 'DESC';
             /* @var $value Value */
             $value = $columnDataset['value'];
             $columnPage->setDataType(DataType::VARCHAR());
             # TODO: get actual column-page if possible
             $columnPage->setLength(64);
             $columnPage->setName("INDEXVALUE_{$columnIndex}");
         }
         $columnPages[] = [clone $columnPage, $direction];
     }
     $sortIndex = new QuickSort($insertionSortFile, $columnPages);
     return $sortIndex;
 }
Example #6
0
 /**
  *
  * @return TableSchema
  */
 public function getTableSchema()
 {
     if (is_null($this->tableSchema)) {
         $columnFile = new FileResourceProxy(fopen("php://memory", "w"));
         $indexFile = new FileResourceProxy(fopen("php://memory", "w"));
         $this->tableSchema = new TableSchema($columnFile, $indexFile);
         foreach ($this->columnNames as $columnName) {
             $columnPage = new ColumnSchema();
             $columnPage->setName($columnName);
             $columnPage->setDataType(DataType::VARCHAR());
             $columnPage->setLength(1024);
             $this->tableSchema->addColumnSchema($columnPage);
         }
     }
     return $this->tableSchema;
 }
Example #7
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $columnDefinition = new ColumnDefinitionJob();
     $tokens->seekTokens([T_STRING, T_CONSTANT_ENCAPSED_STRING]);
     if (!$tokens->isTokens([T_STRING, T_CONSTANT_ENCAPSED_STRING], TokenIterator::CURRENT)) {
         throw new MalformedSqlException("Missing name for column!", $tokens);
     }
     $name = $tokens->getCurrentTokenString();
     if ($name[0] === '`' && $name[strlen($name) - 1] === '`') {
         $name = substr($name, 1, strlen($name) - 2);
     }
     if ($name[0] === '"' && $name[strlen($name) - 1] === '"') {
         $name = substr($name, 1, strlen($name) - 2);
     }
     if ($name[0] === "'" && $name[strlen($name) - 1] === "'") {
         $name = substr($name, 1, strlen($name) - 2);
     }
     $columnDefinition->setName($name);
     # this makes sure that the next token is valid data-type
     $dataTypeString = strtoupper($tokens->getExclusiveTokenString());
     $dataType = DataType::factory($dataTypeString);
     $columnDefinition->setDataType($dataType);
     $tokens->seekIndex($tokens->getExclusiveTokenIndex());
     # data-type-length
     if ($tokens->seekTokenText('(')) {
         if ($dataType === DataType::ENUM() || $dataType === DataType::SET()) {
             do {
                 if (!$this->valueParser->canParseTokens($tokens)) {
                     throw new MalformedSqlException("Invalid value in ENUM!", $tokens);
                 }
                 $columnDefinition->addEnumValue($this->valueParser->convertSqlToJob($tokens));
             } while ($tokens->seekTokenText(','));
         } else {
             if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                 throw new MalformedSqlException("Missing number for length of data-type!", $tokens);
             }
             $columnDefinition->setDataTypeLength((int) $tokens->getCurrentTokenString());
             if ($tokens->seekTokenText(',')) {
                 if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                     throw new MalformedSqlException("Missing second number for length of data-type!", $tokens);
                 }
                 $columnDefinition->setDataTypeSecondLength((int) $tokens->getCurrentTokenString());
             }
         }
         if (!$tokens->seekTokenText(')')) {
             throw new MalformedSqlException("Missing end-parenthesis for length of data-type!", $tokens);
         }
     }
     while (true) {
         switch (true) {
             case $tokens->seekTokenNum(SqlToken::T_NOT()):
                 if (!$tokens->seekTokenNum(SqlToken::T_NULL())) {
                     throw new MalformedSqlException("Missing T_NULL after T_NOT in column-definition!", $tokens);
                 }
                 $columnDefinition->setIsNullable(false);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_NULL()):
                 $columnDefinition->setIsNullable(true);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_DEFAULT()):
                 if (!$this->valueParser->canParseTokens($tokens)) {
                     throw new MalformedSqlException("Missing valid default value for column definition!", $tokens);
                 }
                 $beforeIndex = $tokens->getIndex();
                 $defaultValue = $this->valueParser->convertSqlToJob($tokens);
                 $afterIndex = $tokens->getIndex();
                 $defaultSqlRepresentation = "";
                 for ($index = $beforeIndex + 1; $index <= $afterIndex; $index++) {
                     $defaultSqlRepresentation .= $tokens->getTokenArray()[$index][1];
                 }
                 $columnDefinition->setDefaultValue($defaultValue);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_UNIQUE()):
                 $tokens->seekTokenNum(SqlToken::T_KEY());
                 $columnDefinition->setIsUnique(true);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_PRIMARY()):
                 $tokens->seekTokenNum(SqlToken::T_KEY());
                 $columnDefinition->setIsPrimaryKey(true);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_UNSIGNED()):
                 $columnDefinition->setIsUnsigned(true);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_COMMENT()):
                 if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING)) {
                     throw new MalformedSqlException("Missing encapsed string for comment-declaration column-definition!", $tokens);
                 }
                 $columnDefinition->setComment($tokens->getCurrentTokenString());
                 break;
             case $tokens->seekTokenNum(SqlToken::T_AUTO_INCREMENT()):
                 $columnDefinition->setAutoIncrement(true);
                 break;
             case $tokens->seekTokenNum(SqlToken::T_CHARACTER(), TokenIterator::NEXT, [SqlToken::T_DEFAULT()]):
                 if (!$tokens->seekTokenNum(SqlToken::T_SET())) {
                     throw new MalformedSqlException("MIssing SET after CHARACTER keyword!", $tokens);
                 }
             case $tokens->seekTokenNum(SqlToken::T_CHARSET(), TokenIterator::NEXT, [SqlToken::T_DEFAULT()]):
                 $tokens->seekTokenText('=');
                 if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING) && !$tokens->seekTokenNum(T_STRING)) {
                     throw new MalformedSqlException("Missing string for CHARACTER SET!", $tokens);
                 }
                 $columnDefinition->setCharacterSet($tokens->getCurrentTokenString());
                 break;
             case $tokens->seekTokenNum(SqlToken::T_COLLATE()):
                 $tokens->seekTokenText('=');
                 if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING) && !$tokens->seekTokenNum(T_STRING)) {
                     throw new MalformedSqlException("Missing string for COLLATE!", $tokens);
                 }
                 $columnDefinition->setCollate($tokens->getCurrentTokenString());
                 break;
             case $tokens->seekTokenNum(SqlToken::T_ON()):
                 switch (true) {
                     case $tokens->seekTokenNum(SqlToken::T_UPDATE()):
                         switch (true) {
                             case $this->valueParser->canParseTokens($tokens):
                                 $columnDefinition->setOnUpdate($this->valueParser->convertSqlToJob($tokens));
                                 break;
                             default:
                                 throw new MalformedSqlException("Invalid value for ON UPDATE!", $tokens);
                         }
                         break;
                     case $tokens->seekTokenNum(SqlToken::T_DELETE()):
                         switch (true) {
                             case $this->valueParser->canParseTokens($tokens):
                                 $columnDefinition->setOnDelete($this->valueParser->convertSqlToJob($tokens));
                                 break;
                             default:
                                 throw new MalformedSqlException("Invalid value for ON UPDATE!", $tokens);
                         }
                         break;
                     default:
                         throw new MalformedSqlException("Only UPDATE and DELETE allowed for ON trigger!", $tokens);
                 }
                 break;
             case is_int($tokens->isTokenText(')')):
             case is_int($tokens->isTokenText(',')):
                 break 2;
             default:
                 break 2;
         }
     }
     return $columnDefinition;
 }
Example #8
0
 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;
 }
Example #9
0
 public function convertBinaryToString($binary, DataType $dataType)
 {
     switch ($dataType) {
         case DataType::BIT():
             return $binary;
         case DataType::BOOL():
             break;
             ### NUMERIC
         ### NUMERIC
         case DataType::TINYINT():
             return (int) ord($binary);
         case DataType::SMALLINT():
         case DataType::MEDIUMINT():
         case DataType::INT():
         case DataType::BIGINT():
             return $this->strdec($binary);
         case DataType::DEC():
         case DataType::FLOAT():
         case DataType::DOUBLE():
             return $binary;
             ### TIME / DATE
         ### TIME / DATE
         case DataType::DATE():
             return date("Y-m-d", $this->strdec($binary));
         case DataType::DATETIME():
             return date("Y-m-d H:i:s", $this->strdec($binary));
         case DataType::TIMESTAMP():
             return date("Y-m-d H:i:s", $this->strdec($binary));
         case DataType::TIME():
             return date("H:i:s", $this->strdec($binary));
         case DataType::YEAR():
             return (string) $this->strdec($binary);
             ### TEXT
         ### TEXT
         case DataType::CHAR():
         case DataType::VARCHAR():
         case DataType::BINARY():
         case DataType::VARBINARY():
         case DataType::TINYBLOB():
         case DataType::TINYTEXT():
         case DataType::BLOB():
         case DataType::TEXT():
         case DataType::MEDIUMBLOB():
         case DataType::MEDIUMTEXT():
         case DataType::LONGBLOB():
         case DataType::LONGTEXT():
         case DataType::ENUM():
         case DataType::SET():
             return $binary;
     }
 }
Example #10
0
 public function dataProviderModifyColumn()
 {
     $columnSchema = new ColumnSchema();
     $columnSchema->setName("baz");
     $columnSchema->setDataType(DataType::VARCHAR());
     $columnSchema->setLength(5);
     return array([[[123, "Lorem ipsum", null], [456, "dolor sit", "2015-06-07 12:34:56"]], $columnSchema, [[789, "amet", "1990-10-02 10:20:30"], [234, "", null]], [['123', "Lorem", null], ['456', "dolor", "2015-06-07 12:34:56"], ['789', "amet", "1990-10-02 10:20:30"], ['234', "", null]]]);
 }
Example #11
0
 public function setData($data)
 {
     if (strlen($data) !== self::PAGE_SIZE) {
         throw new \InvalidArgumentException("Invalid data-block given to column-page! (length " . strlen($data) . " != " . self::PAGE_SIZE . ")");
     }
     $rawName = substr($data, 0, 128);
     $rawIndex = substr($data, 128, 2);
     $rawDataType = substr($data, 130, 2);
     $rawLength = substr($data, 132, 16);
     $rawSecondLength = substr($data, 148, 16);
     $hasDefaultValue = substr($data, 164, 1);
     $rawDefaultValue = substr($data, 165, 63);
     $rawExtra = substr($data, 228, 2);
     $rawFkTable = substr($data, 230, 8);
     $rawFkColumn = substr($data, 238, 4);
     $name = rtrim($rawName, "");
     $length = ltrim($rawLength, "");
     $secondLength = ltrim($rawSecondLength, "");
     $defaultValue = rtrim($rawDefaultValue, "");
     $fkTable = ltrim($rawFkTable, "");
     $fkColumn = ltrim($rawFkColumn, "");
     $dataType = unpack("n", $rawDataType)[1];
     $index = unpack("n", $rawIndex)[1];
     $length = $this->strdec($length);
     $secondLength = $this->strdec($secondLength);
     $extra = unpack("n", $rawExtra)[1];
     $fkTable = $this->strdec($fkTable);
     $fkColumn = $this->strdec($fkColumn);
     $hasDefaultValue = (bool) ord($hasDefaultValue);
     if (!$hasDefaultValue) {
         $defaultValue = null;
     }
     $this->setName($name);
     $this->setIndex($index);
     $this->setDataType(DataType::getByValue($dataType));
     $this->setLength($length);
     $this->setSecondLength($secondLength);
     $this->setDefaultValue($defaultValue);
     $this->setExtraFlags($extra);
     $this->setFKTableIndex($fkTable);
     $this->setFKColumnIndex($fkColumn);
 }