W przypadku ucieczki ?
nie jest możliwe, możesz utworzyć zduplikowany operator o innej nazwie.
Nowy operator
Składnia tworzenia operatorów w Postgresie:
CREATE OPERATOR name (
PROCEDURE = function_name
[, LEFTARG = left_type ] [, RIGHTARG = right_type ]
[, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]
[, RESTRICT = res_proc ] [, JOIN = join_proc ]
[, HASHES ] [, MERGES ]
)
W przypadku ?|
używane w jsonb
to będzie:
CREATE OPERATOR ^|(
PROCEDURE = jsonb_exists_any,
LEFTARG = jsonb,
RIGHTARG = _text,
RESTRICT = contsel,
JOIN = contjoinsel);
Użyłem ^|
jako przykład alternatywna nazwa. Może to być dowolna sekwencja z tej listy:+ - * / < > = ~ ! @ # % ^ & |
?`.
Aktualną definicję operatora, który Cię interesuje, możesz znaleźć w tabeli pg_catalog.pg_operator.
SELECT oid, *
FROM pg_catalog.pg_operator
WHERE oprname = '?|'
AND oprleft = (SELECT oid FROM pg_type WHERE typname = 'jsonb');
Możesz także użyć narzędzia GUI, takiego jak pgAdmin i przeglądać pg_catalog
aby przygotować definicję SQL do ponownego użycia.
Włączanie indeksu
Jeśli chcesz użyć indeksu dla tego „nowego” operatora, będziesz musiał utworzyć nową klasę operatora i opcjonalnie rodzinę. W naszym przypadku potrzebujemy obu, ponieważ nie możemy dodać go do istniejącej rodziny, ponieważ domyślny operator już zajmuje miejsce na strategię.
Podobnie jak w przypadku operatorów, zaleca się używanie narzędzia GUI, takiego jak pgAdmin, do przeglądania klas operatorów i po prostu ich kopiowania i wklejania.
Najpierw bierzemy OID operatora, którego zduplikowaliśmy:
SELECT oid, *
FROM pg_catalog.pg_operator
WHERE oprname = '?|'
AND oprleft = (SELECT oid FROM pg_type WHERE typname = 'jsonb');
To samo dla rodziny operatorów (zamiast tego otrzymamy ją z tabeli klas operatorów), szukamy klasy gin, ponieważ jest to ta, która obsługuje ?|
. opcdefault
jest używana, ponieważ istnieje opcjonalna klasa jsonb_path_ops
który nie obsługuje tego operatora:
SELECT opcfamily
FROM pg_opclass
WHERE opcintype = (SELECT oid FROM pg_type WHERE typname = 'jsonb')
AND opcmethod = (SELECT oid FROM pg_am WHERE amname = 'gin')
AND opcdefault
Następnie otrzymujemy strategię używaną przez operatora, którego zduplikowaliśmy:
SELECT amopstrategy,
(SELECT typname FROM pg_type WHERE oid = amoplefttype) AS left_t,
(SELECT typname FROM pg_type WHERE oid = amoprighttype) AS right_t,*
FROM pg_amop
WHERE amopfamily = 4036 --family oid
AND amopopr = 3248 --operator oid
Następnie funkcje używane przez klasę:
SELECT amprocnum, amproc::text, pg_get_function_identity_arguments(amproc::oid) AS args,
(SELECT typname FROM pg_type WHERE oid = amproclefttype) AS left_t,
(SELECT typname FROM pg_type WHERE oid = amprocrighttype) AS right_t,*
FROM pg_amproc
WHERE amprocfamily = 4036 --op family
To prowadzi nas do tej klasy operatorów. Stworzy rodzinę operatorów, jeśli jeszcze nie istnieje.
CREATE OPERATOR CLASS jsonb_ops_custom
FOR TYPE jsonb USING gin AS
OPERATOR 10 ^|(jsonb, _text),
FUNCTION 1 gin_compare_jsonb(text, text),
FUNCTION 2 gin_extract_jsonb(jsonb, internal, internal),
FUNCTION 3 gin_extract_jsonb_query(jsonb, internal, smallint, internal, internal, internal, internal),
FUNCTION 4 gin_consistent_jsonb(internal, smallint, jsonb, integer, internal, internal, internal, internal),
FUNCTION 6 gin_triconsistent_jsonb(internal, smallint, jsonb, integer, internal, internal, internal);
Teraz wystarczy utworzyć indeks przy użyciu utworzonej nazwy operatora, na przykład:
CREATE INDEX ON jsonb_table USING gin(jsonb_column jsonb_ops_custom)
Powinieneś być w stanie korzystać z indeksu:
SET enable_seqscan = off;
EXPLAIN ANALYZE
SELECT * FROM jsonb_table WHERE jsonb_column ^| array['b', 'c'];