From ed9686a36b73975cce2c6e5002349863d0ca79e8 Mon Sep 17 00:00:00 2001
From: Kari Barry <kezzsim@gmail.com>
Date: Tue, 24 Oct 2023 16:22:35 -0400
Subject: [PATCH] =?UTF-8?q?Enable=20GIN=20index=20scans=20on=20metadata=20?=
 =?UTF-8?q?=3D=20queries=20=F0=9F=94=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 tiled/catalog/adapter.py | 13 +++++++++++--
 tiled/catalog/core.py    |  2 +-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/tiled/catalog/adapter.py b/tiled/catalog/adapter.py
index 52f58df72..1ed736a60 100644
--- a/tiled/catalog/adapter.py
+++ b/tiled/catalog/adapter.py
@@ -6,7 +6,7 @@
 import shutil
 import sys
 import uuid
-from functools import partial
+from functools import partial, reduce
 from pathlib import Path
 from urllib.parse import quote_plus, urlparse
 
@@ -938,9 +938,18 @@ def _prepare_structure(structure_family, structure):
 
 def binary_op(query, tree, operation):
     dialect_name = tree.engine.url.get_dialect().name
-    attr = orm.Node.metadata_[query.key.split(".")]
+    keys = query.key.split(".")
+    attr = orm.Node.metadata_[keys]
     if dialect_name == "sqlite":
         condition = operation(_get_value(attr, type(query.value)), query.value)
+    # specific case where GIN optomized index can be used to speed up POSTGRES equals queries
+    elif dialect_name == "postgresql" and operation == operator.eq:
+        condition = orm.Node.metadata_.op("@>")(
+            type_coerce(
+                {keys[0]: reduce(lambda x, y: {y: x}, keys[1:][::-1], query.value)},
+                orm.Node.metadata_.type,
+            )
+        )
     else:
         condition = operation(attr, type_coerce(query.value, orm.Node.metadata_.type))
     return tree.new_variation(conditions=tree.conditions + [condition])
diff --git a/tiled/catalog/core.py b/tiled/catalog/core.py
index 2e7ebdd59..6340b12bd 100644
--- a/tiled/catalog/core.py
+++ b/tiled/catalog/core.py
@@ -17,7 +17,7 @@ async def initialize_database(engine):
 
     async with engine.connect() as connection:
         # Install extensions
-        if (engine.dialect.name == "postgresql"):
+        if engine.dialect.name == "postgresql":
             await connection.execute(text("create extension btree_gin;"))
         # Create all tables.
         await connection.run_sync(Base.metadata.create_all)