Skip to content

Commit 2e13987

Browse files
Merge pull request #96 from utopia-php/feat-database-and-namespace
Feat: namespace as table prefixes
2 parents 61e32be + a041dd2 commit 2e13987

11 files changed

Lines changed: 320 additions & 87 deletions

File tree

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Database/Adapter.php

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ abstract class Adapter
1111
*/
1212
protected $namespace = '';
1313

14+
/**
15+
* @var string
16+
*/
17+
protected $defaultDatabase = '';
18+
1419
/**
1520
* @var array
1621
*/
@@ -64,7 +69,7 @@ public function setNamespace(string $namespace): bool
6469
throw new Exception('Missing namespace');
6570
}
6671

67-
$this->namespace = $namespace;
72+
$this->namespace = $this->filter($namespace);
6873

6974
return true;
7075
}
@@ -87,19 +92,62 @@ public function getNamespace(): string
8792
return $this->namespace;
8893
}
8994

95+
/**
96+
* Set Database.
97+
*
98+
* Set database to use for current scope
99+
*
100+
* @param string $name
101+
* @param bool $reset
102+
*
103+
* @throws Exception
104+
*/
105+
public function setDefaultDatabase(string $name, bool $reset = false): bool
106+
{
107+
if (empty($name) && $reset === false) {
108+
throw new Exception('Missing database');
109+
}
110+
111+
$this->defaultDatabase = ($reset) ? '' : $this->filter($name);
112+
113+
return true;
114+
}
115+
116+
/**
117+
* Get Database.
118+
*
119+
* Get Database from current scope
120+
*
121+
* @throws Exception
122+
*
123+
* @return string
124+
*/
125+
public function getDefaultDatabase(): string
126+
{
127+
if (empty($this->defaultDatabase)) {
128+
throw new Exception('Missing database');
129+
}
130+
131+
return $this->defaultDatabase;
132+
}
133+
90134
/**
91135
* Create Database
92136
*
137+
* @param string $name
138+
*
93139
* @return bool
94140
*/
95-
abstract public function create(): bool;
141+
abstract public function create(string $name): bool;
96142

97143
/**
98144
* Check if database exists
99145
*
146+
* @param string $name
147+
*
100148
* @return bool
101149
*/
102-
abstract public function exists(): bool;
150+
abstract public function exists(string $name): bool;
103151

104152
/**
105153
* List Databases
@@ -111,9 +159,11 @@ abstract public function list(): array;
111159
/**
112160
* Delete Database
113161
*
162+
* @param string $name
163+
*
114164
* @return bool
115165
*/
116-
abstract public function delete(): bool;
166+
abstract public function delete(string $name): bool;
117167

