Skip to content
Open

Joins #133

Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"ext-curl": "*",
"ext-openssl": "*",
"appwrite/appwrite": "19.*",
"utopia-php/database": "4.*",
"utopia-php/database": "dev-joins8 as 4.5.2",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Read the full composer.json to understand context
cat composer.json

Repository: utopia-php/migration

Length of output: 1443


🏁 Script executed:

# Search for any TODOs or comments related to database, joins, or dev branches
rg -i "(todo|fixme|track|cleanup|dev-joins|database.*dev)" --type json --type md --type txt

Repository: utopia-php/migration

Length of output: 233


🏁 Script executed:

# Check git log for recent changes to composer.json to understand the context
git log --oneline -10 composer.json 2>/dev/null || echo "No git history available"

Repository: utopia-php/migration

Length of output: 86


🏁 Script executed:

# Look for any documentation or README files that might explain the dependency
fd -t f "(README|CHANGELOG|CONTRIBUTING)" -x head -50 {}

Repository: utopia-php/migration

Length of output: 1725


🏁 Script executed:

# Check git commit details for the database dependency change
git log -1 --format="%B" 49bddeb 2>/dev/null || git show --format="%B" -s 49bddeb 2>/dev/null || echo "Unable to retrieve commit message"

Repository: utopia-php/migration

Length of output: 79


🏁 Script executed:

# Look for CHANGELOG or any documentation about planned changes
fd -t f "(CHANGELOG|CHANGES|RELEASE)" -x head -30 {}

Repository: utopia-php/migration

Length of output: 46


🏁 Script executed:

# Check if there are any comments in source files about the database version or joins functionality
rg -i "joins|database.*version" --type php src/ -B 2 -A 2 | head -50

Repository: utopia-php/migration

Length of output: 46


Remove the dev dependency before release.

This library uses dev-joins8 as 4.5.2 for the database package, which violates the "minimum-stability": "stable" requirement and will force consumers to accept an unreleased development branch. Once the joins8 branch is merged and released as a stable version in utopia-php/database, revert this to the stable version constraint (e.g., "4.*" or the specific tagged release).

Add a TODO comment in composer.json or create a tracking issue to ensure this change doesn't ship to production.

🤖 Prompt for AI Agents
In `@composer.json` at line 29, The composer.json currently pins
"utopia-php/database" to the dev branch ("dev-joins8 as 4.5.2"), which violates
"minimum-stability": "stable"; update the dependency in composer.json to a
stable constraint (e.g., "utopia-php/database": "4.*" or a specific released
tag) and remove the "dev-joins8 as 4.5.2" alias; also add a TODO comment in
composer.json (or create a tracking issue) referencing the joins8 branch and
reminding to switch back to the stable release once utopia-php/database
publishes the merged release.

"utopia-php/storage": "0.18.*",
"utopia-php/dsn": "0.2.*",
"utopia-php/console": "0.0.*"
Expand Down
94 changes: 51 additions & 43 deletions composer.lock

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

1 change: 1 addition & 0 deletions src/Migration/Resources/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function __construct(
* updatedAt: string,
* enabled: bool,
* originalId: string|null,
* type: string|null,
* } $array
*/
public static function fromArray(array $array): self
Expand Down
15 changes: 10 additions & 5 deletions src/Migration/Sources/Appwrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,11 @@ private function exportRows(int $batchSize): void
}

$selects = ['*', '$id', '$permissions', '$updatedAt', '$createdAt']; // We want relations flat!

foreach ($selects as $select) {
$queries[] = $this->database->querySelect($select);
}

$manyToMany = [];

$attributes = $this->cache->get(Column::getName());
Expand All @@ -1142,22 +1147,22 @@ private function exportRows(int $batchSize): void
}
/** @var Column|Relationship $attribute */

$queries[] = $this->database->querySelect($selects);

$response = $this->database->listRows($table, $queries);

