Skip to content

Commit 735e0d3

Browse files
committed
Comment ambiguous
1 parent 2f2a64a commit 735e0d3

File tree

5 files changed

+299
-126
lines changed

5 files changed

+299
-126
lines changed

src/Database/Validator/AsQuery.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace Utopia\Database\Validator;
4+
5+
use Utopia\Validator;
6+
7+
class AsQuery extends Validator
8+
{
9+
protected string $message = '"as" must contain at most 64 chars. Valid chars are a-z, A-Z, 0-9, and underscore.';
10+
11+
/**
12+
* @param string $attribute
13+
*/
14+
public function __construct(
15+
private readonly string $attribute,
16+
)
17+
{
18+
19+
}
20+
21+
/**
22+
* Validator Description.
23+
* @return string
24+
*/
25+
public function getDescription(): string
26+
{
27+
return $this->message;
28+
}
29+
30+
/**
31+
* Is valid.
32+
* Returns true if valid or false if not.
33+
* @param mixed $value
34+
* @return bool
35+
*/
36+
public function isValid($value): bool
37+
{
38+
if (! \is_string($value)) {
39+
return false;
40+
}
41+
42+
if (empty($value)) {
43+
return true;
44+
}
45+
46+
if (! preg_match('/^[a-zA-Z0-9_]+$/', $value)) {
47+
return false;
48+
}
49+
50+
if (\mb_strlen($value) >= 64) {
51+
return false;
52+
}
53+
54+
if($this->attribute === '*'){
55+
$this->message = 'Invalid "as" on attribute "*"';
56+
return false;
57+
}
58+
59+
return true;
60+
}
61+
62+
/**
63+
* Is array
64+
*
65+
* Function will return true if object is array.
66+
*
67+
* @return bool
68+
*/
69+
public function isArray(): bool
70+
{
71+
return false;
72+
}
73+
74+
/**
75+
* Get Type
76+
*
77+
* Returns validator type.
78+
*
79+
* @return string
80+
*/
81+
public function getType(): string
82+
{
83+
return self::TYPE_STRING;
84+
}
85+
}

src/Database/Validator/Queries/V2.php

Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Utopia\Database\Query;
99
use Utopia\Database\QueryContext;
1010
use Utopia\Database\Validator\Alias as AliasValidator;
11+
use Utopia\Database\Validator\AsQuery as AsValidator;
1112
use Utopia\Database\Validator\Datetime as DatetimeValidator;
1213
use Utopia\Database\Validator\Query\Cursor;
1314
use Utopia\Database\Validator\Query\Limit;
@@ -134,6 +135,8 @@ public function isValid($value, string $scope = ''): bool
134135
throw new \Exception('Queries count is greater than '.$this->maxQueriesCount);
135136
}
136137

