Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

long size varchar with long index size mysql #210

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ loader.php
/bin/view/results/
.vscode
.vscode/*
database.sql

## - Oh Wess!
Makefile
Expand Down
20 changes: 7 additions & 13 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
stopOnFailure="true">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
Expand Down
40 changes: 38 additions & 2 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,9 @@ abstract public function getKeywords(): array;

/**
* Filter Keys
*
* @throws Exception
* @param string $value
* @return string
* @throws Exception
*/
public function filter(string $value): string
{
Expand All @@ -490,4 +490,40 @@ public function filter(string $value): string

return $value;
}


/**
* Returns attribute from List of Document $attributes[]
* @param string $attributeKey
* @param array $attributes Document[]
* returns Document
* @return Document
* @throws Exception
*/
protected function findAttributeInList(string $attributeKey, array $attributes): Document
{
/** @var Document $attribute */
foreach ($attributes as $attribute){
if($this->filter($attributeKey) === $this->filter($attribute->getId())){
return $attribute;
}
}

throw new \Exception('Attribute ' . $attributeKey . ' not found');
}

/**
* This function fixes indexes which have exceeded max default limits
* by comparing the length of the collection attribute string with index max length
* We can overwrite other index behaviour here.
*
* @param Document $index
* @param Document[] $attributes
* @return Document
* @throws Exception
*/
public function fixIndex(Document $index, array $attributes): Document {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be part of the adapter interface as this issue is specific to MariaDB/MySQL.

Also, the name suggest this is a bug fix and might encourage future maintainer to use this as a generic place for adding patches that will increase technical debt.

This method should be designed for enforcing the required behavior for the relevant adapter. getSQLIndexLimit(int $length): int might better explain what we do, and work better with the existing patterns of getSQLIndex() and getSQLIndexType(). Very important we keep consistency and predictability across the library.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I Do not think this is relevant since now it moved to the MariaDB.
Please give me a better name for fixIndex
This function returns the index after checking and overwriting bad values

return $index;
}

}
85 changes: 70 additions & 15 deletions src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,37 +148,41 @@ public function createCollection(string $name, array $attributes = [], array $in
$database = $this->getDefaultDatabase();
$namespace = $this->getNamespace();
$id = $this->filter($name);
$schemaAttributes = [];

foreach ($attributes as $key => $attribute) {
foreach ($attributes as $attribute) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to explain this logic, not clear what is being achieved here. Please add a docblock.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

$attrId = $this->filter($attribute->getId());
$attrType = $this->getSQLType($attribute->getAttribute('type'), $attribute->getAttribute('size', 0), $attribute->getAttribute('signed', true));
$size = $attribute->getAttribute('size', 0);
$type = $attribute->getAttribute('type');
$signed = $attribute->getAttribute('signed', false);
$attrType = $this->getSQLType($type, $size, $signed);

if ($attribute->getAttribute('array')) {
$attrType = 'LONGTEXT';
}

$attributes[$key] = "`{$attrId}` {$attrType}, ";
$schemaAttributes[] = "`{$attrId}` {$attrType}, ";
}

$schemaIndexes = [];
foreach ($indexes as $key => $index) {
$indexId = $this->filter($index->getId());
$indexType = $index->getAttribute('type');

$indexAttributes = $index->getAttribute('attributes');
foreach ($indexAttributes as $nested => $attribute) {
$indexLength = $index->getAttribute('lengths')[$key] ?? '';
$indexLength = (empty($indexLength)) ? '' : '(' . (int)$indexLength . ')';
$indexOrder = $index->getAttribute('orders')[$key] ?? '';
$indexAttributes = [];
foreach ($index->getAttribute('attributes') as $attribute) {
$indexAttribute = $this->filter($attribute);
$size = $index['lengths'][$key] ?? 0;
$length = $size === 0 ? '' : '(' . $size . ')';
$indexOrder = $index->getAttribute('orders')[$key] ?? '';

if ($indexType === Database::INDEX_FULLTEXT) {
$indexOrder = '';
}

$indexAttributes[$nested] = "`{$indexAttribute}`{$indexLength} {$indexOrder}";
$indexAttributes[] = "`{$indexAttribute}`{$length} {$indexOrder}";
}

$indexes[$key] = "{$indexType} `{$indexId}` (" . \implode(", ", $indexAttributes) . " ),";
$schemaIndexes[] = "{$indexType} `{$indexId}` (" . \implode(", ", $indexAttributes) . " ),";
}

try {
Expand All @@ -189,9 +193,9 @@ public function createCollection(string $name, array $attributes = [], array $in
`_createdAt` datetime(3) DEFAULT NULL,
`_updatedAt` datetime(3) DEFAULT NULL,
`_permissions` MEDIUMTEXT DEFAULT NULL,
" . \implode(' ', $attributes) . "
" . \implode(' ', $schemaAttributes) . "
PRIMARY KEY (`_id`),
" . \implode(' ', $indexes) . "
" . \implode(' ', $schemaIndexes) . "
UNIQUE KEY `_uid` (`_uid`),
KEY `_created_at` (`_createdAt`),
KEY `_updated_at` (`_updatedAt`)
Expand Down Expand Up @@ -368,7 +372,6 @@ public function deleteAttribute(string $collection, string $id, bool $array = fa
* @param array $orders
* @return bool
* @throws Exception
* @throws PDOException
*/
public function createIndex(string $collection, string $id, string $type, array $attributes, array $lengths, array $orders): bool
{
Expand Down Expand Up @@ -1790,7 +1793,6 @@ protected function getSQLIndex(string $collection, string $id, string $type, ar

default:
throw new Exception('Unknown Index Type:' . $type);
break;
}

return "CREATE {$type} `{$id}` ON {$this->getSQLTable($collection)} ( " . implode(', ', $attributes) . " )";
Expand Down Expand Up @@ -1891,4 +1893,57 @@ public static function getPDOAttributes(): array
PDO::ATTR_STRINGIFY_FETCHES => true // Returns all fetched data as Strings
];
}

/**
* Return the maximum index length per attribute type
* @param int $size
* @param Document $attribute
* @return int
*/
public function getDefaultIndexSize(int $size, Document $attribute): int
{
$maxIndexLength = 760;

if($attribute['type'] === Database::VAR_STRING){
if($attribute['size'] > $maxIndexLength){
$size = $size === 0 || $size > $maxIndexLength ? $maxIndexLength : $size;
}
}

return $size;
}


/**
* This function fixes indexes which has exceeded max default limits
* with comparing the length of the string length of the collection attribute
*
* @param Document $index
* @param Document[] $attributes
* @return Document
* @throws Exception
*/
public function fixIndex(Document $index, array $attributes): Document {
foreach ($index->getAttribute('attributes') as $key => $indexAttribute) {

//Internal attributes do not have a real attribute
if(in_array($indexAttribute, ['$id', '$createdAt', '$updatedAt'])){
continue;
}

$attribute = $this->findAttributeInList($indexAttribute, $attributes);

$size = $index['lengths'][$key] ?? 0;
$max = 768; // 3072 divided by utf8mb4
if($attribute['type'] === Database::VAR_STRING){
if($attribute['size'] > $max){
$index['lengths'][$key] = $size === 0 || $size > $max ? $max : $size;
}
}
}

return $index;
}


}
1 change: 0 additions & 1 deletion src/Database/Adapter/SQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ public function renameIndex(string $collection, string $old, string $new): bool
* @param array $orders
* @return bool
* @throws Exception
* @throws PDOException
*/
public function createIndex(string $collection, string $id, string $type, array $attributes, array $lengths, array $orders): bool
{
Expand Down
Loading