99use Utopia \Database \Exception as DatabaseException ;
1010use Utopia \Database \Exception \Duplicate as DuplicateException ;
1111use Utopia \Database \Exception \NotFound as NotFoundException ;
12+ use Utopia \Database \Exception \Query as QueryException ;
1213use Utopia \Database \Exception \Timeout as TimeoutException ;
1314use Utopia \Database \Exception \Truncate as TruncateException ;
1415use Utopia \Database \Helpers \ID ;
@@ -409,16 +410,16 @@ public function getSchemaAttributes(string $collection): array
409410 * @param bool $signed
410411 * @param bool $array
411412 * @param string|null $newKey
413+ * @param bool $required
412414 * @return bool
413415 * @throws DatabaseException
414416 */
415- public function updateAttribute (string $ collection , string $ id , string $ type , int $ size , bool $ signed = true , bool $ array = false , ?string $ newKey = null ): bool
417+ public function updateAttribute (string $ collection , string $ id , string $ type , int $ size , bool $ signed = true , bool $ array = false , ?string $ newKey = null , bool $ required = false ): bool
416418 {
417419 $ name = $ this ->filter ($ collection );
418420 $ id = $ this ->filter ($ id );
419421 $ newKey = empty ($ newKey ) ? null : $ this ->filter ($ newKey );
420- $ type = $ this ->getSQLType ($ type , $ size , $ signed , $ array , false );
421-
422+ $ type = $ this ->getSQLType ($ type , $ size , $ signed , $ array , $ required );
422423 if (!empty ($ newKey )) {
423424 $ sql = "ALTER TABLE {$ this ->getSQLTable ($ name )} CHANGE COLUMN ` {$ id }` ` {$ newKey }` {$ type }; " ;
424425 } else {
@@ -1358,14 +1359,16 @@ public function deleteDocument(string $collection, string $id): bool
13581359 * @param Query $query
13591360 * @param array<string, mixed> $binds
13601361 * @param string $attribute
1362+ * @param string $type
13611363 * @param string $alias
13621364 * @param string $placeholder
13631365 * @return string
13641366 */
1365- protected function handleDistanceSpatialQueries (Query $ query , array &$ binds , string $ attribute , string $ alias , string $ placeholder ): string
1367+ protected function handleDistanceSpatialQueries (Query $ query , array &$ binds , string $ attribute , string $ type , string $ alias , string $ placeholder ): string
13661368 {
13671369 $ distanceParams = $ query ->getValues ()[0 ];
1368- $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ distanceParams [0 ]);
1370+ $ wkt = $ this ->convertArrayToWKT ($ distanceParams [0 ]);
1371+ $ binds [": {$ placeholder }_0 " ] = $ wkt ;
13691372 $ binds [": {$ placeholder }_1 " ] = $ distanceParams [1 ];
13701373
13711374 $ useMeters = isset ($ distanceParams [2 ]) && $ distanceParams [2 ] === true ;
@@ -1388,6 +1391,11 @@ protected function handleDistanceSpatialQueries(Query $query, array &$binds, str
13881391 }
13891392
13901393 if ($ useMeters ) {
1394+ $ wktType = $ this ->getSpatialTypeFromWKT ($ wkt );
1395+ $ attrType = strtolower ($ type );
1396+ if ($ wktType != Database::VAR_POINT || $ attrType != Database::VAR_POINT ) {
1397+ throw new QueryException ('Distance in meters is not supported between ' .$ attrType . ' and ' . $ wktType );
1398+ }
13911399 return "ST_DISTANCE_SPHERE( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0), 6371000) {$ operator } : {$ placeholder }_1 " ;
13921400 }
13931401 return "ST_Distance( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) {$ operator } : {$ placeholder }_1 " ;
@@ -1399,66 +1407,67 @@ protected function handleDistanceSpatialQueries(Query $query, array &$binds, str
13991407 * @param Query $query
14001408 * @param array<string, mixed> $binds
14011409 * @param string $attribute
1410+ * @param string $type
14021411 * @param string $alias
14031412 * @param string $placeholder
14041413 * @return string
14051414 */
1406- protected function handleSpatialQueries (Query $ query , array &$ binds , string $ attribute , string $ alias , string $ placeholder ): string
1415+ protected function handleSpatialQueries (Query $ query , array &$ binds , string $ attribute , string $ type , string $ alias , string $ placeholder ): string
14071416 {
14081417 switch ($ query ->getMethod ()) {
14091418 case Query::TYPE_CROSSES :
14101419 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1411- return "ST_Crosses( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1420+ return "ST_Crosses( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14121421
14131422 case Query::TYPE_NOT_CROSSES :
14141423 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1415- return "NOT ST_Crosses( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1424+ return "NOT ST_Crosses( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14161425
14171426 case Query::TYPE_DISTANCE_EQUAL :
14181427 case Query::TYPE_DISTANCE_NOT_EQUAL :
14191428 case Query::TYPE_DISTANCE_GREATER_THAN :
14201429 case Query::TYPE_DISTANCE_LESS_THAN :
1421- return $ this ->handleDistanceSpatialQueries ($ query , $ binds , $ attribute , $ alias , $ placeholder );
1430+ return $ this ->handleDistanceSpatialQueries ($ query , $ binds , $ attribute , $ type , $ alias , $ placeholder );
14221431
14231432 case Query::TYPE_INTERSECTS :
14241433 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1425- return "ST_Intersects( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1434+ return "ST_Intersects( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14261435
14271436 case Query::TYPE_NOT_INTERSECTS :
14281437 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1429- return "NOT ST_Intersects( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1438+ return "NOT ST_Intersects( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14301439
14311440 case Query::TYPE_OVERLAPS :
14321441 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1433- return "ST_Overlaps( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1442+ return "ST_Overlaps( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14341443
14351444 case Query::TYPE_NOT_OVERLAPS :
14361445 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1437- return "NOT ST_Overlaps( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1446+ return "NOT ST_Overlaps( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14381447
14391448 case Query::TYPE_TOUCHES :
14401449 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1441- return "ST_Touches( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1450+ return "ST_Touches( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14421451
14431452 case Query::TYPE_NOT_TOUCHES :
14441453 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1445- return "NOT ST_Touches( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1454+ return "NOT ST_Touches( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14461455
14471456 case Query::TYPE_EQUAL :
14481457 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1449- return "ST_Equals( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1458+ return "ST_Equals( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14501459
14511460 case Query::TYPE_NOT_EQUAL :
14521461 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1453- return "NOT ST_Equals( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1462+ return "NOT ST_Equals( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14541463
14551464 case Query::TYPE_CONTAINS :
14561465 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1457- return "ST_Contains( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1466+ return "ST_Contains( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14581467
14591468 case Query::TYPE_NOT_CONTAINS :
14601469 $ binds [": {$ placeholder }_0 " ] = $ this ->convertArrayToWKT ($ query ->getValues ()[0 ]);
1461- return "NOT ST_Contains( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0)) " ;
1470+ return "NOT ST_Contains( {$ alias }. {$ attribute }, ST_GeomFromText(: {$ placeholder }_0, 'axis-order=long-lat' )) " ;
14621471
14631472 default :
14641473 throw new DatabaseException ('Unknown spatial query method: ' . $ query ->getMethod ());
@@ -1487,7 +1496,7 @@ protected function getSQLCondition(Query $query, array &$binds, array $attribute
14871496 $ attributeType = $ this ->getAttributeType ($ query ->getAttribute (), $ attributes );
14881497
14891498 if (in_array ($ attributeType , Database::SPATIAL_TYPES )) {
1490- return $ this ->handleSpatialQueries ($ query , $ binds , $ attribute , $ alias , $ placeholder );
1499+ return $ this ->handleSpatialQueries ($ query , $ binds , $ attribute , $ attributeType , $ alias , $ placeholder );
14911500 }
14921501
14931502 switch ($ query ->getMethod ()) {
@@ -1632,13 +1641,39 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
16321641
16331642
16341643 case Database::VAR_POINT :
1635- return 'POINT ' . ($ required && !$ this ->getSupportForSpatialIndexNull () ? ' NOT NULL ' : '' );
1644+ $ type = 'POINT ' ;
1645+ if (!$ this ->getSupportForSpatialIndexNull ()) {
1646+ if ($ required ) {
1647+ $ type .= ' NOT NULL ' ;
1648+ } else {
1649+ $ type .= ' NULL ' ;
1650+ }
1651+ }
1652+ return $ type ;
16361653
16371654 case Database::VAR_LINESTRING :
1638- return 'LINESTRING ' . ($ required && !$ this ->getSupportForSpatialIndexNull () ? ' NOT NULL ' : '' );
1655+ $ type = 'LINESTRING ' ;
1656+ if (!$ this ->getSupportForSpatialIndexNull ()) {
1657+ if ($ required ) {
1658+ $ type .= ' NOT NULL ' ;
1659+ } else {
1660+ $ type .= ' NULL ' ;
1661+ }
1662+ }
1663+ return $ type ;
1664+
16391665
16401666 case Database::VAR_POLYGON :
1641- return 'POLYGON ' . ($ required && !$ this ->getSupportForSpatialIndexNull () ? ' NOT NULL ' : '' );
1667+ $ type = 'POLYGON ' ;
1668+ if (!$ this ->getSupportForSpatialIndexNull ()) {
1669+ if ($ required ) {
1670+ $ type .= ' NOT NULL ' ;
1671+ } else {
1672+ $ type .= ' NULL ' ;
1673+ }
1674+ }
1675+ return $ type ;
1676+
16421677
16431678 default :
16441679 throw new DatabaseException ('Unknown type: ' . $ type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON );
@@ -1868,4 +1903,14 @@ public function getSupportForSpatialIndexOrder(): bool
18681903 {
18691904 return true ;
18701905 }
1906+
1907+ /**
1908+ * Does the adapter support calculating distance(in meters) between multidimension geometry(line, polygon,etc)?
1909+ *
1910+ * @return bool
1911+ */
1912+ public function getSupportForDistanceBetweenMultiDimensionGeometryInMeters (): bool
1913+ {
1914+ return false ;
1915+ }
18711916}
0 commit comments