138+
$ambiguous = [];
139+
$duplications = [];
137140
foreach ($value as $query) {
138141
if (!$query instanceof Query) {
139142
try {
@@ -212,8 +215,6 @@ public function isValid($value, string $scope = ''): bool
212215
case Query::TYPE_INNER_JOIN:
213216
case Query::TYPE_LEFT_JOIN:
214217
case Query::TYPE_RIGHT_JOIN:
215-
var_dump('=== Query::TYPE_JOIN ===');
216-
var_dump($query);
217218
$this->validateFilterQueries($query);
218219

219220
if (! self::isValid($query->getValues(), 'joins')) {
@@ -233,8 +234,6 @@ public function isValid($value, string $scope = ''): bool
233234
throw new \Exception('Invalid query: Relations are only valid within joins.');
234235
}
235236

236-
var_dump('=== Query::TYPE_RELATION ===');
237-
var_dump($query);
238237
$this->validateAttributeExist($query->getAttribute(), $query->getAlias());
239238
$this->validateAttributeExist($query->getAttributeRight(), $query->getRightAlias());
240239

@@ -254,8 +253,43 @@ public function isValid($value, string $scope = ''): bool
254253

255254
break;
256255
case Query::TYPE_SELECT:
256+
$validator = new AsValidator($query->getAttribute());
257+
258+
if (! $validator->isValid($query->getAs())) {
259+
throw new \Exception('Invalid Query Select: '.$validator->getDescription());
260+
}
261+
257262
$this->validateSelect($query);
258263

264+
if($query->getAttribute() === '*'){
265+
$collection = $this->context->getCollectionByAlias($query->getAlias());
266+
$attributes = $this->schema[$collection->getId()];
267+
foreach ($attributes as $attribute){
268+
if (($duplications[$query->getAlias()][$attribute['$id']] ?? false) === true){
269+
//throw new \Exception('Ambiguous column using "*" for "'.$query->getAlias().'.'.$attribute['$id'].'"');
270+
}
271+
272+
$duplications[$query->getAlias()][$attribute['$id']] = true;
273+
}
274+
} else {
275+
if (($duplications[$query->getAlias()][$query->getAttribute()] ?? false) === true){
276+
//throw new \Exception('Duplicate Query Select on "'.$query->getAlias().'.'.$query->getAttribute().'"');
277+
}
278+
$duplications[$query->getAlias()][$query->getAttribute()] = true;
279+
}
280+
281+
if (!empty($query->getAs())){
282+
$needle = $query->getAs();
283+
} else {
284+
$needle = $query->getAttribute(); // todo: convert internal attribute from $id => _id
285+
}
286+
287+
if (in_array($needle, $ambiguous)){
288+
//throw new \Exception('Invalid Query Select: ambiguous column "'.$needle.'"');
289+
}
290+
291+
$ambiguous[] = $needle;
292+
259293
break;
260294
case Query::TYPE_ORDER_ASC:
261295
case Query::TYPE_ORDER_DESC:
@@ -274,6 +308,7 @@ public function isValid($value, string $scope = ''): bool
274308
throw new \Exception('Invalid query: Method not found ');
275309
}
276310
}
311+
277312
} catch (\Throwable $e) {
278313
$this->message = $e->getMessage();
279314
var_dump($this->message);
@@ -336,6 +371,13 @@ protected function isEmpty(array $values): bool
336371
*/
337372
protected function validateAttributeExist(string $attributeId, string $alias): void
338373
{
374+
/**
375+
* This is for making query::select('$permissions')) pass
376+
*/
377+
if($attributeId === '$permissions' || $attributeId === '$collection'){
378+
return;
379+
}
380+
339381
var_dump('=== validateAttributeExist');
340382

341383
// if (\str_contains($attributeId, '.')) {
@@ -507,82 +549,44 @@ protected function validateValues(string $attributeId, string $alias, array $val
507549
*/
508550
public function validateSelect(Query $query): void
509551
{
552+
$asValidator = new AsValidator($query->getAttribute());
553+
if (! $asValidator->isValid($query->getAs())) {
554+
throw new \Exception('Query '.\ucfirst($query->getMethod()).': '.$asValidator->getDescription());
555+
}
556+
510557
$internalKeys = \array_map(
511558
fn ($attr) => $attr['$id'],
512559
Database::INTERNAL_ATTRIBUTES
513560
);
514561

515-
foreach ($query->getValues() as $attribute) {
516-
$alias = Query::DEFAULT_ALIAS; // todo: Fix this
562+
$attribute = $query->getAttribute();
517563

518-
var_dump($attribute);
564+
if ($attribute === '*') {
565+
return;
566+
}
519567

520-
/**
521-
* Special symbols with `dots`
522-
*/
568+
if (\in_array($attribute, $internalKeys)) {
569+
//return;
570+
}
571+
572+
$alias = $query->getAlias();
573+
574+
if (\str_contains($attribute, '.')) {
523575
if (\str_contains($attribute, '.')) {
524576
try {
577+
/**
578+
* Special symbols with `dots`
579+
*/
525580
$this->validateAttributeExist($attribute, $alias);
526-
527-
continue;
528-
529581
} catch (\Throwable $e) {
530582
/**
531583
* For relationships, just validate the top level.
532584
* Will validate each nested level during the recursive calls.
533585
*/
534586
$attribute = \explode('.', $attribute)[0];
587+
$this->validateAttributeExist($attribute, $alias);
535588
}
536589
}
537-
538-
/**
539-
* Skip internal attributes
540-
*/
541-
if (\in_array($attribute, $internalKeys)) {
542-
continue;
543-
}
544-
545-
if ($attribute === '*') {
546-
continue;
547-
}
548-
549-
$this->validateAttributeExist($attribute, $alias);
550-
}
551-
}
552-
553-
/**
554-
* @throws \Exception
555-
*/
556-
public function validateSelections(Query $query): void
557-
{
558-
$internalKeys = \array_map(fn ($attr) => $attr['$id'], Database::INTERNAL_ATTRIBUTES);
559-
560-
$alias = $query->getAlias();
561-
$attribute = $query->getAttribute();
562-
563-
/**
564-
* Special symbols with `dots`
565-
*/
566-
if (\str_contains($attribute, '.')) {
567-
try {
568-
$this->validateAttributeExist($attribute, $alias);
569-
570-
return;
571-
} catch (\Throwable $e) {
572-
/**
573-
* For relationships, just validate the top level.
574-
* Will validate each nested level during the recursive calls.
575-
*/
576-
$attribute = \explode('.', $attribute)[0];
577-
}
578-
}
579-
580-
if (\in_array($attribute, $internalKeys)) {
581-
return;
582-
}
583-
584-
if ($attribute === '*') {
585-
return;
586590
}
587591

588592
$this->validateAttributeExist($attribute, $alias);

tests/e2e/Adapter/Base.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818

1919
abstract class Base extends TestCase
2020
{
21+
//use JoinsTests;
2122
use CollectionTests;
2223
use DocumentTests;
2324
use AttributeTests;
2425
use IndexTests;
25-
use JoinsTests;
2626
use PermissionTests;
2727
use RelationshipTests;
2828
use GeneralTests;

0 commit comments

Comments
 (0)