88use Utopia \Database \Query ;
99use Utopia \Database \QueryContext ;
1010use Utopia \Database \Validator \Alias as AliasValidator ;
11+ use Utopia \Database \Validator \AsQuery as AsValidator ;
1112use Utopia \Database \Validator \Datetime as DatetimeValidator ;
1213use Utopia \Database \Validator \Query \Cursor ;
1314use 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 );
0 commit comments