foreach ($response as $row) {
// HACK: Handle many to many
if (!empty($manyToMany)) {
$stack = ['$id']; // Adding $id because we can't select only relations
$queries = [];
$queries[] = $this->database->querySelect('$id'); // Adding $id because we can't select only relations

foreach ($manyToMany as $relation) {
$stack[] = $relation . '.$id';
$queries[] = $this->database->querySelect($relation . '.$id');
}

$rowItem = $this->database->getRow(
$table,
$row['$id'],
[$this->database->querySelect($stack)]
$queries
);

foreach ($manyToMany as $key) {
Expand Down
5 changes: 3 additions & 2 deletions src/Migration/Sources/Appwrite/Reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Utopia\Migration\Sources\Appwrite;

use Utopia\Database\Query;
use Utopia\Migration\Resource;
use Utopia\Migration\Resources\Database\Database;
use Utopia\Migration\Resources\Database\Table;
Expand Down Expand Up @@ -78,10 +79,10 @@ public function getRow(Table $resource, string $rowId, array $queries = []): arr
/**
* Return a query to select the given attributes
*
* @param array $columns
* @param string $column
* @return QueryType|string
*/
public function querySelect(array $columns): mixed;
public function querySelect(string $column): mixed;
Comment on lines +82 to +85
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Interface signature change looks correct, but API.php implementation has issues.

The interface change from array $columns to string $column is consistent with the single-column query approach. However, based on the related code snippet from src/Migration/Sources/Appwrite/Reader/API.php (lines 217-225), the implementation has critical issues:

  1. Return type mismatch: Method declares string return type but returns new Query('select', $column) which is an object
  2. Unreachable code: There's a second return Query::select($column) after the first return statement that will never execute
public function querySelect(string $column): string
{
    return new Query('select', $column);  // Returns Query object, not string

    /**
     * todo fix Query::select to get attribute not array
     */
    return Query::select($column);  // Unreachable
}

Please fix the API.php implementation to either return a string (e.g., the query string representation) or correct the return type declaration.

🤖 Prompt for AI Agents
In `@src/Migration/Sources/Appwrite/Reader.php` around lines 82 - 85, The
implementation of querySelect in API.php contradicts the Reader::querySelect
signature: either change the API.php method return type to match the actual
object being returned (return Query instance / QueryType) or change the body to
return a string representation; specifically, in API.php update the method
declaration for querySelect to return the correct type (e.g., Query or
QueryType) and return new Query('select', $column) (removing the unreachable
second return), or if you must keep a string return type, remove the new
Query(...) return and instead return Query::select($column) (ensuring
Query::select returns a string); eliminate the unreachable code and ensure the
declared return type matches the actual returned value (refer to
Reader::querySelect, API::querySelect, Query and Query::select).


/**
* Return a query to filter the given attributes
Expand Down
13 changes: 9 additions & 4 deletions src/Migration/Sources/Appwrite/Reader/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,17 @@ public function getRow(Table $resource, string $rowId, array $queries = []): arr
}

/**
* @param array $columns
* @return string
* @param string $column
* @return Query
*/
public function querySelect(array $columns): string
public function querySelect(string $column): string
{
return Query::select($columns);
return new Query('select', $column);

/**
* todo fix Query::select to get attribute not array
*/
return Query::select($column);
}
Comment on lines 214 to 226
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file structure and the actual code
find . -name "API.php" -path "*/Migration/Sources/Appwrite/Reader/*" | head -5

Repository: utopia-php/migration

Length of output: 111


🏁 Script executed:

# Check the exact code at those lines
if [ -f "src/Migration/Sources/Appwrite/Reader/API.php" ]; then
  sed -n '200,225p' src/Migration/Sources/Appwrite/Reader/API.php
fi

Repository: utopia-php/migration

Length of output: 601


🏁 Script executed:

# Look at similar methods in the same file to understand the pattern
if [ -f "src/Migration/Sources/Appwrite/Reader/API.php" ]; then
  rg -n "public function query" src/Migration/Sources/Appwrite/Reader/API.php -A 8
fi

Repository: utopia-php/migration

Length of output: 973


🏁 Script executed:

# Search for Appwrite Query imports or usage
rg -n "Query" src/Migration/Sources/Appwrite/Reader/API.php | head -20

Repository: utopia-php/migration

Length of output: 609


🏁 Script executed:

# Check what version of Appwrite is being used (composer.json)
if [ -f "composer.json" ]; then
  cat composer.json | jq '.require | select(. != null) | to_entries[] | select(.key | contains("appwrite"))'
fi

Repository: utopia-php/migration

Length of output: 115


🌐 Web query:

Appwrite PHP SDK 15.x Query class select method documentation

💡 Result:

The Query.select operator is documented on the Appwrite Queries page — it lets you specify which columns/relationship fields to return (you can pass a single name or an array). Use it with SDK list endpoints via the queries parameter. Example (PHP, Appwrite 15.x):

listDocuments( databaseId: '', collectionId: '', queries: [ Query::select(['name','email']), // select specific fields ] ); Docs: - Queries / Select operator (Appwrite docs). [1] - Databases PHP reference (showing use of queries parameter). [2] Sources: [1] https://appwrite.io/docs/products/databases/queries [2] https://appwrite.io/docs/references/cloud/server-php/databases --- 🌐 Web query: `Appwrite PHP SDK Query class static methods documentation` 💡 Result: Here are the main static query helper methods provided by Appwrite SDKs (available via Appwrite\Query in PHP). Use them to build the queries[] array passed to list/read endpoints: - Selection: select(...) - Comparison: equal(...), notEqual(...), less(...), lessEqual(...), greater(...), greaterEqual(...), between(...), notBetween(...) - Null checks: isNull(...), isNotNull(...) - String/array ops: startsWith(...), notStartsWith(...), endsWith(...), notEndsWith(...), contains(...), notContains(...), search(...), notSearch(...) - Logical: AND (by passing an array of subqueries), OR (multiple values in a method) - Ordering: orderAsc(...), orderDesc(...), orderRandom() - Pagination/cursors: limit(...), offset(...), cursorAfter(...), cursorBefore(...) - Time helpers: createdBefore(...), createdAfter(...), updatedBefore(...), updatedAfter(...) - Geo / spatial: distanceEqual(...), distanceNotEqual(...), distanceGreater(...), distanceLess(...), intersects(...), notIntersects(...), overlaps(...), notOverlaps(...), touches(...) - Others / patterns: (supports selecting relationship fields, wildcards, etc.) For full details, examples and exact signatures see the Appwrite Queries docs and the PHP quick-start examples. [1][2] Sources: [1] Appwrite — Queries documentation. [2] Appwrite — PHP quick start / Query examples. ---
**Critical: Return type mismatch, PHPDoc conflict, and incorrect implementation approach.** Multiple issues in this method: 1. **Type mismatch**: Method declares `: string` return type but returns `new Query('select', $column)`, which is a `Query` object, not a string. This will cause a fatal error at runtime. 2. **PHPDoc inconsistency**: `@return Query` conflicts with the native `: string` return type. 3. **Unreachable code**: Lines 215-218 after the first return statement will never execute. 4. **Incorrect implementation**: The constructor approach `new Query('select', $column)` creates an object. All other query methods in this class (e.g., `queryEqual`, `queryCursorAfter`, `queryLimit`) use the static Query methods (`Query::equal()`, `Query::cursorAfter()`, `Query::limit()`), which return strings. Use `Query::select($column)` instead.
Proposed fix ```diff /** * @param string $column - * @return Query + * @return string */ public function querySelect(string $column): string { - return new Query('select', $column); - - /** - * todo fix Query::select to get attribute not array - */ - return Query::select($column); + return Query::select($column); } ```
🧰 Tools
🪛 GitHub Actions: CodeQL [error] 211-211: PHPStan: PHPDoc tag @return with type Appwrite\Query is incompatible with native type string.
🤖 Prompt for AI Agents ``` In @src/Migration/Sources/Appwrite/Reader/API.php around lines 207 - 219, The querySelect method currently returns a Query object via new Query('select', $column) while its native signature declares : string and the PHPDoc says @return Query; replace the implementation to mirror other methods by returning the static string form Query::select($column), update the native return type to string (or adjust PHPDoc if you intentionally want a Query object), and remove the unreachable/new Query(...) code so querySelect consistently returns a string like the other query* methods. ```


/**
Expand Down
6 changes: 3 additions & 3 deletions src/Migration/Sources/Appwrite/Reader/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -360,12 +360,12 @@ public function getRow(TableResource $resource, string $rowId, array $queries =
}

/**
* @param array $columns
* @param string $column
* @return Query
*/
public function querySelect(array $columns): Query
public function querySelect(string $column): Query
{
return Query::select($columns);
return Query::select($column);
}
Comment on lines 362 to 369
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for Query class definition and select method
find . -type f -name "*.php" | head -20 | xargs grep -l "class Query" 2>/dev/null | grep -v node_modules | grep -v vendor

Repository: utopia-php/migration

Length of output: 46


🏁 Script executed:

# Search for select method in Query class more broadly
rg "class Query|function select\(|public static function select" --type php -A 3 -B 1 | head -100

Repository: utopia-php/migration

Length of output: 46


🏁 Script executed:

# Look for Query import in the Database.php file to understand where it comes from
rg "use.*Query|import.*Query" src/Migration/Sources/Appwrite/Reader/Database.php

Repository: utopia-php/migration

Length of output: 90


🏁 Script executed:

# Check composer.json for utopia-php/database dependency
cat composer.json | grep -A 2 -B 2 "utopia-php/database" || head -30 composer.json

Repository: utopia-php/migration

Length of output: 255


🌐 Web query:

utopia-php/database Query::select method signature parameters

💡 Result:

Signature: Query::select(array $attributes) — accepts an array of attribute names to return (e.g. Query::select(['name','year'])). [1][2]

Sources:

  • Package README (utopia-php/database) — shows Query::select(attributes: ["...", "..."]). [1]
  • Package page (source repository link: github.com/utopia-php/database). [2]

Fix Query::select() parameter: pass column name as array.

The implementation passes a single string to Query::select(), but the utopia-php/database API expects an array of column names. Change line 368 to:

return Query::select([$column]);
🤖 Prompt for AI Agents
In `@src/Migration/Sources/Appwrite/Reader/Database.php` around lines 362 - 369,
The method querySelect currently calls Query::select with a string; change it to
pass an array containing the column name so the utopia-php/database API is used
correctly: update the return in querySelect to call Query::select with [$column]
instead of $column, keeping the method signature and return type intact.


/**
Expand Down
Loading