2011-02-14 09:06:41 +08:00
|
|
|
CREATE EXTENSION ltree;
|
2002-07-31 00:40:34 +08:00
|
|
|
|
2016-11-30 04:05:22 +08:00
|
|
|
-- Check whether any of our opclasses fail amvalidate
|
|
|
|
SELECT amname, opcname
|
|
|
|
FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid = opcmethod
|
|
|
|
WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid);
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT ''::ltree;
|
|
|
|
SELECT '1'::ltree;
|
|
|
|
SELECT '1.2'::ltree;
|
|
|
|
SELECT '1.2._3'::ltree;
|
|
|
|
|
2020-04-02 07:44:17 +08:00
|
|
|
-- empty labels not allowed
|
|
|
|
SELECT '.2.3'::ltree;
|
|
|
|
SELECT '1..3'::ltree;
|
|
|
|
SELECT '1.2.'::ltree;
|
|
|
|
|
|
|
|
SELECT repeat('x', 255)::ltree;
|
|
|
|
SELECT repeat('x', 256)::ltree;
|
|
|
|
|
2003-04-01 04:53:45 +08:00
|
|
|
SELECT ltree2text('1.2.3.34.sdf');
|
|
|
|
SELECT text2ltree('1.2.3.34.sdf');
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT subltree('Top.Child1.Child2',1,2);
|
|
|
|
SELECT subpath('Top.Child1.Child2',1,2);
|
|
|
|
SELECT subpath('Top.Child1.Child2',-1,1);
|
|
|
|
SELECT subpath('Top.Child1.Child2',0,-2);
|
|
|
|
SELECT subpath('Top.Child1.Child2',0,-1);
|
|
|
|
SELECT subpath('Top.Child1.Child2',0,0);
|
|
|
|
SELECT subpath('Top.Child1.Child2',1,0);
|
|
|
|
SELECT subpath('Top.Child1.Child2',0);
|
|
|
|
SELECT subpath('Top.Child1.Child2',1);
|
|
|
|
|
2003-04-01 04:53:45 +08:00
|
|
|
|
|
|
|
SELECT index('1.2.3.4.5.6','1.2');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','1.2');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','1.2.3');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','1.2.3.j');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','1.2.3.j.4.5.5.5.5.5.5');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','1.2.3');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','6');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','6.1');
|
|
|
|
SELECT index('a.1.2.3.4.5.6','5.6');
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6','5.6');
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',3);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',6);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',7);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-7);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-4);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-3);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-2);
|
|
|
|
SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-20000);
|
|
|
|
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::text;
|
|
|
|
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::ltree;
|
|
|
|
SELECT 'Top_0'::ltree || 'Top.Child1.Child2'::ltree;
|
|
|
|
SELECT 'Top.Child1.Child2'::ltree || ''::ltree;
|
|
|
|
SELECT ''::ltree || 'Top.Child1.Child2'::ltree;
|
|
|
|
|
2004-08-21 08:26:54 +08:00
|
|
|
SELECT lca('{la.2.3,1.2.3.4.5.6,""}') IS NULL;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT lca('{la.2.3,1.2.3.4.5.6}') IS NULL;
|
|
|
|
SELECT lca('{1.la.2.3,1.2.3.4.5.6}');
|
|
|
|
SELECT lca('{1.2.3,1.2.3.4.5.6}');
|
2018-07-14 06:45:30 +08:00
|
|
|
SELECT lca('{1.2.3}');
|
|
|
|
SELECT lca('{1}'), lca('{1}') IS NULL;
|
|
|
|
SELECT lca('{}') IS NULL;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT lca('1.la.2.3','1.2.3.4.5.6');
|
|
|
|
SELECT lca('1.2.3','1.2.3.4.5.6');
|
|
|
|
SELECT lca('1.2.2.3','1.2.3.4.5.6');
|
|
|
|
SELECT lca('1.2.2.3','1.2.3.4.5.6','');
|
|
|
|
SELECT lca('1.2.2.3','1.2.3.4.5.6','2');
|
|
|
|
SELECT lca('1.2.2.3','1.2.3.4.5.6','1');
|
|
|
|
|
|
|
|
|
|
|
|
SELECT '1'::lquery;
|
|
|
|
SELECT '4|3|2'::lquery;
|
|
|
|
SELECT '1.2'::lquery;
|
|
|
|
SELECT '1.4|3|2'::lquery;
|
|
|
|
SELECT '1.0'::lquery;
|
|
|
|
SELECT '4|3|2.0'::lquery;
|
|
|
|
SELECT '1.2.0'::lquery;
|
|
|
|
SELECT '1.4|3|2.0'::lquery;
|
|
|
|
SELECT '1.*'::lquery;
|
|
|
|
SELECT '4|3|2.*'::lquery;
|
|
|
|
SELECT '1.2.*'::lquery;
|
|
|
|
SELECT '1.4|3|2.*'::lquery;
|
|
|
|
SELECT '*.1.*'::lquery;
|
|
|
|
SELECT '*.4|3|2.*'::lquery;
|
|
|
|
SELECT '*.1.2.*'::lquery;
|
|
|
|
SELECT '*.1.4|3|2.*'::lquery;
|
|
|
|
SELECT '1.*.4|3|2'::lquery;
|
|
|
|
SELECT '1.*.4|3|2.0'::lquery;
|
|
|
|
SELECT '1.*.4|3|2.*{1,4}'::lquery;
|
|
|
|
SELECT '1.*.4|3|2.*{,4}'::lquery;
|
|
|
|
SELECT '1.*.4|3|2.*{1,}'::lquery;
|
|
|
|
SELECT '1.*.4|3|2.*{1}'::lquery;
|
Fix lquery's NOT handling, and add ability to quantify non-'*' items.
The existing implementation of the ltree ~ lquery match operator is
sufficiently complex and undocumented that it's hard to tell exactly
what it does. But one thing it clearly gets wrong is the combination
of NOT symbols (!) and '*' symbols. A pattern such as '*.!foo.*'
should, by any ordinary understanding of regular expression behavior,
match any ltree that has at least one label that's not "foo". As best
we can tell by experimentation, what it's actually matching is any
ltree in which *no* label is "foo". That's surprising, and not at all
what the documentation says.
Now, that's arguably a useful behavior, so if we rewrite to fix the
bug we should provide some other way to get it. To do so, add the
ability to attach lquery quantifiers to non-'*' items as well as '*'s.
Then the pattern '!foo{,}' expresses "any ltree in which no label is
foo". For backwards compatibility, the default quantifier for non-'*'
items has to be "{1}", although the default for '*' items is '{,}'.
I wouldn't have done it like that in a green field, but it's not
totally horrible.
Armed with that, rewrite checkCond() from scratch. Treating '*' and
non-'*' items alike makes it simpler, not more complicated, so that
the function actually gets a lot shorter than it was.
Filip Rembiałkowski, Tom Lane, Nikita Glukhov, per a very
ancient bug report from M. Palm
Discussion: https://postgr.es/m/CAP_rww=waX2Oo6q+MbMSiZ9ktdj6eaJj0cQzNu=Ry2cCDij5fw@mail.gmail.com
2020-03-31 23:14:30 +08:00
|
|
|
SELECT 'foo.bar{,}.!a*|b{1,}.c{,44}.d{3,4}'::lquery;
|
2020-04-02 07:44:17 +08:00
|
|
|
SELECT 'foo*@@*'::lquery;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT 'qwerty%@*.tu'::lquery;
|
|
|
|
|
2020-04-02 07:44:17 +08:00
|
|
|
-- empty labels not allowed
|
|
|
|
SELECT '.2.3'::lquery;
|
|
|
|
SELECT '1..3'::lquery;
|
|
|
|
SELECT '1.2.'::lquery;
|
|
|
|
SELECT '@.2.3'::lquery;
|
|
|
|
SELECT '1.@.3'::lquery;
|
|
|
|
SELECT '1.2.@'::lquery;
|
|
|
|
SELECT '!.2.3'::lquery;
|
|
|
|
SELECT '1.!.3'::lquery;
|
|
|
|
SELECT '1.2.!'::lquery;
|
|
|
|
SELECT '1.2.3|@.4'::lquery;
|
|
|
|
|
|
|
|
SELECT (repeat('x', 255) || '*@@*')::lquery;
|
|
|
|
SELECT (repeat('x', 256) || '*@@*')::lquery;
|
|
|
|
SELECT ('!' || repeat('x', 255))::lquery;
|
|
|
|
SELECT ('!' || repeat('x', 256))::lquery;
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT nlevel('1.2.3.4');
|
2020-03-29 05:09:51 +08:00
|
|
|
SELECT nlevel(('1' || repeat('.1', 65534))::ltree);
|
|
|
|
SELECT nlevel(('1' || repeat('.1', 65535))::ltree);
|
|
|
|
SELECT nlevel(('1' || repeat('.1', 65534))::ltree || '1');
|
|
|
|
SELECT ('1' || repeat('.1', 65534))::lquery IS NULL;
|
|
|
|
SELECT ('1' || repeat('.1', 65535))::lquery IS NULL;
|
|
|
|
SELECT '*{65535}'::lquery;
|
|
|
|
SELECT '*{65536}'::lquery;
|
|
|
|
SELECT '*{,65534}'::lquery;
|
|
|
|
SELECT '*{,65535}'::lquery;
|
|
|
|
SELECT '*{,65536}'::lquery;
|
2020-03-31 22:30:59 +08:00
|
|
|
SELECT '*{4,3}'::lquery;
|
2020-03-29 05:09:51 +08:00
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT '1.2'::ltree < '2.2'::ltree;
|
|
|
|
SELECT '1.2'::ltree <= '2.2'::ltree;
|
|
|
|
SELECT '2.2'::ltree = '2.2'::ltree;
|
|
|
|
SELECT '3.2'::ltree >= '2.2'::ltree;
|
|
|
|
SELECT '3.2'::ltree > '2.2'::ltree;
|
|
|
|
|
|
|
|
SELECT '1.2.3'::ltree @> '1.2.3.4'::ltree;
|
|
|
|
SELECT '1.2.3.4'::ltree @> '1.2.3.4'::ltree;
|
|
|
|
SELECT '1.2.3.4.5'::ltree @> '1.2.3.4'::ltree;
|
|
|
|
SELECT '1.3.3'::ltree @> '1.2.3.4'::ltree;
|
|
|
|
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.b.c.d.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'A.b.c.d.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'A@.b.c.d.e';
|
|
|
|
SELECT 'aa.b.c.d.e'::ltree ~ 'A@.b.c.d.e';
|
|
|
|
SELECT 'aa.b.c.d.e'::ltree ~ 'A*.b.c.d.e';
|
|
|
|
SELECT 'aa.b.c.d.e'::ltree ~ 'A*@.b.c.d.e';
|
|
|
|
SELECT 'aa.b.c.d.e'::ltree ~ 'A*@|g.b.c.d.e';
|
|
|
|
SELECT 'g.b.c.d.e'::ltree ~ 'A*@|g.b.c.d.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.b.c.d.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{3}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{4}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{,4}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2,}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2,4}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2,3}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2,3}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2,4}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2,5}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{2,3}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{2,4}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{2,5}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.e.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.a.*.d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!d';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!a.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!e.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*.!e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*.!d';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*.!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*.!f.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.a.*.!f.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.a.*.!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.a.!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.a.!d';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.a.*.!d.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*.c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.*.c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.b.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.*.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{2}.!b.*.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{1}.!b.*.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{1}.!b.*{1}.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.!b.*{1}.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.*{1}.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*{1}.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*.!c.*.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.*.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{2}.!b.*.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{1}.!b.*.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*{1}.!b.*{1}.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.!b.*{1}.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!b.*{1}.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*{1}.!c.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*.!c.*';
|
2020-03-29 06:31:05 +08:00
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{2}.*{2}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{1}.*{2}.e';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{1}.*{4}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a.*{5}.*';
|
Fix lquery's NOT handling, and add ability to quantify non-'*' items.
The existing implementation of the ltree ~ lquery match operator is
sufficiently complex and undocumented that it's hard to tell exactly
what it does. But one thing it clearly gets wrong is the combination
of NOT symbols (!) and '*' symbols. A pattern such as '*.!foo.*'
should, by any ordinary understanding of regular expression behavior,
match any ltree that has at least one label that's not "foo". As best
we can tell by experimentation, what it's actually matching is any
ltree in which *no* label is "foo". That's surprising, and not at all
what the documentation says.
Now, that's arguably a useful behavior, so if we rewrite to fix the
bug we should provide some other way to get it. To do so, add the
ability to attach lquery quantifiers to non-'*' items as well as '*'s.
Then the pattern '!foo{,}' expresses "any ltree in which no label is
foo". For backwards compatibility, the default quantifier for non-'*'
items has to be "{1}", although the default for '*' items is '{,}'.
I wouldn't have done it like that in a green field, but it's not
totally horrible.
Armed with that, rewrite checkCond() from scratch. Treating '*' and
non-'*' items alike makes it simpler, not more complicated, so that
the function actually gets a lot shorter than it was.
Filip Rembiałkowski, Tom Lane, Nikita Glukhov, per a very
ancient bug report from M. Palm
Discussion: https://postgr.es/m/CAP_rww=waX2Oo6q+MbMSiZ9ktdj6eaJj0cQzNu=Ry2cCDij5fw@mail.gmail.com
2020-03-31 23:14:30 +08:00
|
|
|
SELECT '5.0.1.0'::ltree ~ '5.!0.!0.0';
|
|
|
|
SELECT 'a.b'::ltree ~ '!a.!a';
|
|
|
|
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a{,}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a{1,}.*';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a{,}.!a{,}';
|
|
|
|
SELECT 'a.b.c.d.a'::ltree ~ 'a{,}.!a{,}';
|
|
|
|
SELECT 'a.b.c.d.a'::ltree ~ 'a{,2}.!a{1,}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ 'a{,2}.!a{1,}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!x{,}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!c{,}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!c{0,3}.!a{2,}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ~ '!c{0,3}.!d{2,}.*';
|
2003-02-19 11:50:09 +08:00
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT 'QWER_TY'::ltree ~ 'q%@*';
|
2020-04-02 07:44:17 +08:00
|
|
|
SELECT 'QWER_TY'::ltree ~ 'q%@*%@*';
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT 'QWER_TY'::ltree ~ 'Q_t%@*';
|
|
|
|
SELECT 'QWER_GY'::ltree ~ 'q_t%@*';
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
--ltxtquery
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT '!tree & aWdf@*'::ltxtquery;
|
|
|
|
SELECT 'tree & aw_qw%*'::ltxtquery;
|
|
|
|
SELECT 'ltree.awdfg'::ltree @ '!tree & aWdf@*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ '!tree & aWdf@*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ '!tree | aWdf@*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree | aWdf@*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree & aWdf@*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree & aWdf@'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree & aWdf*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree & aWdf'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree & awdf*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg'::ltree @ 'tree & aWdfg@'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_qw%*'::ltxtquery;
|
|
|
|
SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_rw%*'::ltxtquery;
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
--arrays
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT '{1.2.3}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.2.3.4}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.2.3.4.5}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.3.3}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{5.67.8, 1.2.3}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{5.67.8, 1.2.3.4}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{5.67.8, 1.2.3.4.5}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{5.67.8, 1.3.3}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.2.3, 7.12.asd}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.2.3.4, 7.12.asd}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.2.3.4.5, 7.12.asd}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{1.3.3, 7.12.asd}'::ltree[] @> '1.2.3.4';
|
|
|
|
SELECT '{ltree.asd, tree.awdfg}'::ltree[] @ 'tree & aWdfg@'::ltxtquery;
|
|
|
|
SELECT '{j.k.l.m, g.b.c.d.e}'::ltree[] ~ 'A*@|g.b.c.d.e';
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT 'a.b.c.d.e'::ltree ? '{A.b.c.d.e}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ? '{a.b.c.d.e}';
|
|
|
|
SELECT 'a.b.c.d.e'::ltree ? '{A.b.c.d.e, a.*}';
|
|
|
|
SELECT '{a.b.c.d.e,B.df}'::ltree[] ? '{A.b.c.d.e}';
|
|
|
|
SELECT '{a.b.c.d.e,B.df}'::ltree[] ? '{A.b.c.d.e,*.df}';
|
2002-07-31 00:40:34 +08:00
|
|
|
|
2017-02-06 17:33:58 +08:00
|
|
|
--extractors
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT ('{3456,1.2.3.34}'::ltree[] ?@> '1.2.3.4') is null;
|
|
|
|
SELECT '{3456,1.2.3}'::ltree[] ?@> '1.2.3.4';
|
|
|
|
SELECT '{3456,1.2.3.4}'::ltree[] ?<@ '1.2.3';
|
|
|
|
SELECT ('{3456,1.2.3.4}'::ltree[] ?<@ '1.2.5') is null;
|
|
|
|
SELECT '{ltree.asd, tree.awdfg}'::ltree[] ?@ 'tree & aWdfg@'::ltxtquery;
|
|
|
|
SELECT '{j.k.l.m, g.b.c.d.e}'::ltree[] ?~ 'A*@|g.b.c.d.e';
|
|
|
|
|
|
|
|
CREATE TABLE ltreetest (t ltree);
|
|
|
|
\copy ltreetest FROM 'data/ltree.data'
|
|
|
|
|
|
|
|
SELECT * FROM ltreetest WHERE t < '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t <= '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t = '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t >= '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t > '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t @> '1.1.1' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t <@ '1.1.1' order by t asc;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t ~ '1.1.1.*' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ~ '23.*.2' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
create unique index tstidx on ltreetest (t);
|
|
|
|
set enable_seqscan=off;
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t < '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t <= '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t = '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t >= '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t > '12.3' order by t asc;
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
drop index tstidx;
|
|
|
|
create index tstidx on ltreetest using gist (t);
|
|
|
|
set enable_seqscan=off;
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t < '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t <= '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t = '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t >= '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t > '12.3' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t @> '1.1.1' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t <@ '1.1.1' order by t asc;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t ~ '1.1.1.*' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ~ '23.*.2' order by t asc;
|
|
|
|
SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
|
2002-07-31 00:40:34 +08:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-31 00:17:11 +08:00
|
|
|
drop index tstidx;
|
|
|
|
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0));
|
|
|
|
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025));
|
|
|
|
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
|
|
|
|
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t < '12.3';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t <= '12.3';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t = '12.3';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t >= '12.3';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t > '12.3';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t @> '1.1.1';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t <@ '1.1.1';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t @ '23 & 1';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t ~ '1.1.1.*';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t ~ '*.1';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t ~ '23.*{1}.1';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t ~ '23.*.1';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t ~ '23.*.2';
|
|
|
|
SELECT count(*) FROM ltreetest WHERE t ? '{23.*.1,23.*.2}';
|
|
|
|
|
2002-07-31 00:40:34 +08:00
|
|
|
create table _ltreetest (t ltree[]);
|
2002-10-19 02:41:22 +08:00
|
|
|
\copy _ltreetest FROM 'data/_ltree.data'
|
2002-07-31 00:40:34 +08:00
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t @> '1.1.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
create index _tstidx on _ltreetest using gist (t);
|
|
|
|
set enable_seqscan=off;
|
|
|
|
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t @> '1.1.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
|
2002-10-19 02:41:22 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
|
2003-02-19 11:50:09 +08:00
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-31 00:17:11 +08:00
|
|
|
|
|
|
|
drop index _tstidx;
|
|
|
|
create index _tstidx on _ltreetest using gist (t gist__ltree_ops(siglen=0));
|
|
|
|
create index _tstidx on _ltreetest using gist (t gist__ltree_ops(siglen=2025));
|
|
|
|
create index _tstidx on _ltreetest using gist (t gist__ltree_ops(siglen=2024));
|
|
|
|
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t @> '1.1.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
|
|
|
|
SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
|