3030 */
3131class Postgres extends SQL
3232{
33+ public const MAX_IDENTIFIER_NAME = 63 ;
3334 /**
3435 * @inheritDoc
3536 */
@@ -244,17 +245,24 @@ public function createCollection(string $name, array $attributes = [], array $in
244245 " ;
245246
246247 if ($ this ->sharedTables ) {
248+ $ uidIndex = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ id }_uid " );
249+ $ createdIndex = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ id }_created " );
250+ $ updatedIndex = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ id }_updated " );
251+ $ tenantIdIndex = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ id }_tenant_id " );
247252 $ collection .= "
248- CREATE UNIQUE INDEX \"{$ namespace } _ { $ this -> tenant } _ { $ id } _uid \" ON {$ this ->getSQLTable ($ id )} ( \"_uid \" COLLATE utf8_ci_ai, \"_tenant \");
249- CREATE INDEX \"{$ namespace } _ { $ this -> tenant } _ { $ id } _created \" ON {$ this ->getSQLTable ($ id )} (_tenant, \"_createdAt \");
250- CREATE INDEX \"{$ namespace } _ { $ this -> tenant } _ { $ id } _updated \" ON {$ this ->getSQLTable ($ id )} (_tenant, \"_updatedAt \");
251- CREATE INDEX \"{$ namespace } _ { $ this -> tenant } _ { $ id } _tenant_id \" ON {$ this ->getSQLTable ($ id )} (_tenant, _id);
253+ CREATE UNIQUE INDEX \"{$ uidIndex } \" ON {$ this ->getSQLTable ($ id )} ( \"_uid \" COLLATE utf8_ci_ai, \"_tenant \");
254+ CREATE INDEX \"{$ createdIndex } \" ON {$ this ->getSQLTable ($ id )} (_tenant, \"_createdAt \");
255+ CREATE INDEX \"{$ updatedIndex } \" ON {$ this ->getSQLTable ($ id )} (_tenant, \"_updatedAt \");
256+ CREATE INDEX \"{$ tenantIdIndex } \" ON {$ this ->getSQLTable ($ id )} (_tenant, _id);
252257 " ;
253258 } else {
259+ $ uidIndex = $ this ->getShortKey ("{$ namespace }_ {$ id }_uid " );
260+ $ createdIndex = $ this ->getShortKey ("{$ namespace }_ {$ id }_created " );
261+ $ updatedIndex = $ this ->getShortKey ("{$ namespace }_ {$ id }_updated " );
254262 $ collection .= "
255- CREATE UNIQUE INDEX \"{$ namespace } _ { $ id } _uid \" ON {$ this ->getSQLTable ($ id )} ( \"_uid \" COLLATE utf8_ci_ai);
256- CREATE INDEX \"{$ namespace } _ { $ id } _created \" ON {$ this ->getSQLTable ($ id )} ( \"_createdAt \");
257- CREATE INDEX \"{$ namespace } _ { $ id } _updated \" ON {$ this ->getSQLTable ($ id )} ( \"_updatedAt \");
263+ CREATE UNIQUE INDEX \"{$ uidIndex } \" ON {$ this ->getSQLTable ($ id )} ( \"_uid \" COLLATE utf8_ci_ai);
264+ CREATE INDEX \"{$ createdIndex } \" ON {$ this ->getSQLTable ($ id )} ( \"_createdAt \");
265+ CREATE INDEX \"{$ updatedIndex } \" ON {$ this ->getSQLTable ($ id )} ( \"_updatedAt \");
258266 " ;
259267 }
260268
@@ -271,17 +279,21 @@ public function createCollection(string $name, array $attributes = [], array $in
271279 " ;
272280
273281 if ($ this ->sharedTables ) {
282+ $ uniquePermissionIndex = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ id }_ukey " );
283+ $ permissionIndex = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ id }_permission " );
274284 $ permissions .= "
275- CREATE UNIQUE INDEX \"{$ namespace } _ { $ this -> tenant } _ { $ id } _ukey \"
285+ CREATE UNIQUE INDEX \"{$ uniquePermissionIndex } \"
276286 ON {$ this ->getSQLTable ($ id . '_perms ' )} USING btree (_tenant,_document,_type,_permission);
277- CREATE INDEX \"{$ namespace } _ { $ this -> tenant } _ { $ id } _permission \"
287+ CREATE INDEX \"{$ permissionIndex } \"
278288 ON {$ this ->getSQLTable ($ id . '_perms ' )} USING btree (_tenant,_permission,_type);
279289 " ;
280290 } else {
291+ $ uniquePermissionIndex = $ this ->getShortKey ("{$ namespace }_ {$ id }_ukey " );
292+ $ permissionIndex = $ this ->getShortKey ("{$ namespace }_ {$ id }_permission " );
281293 $ permissions .= "
282- CREATE UNIQUE INDEX \"{$ namespace } _ { $ id } _ukey \"
294+ CREATE UNIQUE INDEX \"{$ uniquePermissionIndex } \"
283295 ON {$ this ->getSQLTable ($ id . '_perms ' )} USING btree (_document COLLATE utf8_ci_ai,_type,_permission);
284- CREATE INDEX \"{$ namespace } _ { $ id } _permission \"
296+ CREATE INDEX \"{$ permissionIndex } \"
285297 ON {$ this ->getSQLTable ($ id . '_perms ' )} USING btree (_permission,_type);
286298 " ;
287299 }
@@ -893,15 +905,15 @@ public function createIndex(string $collection, string $id, string $type, array
893905 default => throw new DatabaseException ('Unknown index type: ' . $ type . '. Must be one of ' . Database::INDEX_KEY . ', ' . Database::INDEX_UNIQUE . ', ' . Database::INDEX_FULLTEXT . ', ' . Database::INDEX_SPATIAL . ', ' . Database::INDEX_OBJECT . ', ' . Database::INDEX_HNSW_EUCLIDEAN . ', ' . Database::INDEX_HNSW_COSINE . ', ' . Database::INDEX_HNSW_DOT ),
894906 };
895907
896- $ key = "\" {$ this ->getNamespace ()}_ {$ this ->tenant }_ {$ collection }_ {$ id }\"" ;
908+ $ keyName = $ this -> getShortKey ( " {$ this ->getNamespace ()}_ {$ this ->tenant }_ {$ collection }_ {$ id }" ) ;
897909 $ attributes = \implode (', ' , $ attributes );
898910
899911 if ($ this ->sharedTables && \in_array ($ type , [Database::INDEX_KEY , Database::INDEX_UNIQUE ])) {
900912 // Add tenant as first index column for best performance
901913 $ attributes = "_tenant, {$ attributes }" ;
902914 }
903915
904- $ sql = "CREATE {$ sqlType } { $ key } ON {$ this ->getSQLTable ($ collection )}" ;
916+ $ sql = "CREATE {$ sqlType } \"{ $ keyName }\" ON {$ this ->getSQLTable ($ collection )}" ;
905917
906918 // Add USING clause for special index types
907919 $ sql .= match ($ type ) {
@@ -936,9 +948,9 @@ public function deleteIndex(string $collection, string $id): bool
936948 $ id = $ this ->filter ($ id );
937949 $ schemaName = $ this ->getDatabase ();
938950
939- $ key = "\" {$ this ->getNamespace ()}_ {$ this ->tenant }_ {$ collection }_ {$ id }\"" ;
951+ $ keyName = $ this -> getShortKey ( " {$ this ->getNamespace ()}_ {$ this ->tenant }_ {$ collection }_ {$ id }" ) ;
940952
941- $ sql = "DROP INDEX IF EXISTS \"{$ schemaName }\". { $ key } " ;
953+ $ sql = "DROP INDEX IF EXISTS \"{$ schemaName }\". \"{ $ keyName }\" " ;
942954 $ sql = $ this ->trigger (Database::EVENT_INDEX_DELETE , $ sql );
943955
944956 return $ this ->execute ($ this ->getPDO ()
@@ -961,10 +973,11 @@ public function renameIndex(string $collection, string $old, string $new): bool
961973 $ namespace = $ this ->getNamespace ();
962974 $ old = $ this ->filter ($ old );
963975 $ new = $ this ->filter ($ new );
964- $ oldIndexName = "{$ this ->tenant }_ {$ collection }_ {$ old }" ;
965- $ newIndexName = "{$ namespace }_ {$ this ->tenant }_ {$ collection }_ {$ new }" ;
976+ $ schema = $ this ->getDatabase ();
977+ $ oldIndexName = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ collection }_ {$ old }" );
978+ $ newIndexName = $ this ->getShortKey ("{$ namespace }_ {$ this ->tenant }_ {$ collection }_ {$ new }" );
966979
967- $ sql = "ALTER INDEX { $ this -> getSQLTable ( $ oldIndexName)} RENAME TO \"{$ newIndexName }\"" ;
980+ $ sql = "ALTER INDEX \"{ $ schema }\" . \"{ $ oldIndexName}\" RENAME TO \"{$ newIndexName }\"" ;
968981 $ sql = $ this ->trigger (Database::EVENT_INDEX_RENAME , $ sql );
969982
970983 return $ this ->execute ($ this ->getPDO ()
@@ -2738,4 +2751,42 @@ protected function bindOperatorParams(\PDOStatement|PDOStatementProxy $stmt, Ope
27382751 break ;
27392752 }
27402753 }
2754+
2755+ /**
2756+ * Ensure index key length stays within PostgreSQL's 63 character limit.
2757+ *
2758+ * @param string $key
2759+ * @return string
2760+ */
2761+ protected function getShortKey (string $ key ): string
2762+ {
2763+ if (\strlen ($ key ) <= self ::MAX_IDENTIFIER_NAME ) {
2764+ return $ key ;
2765+ }
2766+
2767+ $ suffix = '' ;
2768+ $ separatorPosition = strrpos ($ key , '_ ' );
2769+ if ($ separatorPosition !== false ) {
2770+ $ suffix = substr ($ key , $ separatorPosition + 1 );
2771+ }
2772+
2773+ $ hash = md5 ($ key );
2774+
2775+ if ($ suffix !== '' ) {
2776+ $ hashedKey = "{$ hash }_ {$ suffix }" ;
2777+ if (\strlen ($ hashedKey ) <= self ::MAX_IDENTIFIER_NAME ) {
2778+ return $ hashedKey ;
2779+ }
2780+ }
2781+
2782+ return substr ($ hash , 0 , self ::MAX_IDENTIFIER_NAME );
2783+ }
2784+
2785+ protected function getSQLTable (string $ name ): string
2786+ {
2787+ $ table = "{$ this ->getNamespace ()}_ {$ this ->filter ($ name )}" ;
2788+ $ table = $ this ->getShortKey ($ table );
2789+
2790+ return "{$ this ->quote ($ this ->getDatabase ())}. {$ this ->quote ($ table )}" ;
2791+ }
27412792}
0 commit comments