pr followups

This commit is contained in:
ArnabChatterjee20k
2025-09-02 23:00:31 +05:30
parent 1112058689
commit 8f7085ccfc
9 changed files with 414 additions and 63 deletions
Generated
+127 -42
View File
@@ -2599,16 +2599,16 @@
},
{
"name": "symfony/http-client",
"version": "v7.3.2",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
"reference": "1c064a0c67749923483216b081066642751cc2c7"
"reference": "333b9bd7639cbdaecd25a3a48a9d2dcfaa86e019"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/1c064a0c67749923483216b081066642751cc2c7",
"reference": "1c064a0c67749923483216b081066642751cc2c7",
"url": "https://api.github.com/repos/symfony/http-client/zipball/333b9bd7639cbdaecd25a3a48a9d2dcfaa86e019",
"reference": "333b9bd7639cbdaecd25a3a48a9d2dcfaa86e019",
"shasum": ""
},
"require": {
@@ -2616,6 +2616,7 @@
"psr/log": "^1|^2|^3",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/http-client-contracts": "~3.4.4|^3.5.2",
"symfony/polyfill-php83": "^1.29",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
@@ -2674,7 +2675,7 @@
"http"
],
"support": {
"source": "https://github.com/symfony/http-client/tree/v7.3.2"
"source": "https://github.com/symfony/http-client/tree/v7.3.3"
},
"funding": [
{
@@ -2694,7 +2695,7 @@
"type": "tidelift"
}
],
"time": "2025-07-15T11:36:08+00:00"
"time": "2025-08-27T07:45:05+00:00"
},
{
"name": "symfony/http-client-contracts",
@@ -2939,6 +2940,86 @@
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php83",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php83.git",
"reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5",
"reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php83\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-07-08T02:45:35+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v3.6.0",
@@ -3557,16 +3638,16 @@
},
{
"name": "utopia-php/database",
"version": "1.2.2",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "d59a207c079cc9e821ee4cab045a411bdad79e8c"
"reference": "06ffa2b1c977f5451200a1ee82a500be1390a789"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/d59a207c079cc9e821ee4cab045a411bdad79e8c",
"reference": "d59a207c079cc9e821ee4cab045a411bdad79e8c",
"url": "https://api.github.com/repos/utopia-php/database/zipball/06ffa2b1c977f5451200a1ee82a500be1390a789",
"reference": "06ffa2b1c977f5451200a1ee82a500be1390a789",
"shasum": ""
},
"require": {
@@ -3607,9 +3688,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/1.2.2"
"source": "https://github.com/utopia-php/database/tree/1.3.0"
},
"time": "2025-08-27T11:27:06+00:00"
"time": "2025-09-02T16:20:02+00:00"
},
{
"name": "utopia-php/detector",
@@ -4109,16 +4190,16 @@
},
{
"name": "utopia-php/migration",
"version": "1.0.0",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "0e4499d9dd2c90c2be188cc5fb7a32d9a892b569"
"reference": "38171023efd3abe650d2abc5ac65f5df52311da6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/0e4499d9dd2c90c2be188cc5fb7a32d9a892b569",
"reference": "0e4499d9dd2c90c2be188cc5fb7a32d9a892b569",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/38171023efd3abe650d2abc5ac65f5df52311da6",
"reference": "38171023efd3abe650d2abc5ac65f5df52311da6",
"shasum": ""
},
"require": {
@@ -4159,9 +4240,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/1.0.0"
"source": "https://github.com/utopia-php/migration/tree/1.0.1"
},
"time": "2025-08-13T09:15:53+00:00"
"time": "2025-08-28T13:41:25+00:00"
},
{
"name": "utopia-php/orchestration",
@@ -7410,16 +7491,16 @@
},
{
"name": "symfony/console",
"version": "v7.3.2",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1"
"reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1",
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1",
"url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7",
"reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7",
"shasum": ""
},
"require": {
@@ -7484,7 +7565,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.3.2"
"source": "https://github.com/symfony/console/tree/v7.3.3"
},
"funding": [
{
@@ -7504,7 +7585,7 @@
"type": "tidelift"
}
],
"time": "2025-07-30T17:13:41+00:00"
"time": "2025-08-25T06:35:40+00:00"
},
{
"name": "symfony/filesystem",
@@ -7646,16 +7727,16 @@
},
{
"name": "symfony/options-resolver",
"version": "v7.3.2",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37"
"reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/119bcf13e67dbd188e5dbc74228b1686f66acd37",
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
"reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
"shasum": ""
},
"require": {
@@ -7693,7 +7774,7 @@
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v7.3.2"
"source": "https://github.com/symfony/options-resolver/tree/v7.3.3"
},
"funding": [
{
@@ -7713,7 +7794,7 @@
"type": "tidelift"
}
],
"time": "2025-07-15T11:36:08+00:00"
"time": "2025-08-05T10:16:07+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -8047,16 +8128,16 @@
},
{
"name": "symfony/process",
"version": "v7.3.0",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af"
"reference": "32241012d521e2e8a9d713adb0812bb773b907f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
"reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
"url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1",
"reference": "32241012d521e2e8a9d713adb0812bb773b907f1",
"shasum": ""
},
"require": {
@@ -8088,7 +8169,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v7.3.0"
"source": "https://github.com/symfony/process/tree/v7.3.3"
},
"funding": [
{
@@ -8099,25 +8180,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-17T09:11:12+00:00"
"time": "2025-08-18T09:42:54+00:00"
},
{
"name": "symfony/string",
"version": "v7.3.2",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca"
"reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca",
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca",
"url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
"reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
"shasum": ""
},
"require": {
@@ -8175,7 +8260,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v7.3.2"
"source": "https://github.com/symfony/string/tree/v7.3.3"
},
"funding": [
{
@@ -8195,7 +8280,7 @@
"type": "tidelift"
}
],
"time": "2025-07-10T08:47:49+00:00"
"time": "2025-08-25T06:35:40+00:00"
},
{
"name": "textalk/websocket",
@@ -64,7 +64,7 @@ class Update extends Action
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for attribute when not provided, as JSON string. Cannot be set when attribute is required.',true)
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for attribute when not provided, as JSON string. Cannot be set when attribute is required.', true)
->param('newKey', null, new Key(), 'New attribute key.', true)
->inject('response')
->inject('dbForProject')
@@ -56,7 +56,7 @@ class Create extends PointCreate
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreate).')
->param('key', '', new Key(), 'Column Key.')
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for column when not provided, as JSON string. Cannot be set when column is required.',true)
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for column when not provided, as JSON string. Cannot be set when column is required.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
@@ -58,7 +58,7 @@ class Update extends PointUpdate
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreate).')
->param('key', '', new Key(), 'Column Key.')
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for column when not provided, as JSON string. Cannot be set when column is required.',true)
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for column when not provided, as JSON string. Cannot be set when column is required.', true)
->param('newKey', null, new Key(), 'New Column Key.', true)
->inject('response')
->inject('dbForProject')
@@ -57,7 +57,6 @@ class Create extends PolygonCreate
->param('key', '', new Key(), 'Column Key.')
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POLYGON)), 'Default value for column when not provided, as JSON string. Cannot be set when column is required.', true)
->param('array', false, new Boolean(), 'Is column an array?', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
@@ -7572,4 +7572,159 @@ trait DatabasesBase
'x-appwrite-key' => $this->getProject()['apiKey']
]));
}
public function testSpatialDistanceInMeter(): void
{
$database = $this->client->call(Client::METHOD_POST, '/databases', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
], [
'databaseId' => ID::unique(),
'name' => 'Spatial Distance Meters Database'
]);
$databaseId = $database['body']['$id'];
// Create collection with spatial attribute
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'collectionId' => ID::unique(),
'name' => 'Spatial Distance Meters Collection',
'documentSecurity' => true,
'permissions' => [
Permission::create(Role::any()),
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]);
$collectionId = $collection['body']['$id'];
// Create point attribute
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/point', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'key' => 'loc',
'required' => true,
]);
$this->assertEquals(202, $response['headers']['status-code']);
sleep(2);
// Create spatial index
$indexResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'key' => 'idx_loc',
'type' => Database::INDEX_SPATIAL,
'attributes' => ['loc'],
]);
sleep(2);
$this->assertEquals(202, $indexResponse['headers']['status-code']);
// Two points roughly ~1000 meters apart by latitude delta (~0.009 deg ≈ 1km)
$p0 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'p0',
'data' => [
'loc' => [0.0000, 0.0000]
]
]);
$p1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'p1',
'data' => [
'loc' => [0.0090, 0.0000]
]
]);
$this->assertEquals(201, $p0['headers']['status-code']);
$this->assertEquals(201, $p1['headers']['status-code']);
// distanceLessThan with meters=true: within 1500m should include both
$within1_5km = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::distanceLessThan('loc', [0.0000, 0.0000], 1500, true)->toString()]
]);
$this->assertEquals(200, $within1_5km['headers']['status-code']);
$this->assertCount(2, $within1_5km['body']['documents']);
// Within 500m should include only p0 (exact point)
$within500m = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::distanceLessThan('loc', [0.0000, 0.0000], 500, true)->toString()]
]);
$this->assertEquals(200, $within500m['headers']['status-code']);
$this->assertCount(1, $within500m['body']['documents']);
$this->assertEquals('p0', $within500m['body']['documents'][0]['$id']);
// distanceGreaterThan 500m should include only p1
$greater500m = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::distanceGreaterThan('loc', [0.0000, 0.0000], 500, true)->toString()]
]);
$this->assertEquals(200, $greater500m['headers']['status-code']);
$this->assertCount(1, $greater500m['body']['documents']);
$this->assertEquals('p1', $greater500m['body']['documents'][0]['$id']);
// distanceEqual with 0m should return exact match p0
$equalZero = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::distanceEqual('loc', [0.0000, 0.0000], 0, true)->toString()]
]);
$this->assertEquals(200, $equalZero['headers']['status-code']);
$this->assertEquals('p0', $equalZero['body']['documents'][0]['$id']);
// distanceNotEqual with 0m should return p1
$notEqualZero = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::distanceNotEqual('loc', [0.0000, 0.0000], 0, true)->toString()]
]);
$this->assertEquals(200, $notEqualZero['headers']['status-code']);
$this->assertEquals('p1', $notEqualZero['body']['documents'][0]['$id']);
// Cleanup
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
}
}
@@ -6406,20 +6406,14 @@ class DatabasesCustomServerTest extends Scope
[
'$id' => ID::unique(),
'name' => 'Invalid Point',
'location' => [1000.0, 2000.0], // Invalid coordinates
'area' => [
[10.0, 20.0],
[11.0, 20.0],
[11.0, 21.0],
[10.0, 21.0],
[10.0, 20.0]
]
'location' => [1000.0, 2000.0],
'area' => [10.0 , 10.0]
]
],
]);
// Coordinates are not validated strictly; creation should succeed
$this->assertEquals(201, $response['headers']['status-code']);
// invalid polygon
$this->assertEquals(400, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([
'content-type' => 'application/json',
@@ -6438,7 +6432,7 @@ class DatabasesCustomServerTest extends Scope
],
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertEquals(400, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([
'content-type' => 'application/json',
@@ -6720,8 +6714,7 @@ class DatabasesCustomServerTest extends Scope
],
]);
// Single point linestrings are accepted as arrays; creation should succeed
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertEquals(400, $response['headers']['status-code']);
// Cleanup
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
@@ -8106,7 +8106,31 @@ trait DatabasesBase
'type' => Database::INDEX_SPATIAL,
'columns' => ['pOptional'],
]);
$this->assertEquals(202, $badIndex['headers']['status-code']);
$this->assertEquals(400, $badIndex['headers']['status-code']);
// making it required to create index on it
$updated = $this->client->call(Client::METHOD_PATCH, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/point/'.'pOptional', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'required' => true,
'default' => null
]);
$this->assertEquals(200, $updated['headers']['status-code']);
sleep(2);
$retriedIndex = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'key' => 'idx_optional_point',
'type' => Database::INDEX_SPATIAL,
'columns' => ['pOptional'],
]);
$this->assertEquals(202, $retriedIndex['headers']['status-code']);
// Passing orders to spatial index should not throw error (in case of mariadb)
$ordersIndex = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([
@@ -8292,4 +8316,100 @@ trait DatabasesBase
'x-appwrite-key' => $this->getProject()['apiKey']
]));
}
public function testSpatialDistanceInMeter(): void
{
$headers = [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
];
// Create database
$database = $this->client->call(Client::METHOD_POST, '/tablesdb', $headers, [
'databaseId' => ID::unique(),
'name' => 'Spatial Distance Meters Database'
]);
$databaseId = $database['body']['$id'];
// Create table
$table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", $headers, [
'tableId' => ID::unique(),
'name' => 'Spatial Distance Meters Table',
'rowSecurity' => true,
'permissions' => [
Permission::create(Role::any()),
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]);
$tableId = $table['body']['$id'];
// Create point column
$resp = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/point", $headers, [
'key' => 'loc',
'required' => true,
]);
$this->assertEquals(202, $resp['headers']['status-code']);
sleep(2);
// Create spatial index
$indexResp = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/indexes", $headers, [
'key' => 'idx_loc',
'type' => Database::INDEX_SPATIAL,
'columns' => ['loc'],
]);
$this->assertEquals(202, $indexResp['headers']['status-code']);
// Insert two points ~1km apart
$points = [
'p0' => [0.0000, 0.0000],
'p1' => [0.0090, 0.0000]
];
foreach ($points as $id => $loc) {
$rowResp = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", $headers, [
'rowId' => $id,
'data' => ['loc' => $loc]
]);
$this->assertEquals(201, $rowResp['headers']['status-code']);
}
// Queries
$queries = [
'within1_5km' => Query::distanceLessThan('loc', [0.0, 0.0], 1500, true),
'within500m' => Query::distanceLessThan('loc', [0.0, 0.0], 500, true),
'greater500m' => Query::distanceGreaterThan('loc', [0.0, 0.0], 500, true),
'equal0m' => Query::distanceEqual('loc', [0.0, 0.0], 0, true),
'notEqual0m' => Query::distanceNotEqual('loc', [0.0, 0.0], 0, true),
];
// Assertions
$results = [
'within1_5km' => 2,
'within500m' => 1,
'greater500m' => 1,
'equal0m' => 'p0',
'notEqual0m' => 'p1'
];
foreach ($queries as $key => $query) {
$resp = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", $headers, [
'queries' => [$query->toString()]
]);
$this->assertEquals(200, $resp['headers']['status-code']);
if (is_int($results[$key])) {
$this->assertCount($results[$key], $resp['body']['rows']);
} else {
$this->assertEquals($results[$key], $resp['body']['rows'][0]['$id']);
}
}
// Cleanup
$this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}", $headers);
$this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}", $headers);
}
}
@@ -6399,7 +6399,7 @@ class DatabasesCustomServerTest extends Scope
],
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertEquals(400, $response['headers']['status-code']);
// Test 4c: Missing required location (should fail)
$response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([
@@ -6682,8 +6682,7 @@ class DatabasesCustomServerTest extends Scope
],
]);
// Single point linestrings are accepted as arrays; creation should succeed
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertEquals(400, $response['headers']['status-code']);
// Cleanup
$this->client->call(Client::METHOD_DELETE, '/tablesdb/' . $databaseId . '/tables/' . $tableId, array_merge([