118168
/**
119169
* Create Collection
@@ -376,7 +426,7 @@ abstract public function getSupportForCasting(): bool;
376426
*/
377427
public function filter(string $value):string
378428
{
379-
$value = preg_replace("/[^A-Za-z0-9]_/", '', $value);
429+
$value = preg_replace("/[^A-Za-z0-9\_\-\.]/", '', $value);
380430

381431
if(\is_null($value)) {
382432
throw new Exception('Failed to filter key');

src/Database/Adapter/MariaDB.php

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,30 @@ public function __construct($pdo)
3333

3434
/**
3535
* Create Database
36+
*
37+
* @param string $name
3638
*
3739
* @return bool
3840
*/
39-
public function create(): bool
41+
public function create(string $name): bool
4042
{
41-
$name = $this->getNamespace();
43+
$name = $this->filter($name);
4244

4345
return $this->getPDO()
44-
->prepare("CREATE DATABASE {$name} /*!40100 DEFAULT CHARACTER SET utf8mb4 */;")
46+
->prepare("CREATE DATABASE IF NOT EXISTS `{$name}` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;")
4547
->execute();
4648
}
4749

4850
/**
4951
* Check if database exists
5052
*
53+
* @param string $name
54+
*
5155
* @return bool
5256
*/
53-
public function exists(): bool
57+
public function exists(string $name): bool
5458
{
55-
$name = $this->getNamespace();
59+
$name = $this->filter($name);
5660

5761
$stmt = $this->getPDO()
5862
->prepare("SELECT SCHEMA_NAME
@@ -62,7 +66,7 @@ public function exists(): bool
6266
$stmt->bindValue(':schema', $name, PDO::PARAM_STR);
6367

6468
$stmt->execute();
65-
69+
6670
$document = $stmt->fetch(PDO::FETCH_ASSOC);
6771

6872
return (($document['SCHEMA_NAME'] ?? '') == $name);
@@ -82,14 +86,16 @@ public function list(): array
8286
/**
8387
* Delete Database
8488
*
89+
* @param string $name
90+
*
8591
* @return bool
8692
*/
87-
public function delete(): bool
93+
public function delete(string $name): bool
8894
{
89-
$name = $this->getNamespace();
95+
$name = $this->filter($name);
9096

9197
return $this->getPDO()
92-
->prepare("DROP DATABASE {$name};")
98+
->prepare("DROP DATABASE `{$name}`;")
9399
->execute();
94100
}
95101

@@ -103,11 +109,13 @@ public function delete(): bool
103109
*/
104110
public function createCollection(string $name, array $attributes = [], array $indexes = []): bool
105111
{
112+
$database = $this->getDefaultDatabase();
113+
$namespace = $this->getNamespace();
106114
$id = $this->filter($name);
107115

108116
if (!empty($attributes) || !empty($indexes)) {
109117
foreach ($attributes as &$attribute) {
110-
$attrId = $attribute->getId();
118+
$attrId = $this->filter($attribute->getId());
111119
$attrType = $this->getSQLType($attribute->getAttribute('type'), $attribute->getAttribute('size', 0), $attribute->getAttribute('signed', true));
112120

113121
if($attribute->getAttribute('array')) {
@@ -140,7 +148,7 @@ public function createCollection(string $name, array $attributes = [], array $in
140148
}
141149

142150
$this->getPDO()
143-
->prepare("CREATE TABLE IF NOT EXISTS {$this->getNamespace()}.{$id} (
151+
->prepare("CREATE TABLE IF NOT EXISTS `{$database}`.`{$namespace}_{$id}` (
144152
`_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
145153
`_uid` CHAR(255) NOT NULL,
146154
`_read` " . $this->getTypeForReadPermission() . " NOT NULL,
@@ -154,7 +162,7 @@ public function createCollection(string $name, array $attributes = [], array $in
154162

155163
} else {
156164
$this->getPDO()
157-
->prepare("CREATE TABLE IF NOT EXISTS {$this->getNamespace()}.{$id} (
165+
->prepare("CREATE TABLE IF NOT EXISTS `{$database}`.`{$namespace}_{$id}` (
158166
`_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
159167
`_uid` CHAR(255) NOT NULL,
160168
`_read` " . $this->getTypeForReadPermission() . " NOT NULL,
@@ -180,7 +188,7 @@ public function deleteCollection(string $id): bool
180188
$id = $this->filter($id);
181189

182190
return $this->getPDO()
183-
->prepare("DROP TABLE {$this->getNamespace()}.{$id};")
191+
->prepare("DROP TABLE `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$id}`;")
184192
->execute();
185193
}
186194

@@ -206,7 +214,7 @@ public function createAttribute(string $collection, string $id, string $type, in
206214
}
207215

208216
return $this->getPDO()
209-
->prepare("ALTER TABLE {$this->getNamespace()}.{$name}
217+
->prepare("ALTER TABLE `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
210218
ADD COLUMN `{$id}` {$type};")
211219
->execute();
212220
}
@@ -226,7 +234,7 @@ public function deleteAttribute(string $collection, string $id, bool $array = fa
226234
$id = $this->filter($id);
227235

228236
return $this->getPDO()
229-
->prepare("ALTER TABLE {$this->getNamespace()}.{$name}
237+
->prepare("ALTER TABLE `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
230238
DROP COLUMN `{$id}`;")
231239
->execute();
232240
}
@@ -280,7 +288,7 @@ public function deleteIndex(string $collection, string $id): bool
280288
$id = $this->filter($id);
281289

282290
return $this->getPDO()
283-
->prepare("ALTER TABLE {$this->getNamespace()}.{$name}
291+
->prepare("ALTER TABLE `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
284292
DROP INDEX `{$id}`;")
285293
->execute();
286294
}
@@ -297,7 +305,8 @@ public function getDocument(string $collection, string $id): Document
297305
{
298306
$name = $this->filter($collection);
299307

300-
$stmt = $this->getPDO()->prepare("SELECT * FROM {$this->getNamespace()}.{$name}
308+
$stmt = $this->getPDO()->prepare("SELECT *
309+
FROM `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
301310
WHERE _uid = :_uid
302311
LIMIT 1;
303312
");
@@ -351,7 +360,7 @@ public function createDocument(string $collection, Document $document): Document
351360
}
352361

353362
$stmt = $this->getPDO()
354-
->prepare("INSERT INTO {$this->getNamespace()}.{$name}
363+
->prepare("INSERT INTO `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
355364
SET {$columns} _uid = :_uid, _read = :_read, _write = :_write");
356365

357366
$stmt->bindValue(':_uid', $document->getId(), PDO::PARAM_STR);
@@ -416,7 +425,7 @@ public function updateDocument(string $collection, Document $document): Document
416425
}
417426

418427
$stmt = $this->getPDO()
419-
->prepare("UPDATE {$this->getNamespace()}.{$name}
428+
->prepare("UPDATE `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
420429
SET {$columns} _uid = :_uid, _read = :_read, _write = :_write WHERE _uid = :_uid");
421430

422431
$stmt->bindValue(':_uid', $document->getId(), PDO::PARAM_STR);
@@ -473,7 +482,7 @@ public function deleteDocument(string $collection, string $id): bool
473482
$this->getPDO()->beginTransaction();
474483

475484
$stmt = $this->getPDO()
476-
->prepare("DELETE FROM {$this->getNamespace()}.{$name}
485+
->prepare("DELETE FROM `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}`
477486
WHERE _uid = :_uid LIMIT 1");
478487

479488
$stmt->bindValue(':_uid', $id, PDO::PARAM_STR);
@@ -581,7 +590,7 @@ public function find(string $collection, array $queries = [], int $limit = 25, i
581590

582591
$order = 'ORDER BY '.implode(', ', $orders);
583592

584-
$stmt = $this->getPDO()->prepare("SELECT table_main.* FROM {$this->getNamespace()}.{$name} table_main
593+
$stmt = $this->getPDO()->prepare("SELECT table_main.* FROM `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}` table_main
585594
WHERE {$permissions} AND ".implode(' AND ', $where)."
586595
{$order}
587596
LIMIT :offset, :limit;
@@ -658,7 +667,7 @@ public function count(string $collection, array $queries = [], int $max = 0): in
658667
$where[] = empty($condition) ? '' : '('.$condition.')';
659668
}
660669

661-
$stmt = $this->getPDO()->prepare("SELECT COUNT(1) as sum FROM (SELECT 1 FROM {$this->getNamespace()}.{$name} table_main
670+
$stmt = $this->getPDO()->prepare("SELECT COUNT(1) as sum FROM (SELECT 1 FROM `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}` table_main
662671
WHERE {$permissions} AND ".implode(' AND ', $where)."
663672
{$limit}) table_count
664673
");
@@ -712,10 +721,13 @@ public function sum(string $collection, string $attribute, array $queries = [],
712721
$where[] = implode(' OR ', $conditions);
713722
}
714723

715-
$stmt = $this->getPDO()->prepare("SELECT SUM({$attribute}) as sum FROM (SELECT {$attribute} FROM {$this->getNamespace()}.{$name} table_main
716-
WHERE {$permissions} AND ".implode(' AND ', $where)."
717-
{$limit}) table_count
718-
");
724+
$stmt = $this->getPDO()->prepare("SELECT SUM({$attribute}) as sum
725+
FROM (
726+
SELECT {$attribute}
727+
FROM `{$this->getDefaultDatabase()}`.`{$this->getNamespace()}_{$name}` table_main
728+
WHERE {$permissions} AND ".implode(' AND ', $where)."
729+
{$limit}
730+
) table_count");
719731

720732
foreach($queries as $i => $query) {
721733
if($query->getOperator() === Query::TYPE_SEARCH) continue;
@@ -1140,7 +1152,7 @@ protected function getSQLIndex(string $collection, string $id, string $type, ar
11401152
break;
11411153
}
11421154

1143-
return 'CREATE '.$type.' '.$id.' ON '.$this->getNamespace().'.'.$collection.' ( '.implode(', ', $attributes).' );';
1155+
return 'CREATE '.$type.' '.$id.' ON `'.$this->getDefaultDatabase().'`.`'.$this->getNamespace().'_'.$collection.'` ( '.implode(', ', $attributes).' );';
11441156
}
11451157

11461158
/**

0 commit comments

Comments
 (0)