[GENERAL] Array Comparison

2014-12-05 Thread Ian Harding
I have a function that returns bigint[] and would like to be able to
compare a bigint to the result.

freeload= select fn_descendents('trip'::varchar,61::bigint);
  fn_descendents
---
 {935,815,689,569,446,325,205,191}
(1 row)
freeload= select 935::bigint in (select
fn_descendents('trip'::varchar,61::bigint));
ERROR:  operator does not exist: bigint = bigint[]
LINE 1: select 935::bigint in (select fn_descendents('trip'::varchar...
   ^
HINT:  No operator matches the given name and argument type(s). You might
need to add explicit type casts.
This is probably super obvious but I'm not getting it right now.

Thank you all in advance!

- Ian


Re: [GENERAL] Array Comparison

2014-12-05 Thread Ian Harding
On Fri, Dec 5, 2014 at 4:55 PM, Ian Harding harding@gmail.com wrote:

 I have a function that returns bigint[] and would like to be able to
 compare a bigint to the result.

 freeload= select fn_descendents('trip'::varchar,61::bigint);
   fn_descendents
 ---
  {935,815,689,569,446,325,205,191}
 (1 row)
 freeload= select 935::bigint in (select
 fn_descendents('trip'::varchar,61::bigint));
 ERROR:  operator does not exist: bigint = bigint[]
 LINE 1: select 935::bigint in (select fn_descendents('trip'::varchar...
^
 HINT:  No operator matches the given name and argument type(s). You might
 need to add explicit type casts.
 This is probably super obvious but I'm not getting it right now.

 Hmmm.. This works...

select array[935::bigint] @ (select
fn_descendents('trip'::varchar,61::bigint));

Still, why?


Re: [GENERAL] Array Comparison

2014-12-05 Thread David G Johnston
Ian Harding wrote
 On Fri, Dec 5, 2014 at 4:55 PM, Ian Harding lt;

 harding.ian@

 gt; wrote:
 I have a function that returns bigint[] and would like to be able to
 compare a bigint to the result.

Here are some of your options:

http://www.postgresql.org/docs/9.3/interactive/functions-array.html
http://www.postgresql.org/docs/9.3/interactive/functions-comparisons.html

The direct type-to-type operators are covered in the first link while
generic comparison mechanisms - including those the can compare arrays to
scalars - are in the second one.

There are lots of ways to compare things; e.g., are they equal, is one
greater than another and, for multi-valued items, does one contain the other
or do they overlap


 select 935::bigint in (select
 fn_descendents('trip'::varchar,61::bigint));
 ERROR:  operator does not exist: bigint = bigint[]

As shown by the error the application of IN simply checks to see if any of
the ROWS of the given select match against the left-hand value.  That means
zero or more evaluations of:
bigint = bigint[]
which does not makes sense.  There is no special evalulation mode for a
subquery that only happens to return a single row.

From the second link above you can express the scalar-to-array comparison
you seek through the use of ANY.

bigint = ANY(bigint[])

Since your function already returns an array you do not to (and indeed
cannot) use a subquery/SELECT.  Simply write:

935::bigint = ANY(fn_descendents(...))


 Hmmm.. This works...

 select array[935::bigint] @ (select
 fn_descendents('trip'::varchar,61::bigint));
 
 Still, why?

Do you understand the concept of array containment - what it means for an
array to contain or be contained by another array?  The documentation
assumes that concept is known and simply provides the syntax/operators
needed to access it.

David J.






--
View this message in context: 
http://postgresql.nabble.com/Array-Comparison-tp5829471p5829473.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Fwd: [GENERAL] Array Comparison

2014-12-05 Thread David Johnston
Please send replies to the list.

On Friday, December 5, 2014, Ian Harding harding@gmail.com
javascript:_e(%7B%7D,'cvml','harding@gmail.com'); wrote:



 On Fri, Dec 5, 2014 at 5:37 PM, David G Johnston 
 david.g.johns...@gmail.com wrote:

 Ian Harding wrote
  On Fri, Dec 5, 2014 at 4:55 PM, Ian Harding lt;

  harding.ian@

  gt; wrote:
  I have a function that returns bigint[] and would like to be able to
  compare a bigint to the result.

 Here are some of your options:

 http://www.postgresql.org/docs/9.3/interactive/functions-array.html
 http://www.postgresql.org/docs/9.3/interactive/functions-comparisons.html

 The direct type-to-type operators are covered in the first link while
 generic comparison mechanisms - including those the can compare arrays to
 scalars - are in the second one.

 There are lots of ways to compare things; e.g., are they equal, is one
 greater than another and, for multi-valued items, does one contain the
 other
 or do they overlap


  select 935::bigint in (select
  fn_descendents('trip'::varchar,61::bigint));
  ERROR:  operator does not exist: bigint = bigint[]

 As shown by the error the application of IN simply checks to see if any
 of
 the ROWS of the given select match against the left-hand value.  That
 means
 zero or more evaluations of:
 bigint = bigint[]
 which does not makes sense.  There is no special evalulation mode for a
 subquery that only happens to return a single row.

 Ah.  Right.  That makes sense.


 From the second link above you can express the scalar-to-array comparison
 you seek through the use of ANY.

 bigint = ANY(bigint[])

 Since your function already returns an array you do not to (and indeed
 cannot) use a subquery/SELECT.  Simply write:

 935::bigint = ANY(fn_descendents(...))


 I sort of figured that out only I fatfingered it to ... IN ANY(...


  Hmmm.. This works...
 
  select array[935::bigint] @ (select
  fn_descendents('trip'::varchar,61::bigint));
 
  Still, why?

 Do you understand the concept of array containment - what it means for an
 array to contain or be contained by another array?  The documentation
 assumes that concept is known and simply provides the syntax/operators
 needed to access it.


 Ah, but isn't this the same There is no special evalulation mode for a
 subquery that only happens to return a single row. from above?  I'm asking
 Is this scalar array contained in the result set of this select for which
 there is no special evaluation mode for the happy coincidence that it only
 has one value?  That's what surprised me.


No.  Your query will output one row for every input row the subquery
generates - each row having a true or false value depending on whether the
particular value contains your array constant.

Your initial attempt incorrectly tried to get in the IN to apply to each
element of the only array that was returned but that doesn't work and which
is why the scalar=array comparison failed; the array is never decomposed.
If your replace @ with IN in this example you would get a single result
(Boolean false in this case) regardless of how many rows the subquery
returns.  The IN wraps the subquery expression and makes it into a kind of
scalar while directly using the operator against the subquery causes
multiple evaluations.

See: SELECT generate_series(1,10) - for an idea of how row generating
expressions in the select list behave.

David J.


Re: [GENERAL] Array comparison prefix search

2009-12-10 Thread Denes Daniel
I tried making the ident column a text instead of text[] in the beginning,
but searches were approximately of the same speed; so I voted for the array,
because this way there isn't even a possibility for the separator (##) to
cause problems.

Anyway, the ident BETWEEN ARRAY['foo', 'bar'] AND ARRAY['foo', 'bar',
NULL] approach works really fast (uses the index), and selects all arrays
that are equal to or start with ['foo', 'bar'].

Thanks everybody,
Denes Daniel



2009/12/7 Sam Mason s...@samason.me.uk

 On Sat, Dec 05, 2009 at 09:54:58AM -0500, Merlin Moncure wrote:
  GIN is a pretty heavy price to pay for something that should be btree
  indexable.  Also note he is using a multi column index with array as
  second column...that would be pretty awkward with GIN.

 Yup, sounds as though it's not going to work here.  I was mainly
 suggesting it as it's working now, as opposed to something that
 could/should be made to work.

  Normalizing the data loses the nice property of being able to order
  the entire structure using a single index.  He's using the array as if
  it was a string...it's basically an optimization.

 Hum, not sure why this didn't come up already: what about having an
 index on (type,(array_to_string(ident,'##')) and relying on the already
 existing optimizations for string prefixes.  Not sure what sort of
 values can be used in ident, but it could work.

 --
  Sam  http://samason.me.uk/



Re: [GENERAL] Array comparison prefix search

2009-12-07 Thread Sam Mason
On Sat, Dec 05, 2009 at 09:54:58AM -0500, Merlin Moncure wrote:
 GIN is a pretty heavy price to pay for something that should be btree
 indexable.  Also note he is using a multi column index with array as
 second column...that would be pretty awkward with GIN.

Yup, sounds as though it's not going to work here.  I was mainly
suggesting it as it's working now, as opposed to something that
could/should be made to work.

 Normalizing the data loses the nice property of being able to order
 the entire structure using a single index.  He's using the array as if
 it was a string...it's basically an optimization.

Hum, not sure why this didn't come up already: what about having an
index on (type,(array_to_string(ident,'##')) and relying on the already
existing optimizations for string prefixes.  Not sure what sort of
values can be used in ident, but it could work.

-- 
  Sam  http://samason.me.uk/

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison prefix search

2009-12-07 Thread Merlin Moncure
On Mon, Dec 7, 2009 at 7:01 AM, Sam Mason s...@samason.me.uk wrote:
 On Sat, Dec 05, 2009 at 09:54:58AM -0500, Merlin Moncure wrote:
 GIN is a pretty heavy price to pay for something that should be btree
 indexable.  Also note he is using a multi column index with array as
 second column...that would be pretty awkward with GIN.

 Yup, sounds as though it's not going to work here.  I was mainly
 suggesting it as it's working now, as opposed to something that
 could/should be made to work.

 Normalizing the data loses the nice property of being able to order
 the entire structure using a single index.  He's using the array as if
 it was a string...it's basically an optimization.

 Hum, not sure why this didn't come up already: what about having an
 index on (type,(array_to_string(ident,'##')) and relying on the already
 existing optimizations for string prefixes.  Not sure what sort of
 values can be used in ident, but it could work.

hm, that's certainly an interesting idea, but I think unless you pad
all the strings out you are going to run into some odd ordering
issues.  If it works though I think you'll have a much tighter index
than the raw one over the array.

merlin

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison prefix search

2009-12-05 Thread Sam Mason
On Sat, Dec 05, 2009 at 02:23:13AM +0100, Denes Daniel wrote:
 2009/12/4 Sam Mason s...@samason.me.uk
   CREATE INDEX test_my_idx ON test (type,(ident[1]));
 
 Sorry, but this approach is no good, since I may search like:
 SELECT * FROM test WHERE type = 'three' AND (ident[1] = 'foo' AND ident[2] =
 'bar');
 or for the first 3 items in an array with 6 items, or any other prefix...

Would a GIN index help?  You'd be able to ask if a 'foo' appears
anywhere in the array (or some subset if you want).  You can then have a
subsequent filter that actually expresses the clause you want.  Not sure
what selectivity you're dealing with and if this would be a problem.

 The arrays are all the same length for a given type, but for type
 'twenty-three' they may be 23 items long, or even longer for another type,
 so I can't create an index for all possible cases that way. And yet, all the
 information needed is in the primary index, I just don't know how to get
 PostgeSQL to use it.

Arrays and PG (not sure how well other databases handle this case
either) don't work too well.  Have you thought about normalising your
schema a bit to give the database more help?

 And why is it this way when I'm using an ARRAY[], and the other way when
 using ROW()?

I'd say ROW is doing the wrong thing here, but I think other people may
well disagree with me.  Composite/non-atomic types don't exist in the
SQL spec much (AFAIK) hence their behavior is somewhat ad-hoc and tends
to reflect the original use case rather than being too consistent.

-- 
  Sam  http://samason.me.uk/

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison prefix search

2009-12-05 Thread Merlin Moncure
On Sat, Dec 5, 2009 at 4:54 AM, Sam Mason s...@samason.me.uk wrote:
 On Sat, Dec 05, 2009 at 02:23:13AM +0100, Denes Daniel wrote:
 2009/12/4 Sam Mason s...@samason.me.uk
   CREATE INDEX test_my_idx ON test (type,(ident[1]));

 Sorry, but this approach is no good, since I may search like:
 SELECT * FROM test WHERE type = 'three' AND (ident[1] = 'foo' AND ident[2] =
 'bar');
 or for the first 3 items in an array with 6 items, or any other prefix...

 Would a GIN index help?  You'd be able to ask if a 'foo' appears
 anywhere in the array (or some subset if you want).  You can then have a
 subsequent filter that actually expresses the clause you want.  Not sure
 what selectivity you're dealing with and if this would be a problem.

GIN is a pretty heavy price to pay for something that should be btree
indexable.  Also note he is using a multi column index with array as
second column...that would be pretty awkward with GIN.

 The arrays are all the same length for a given type, but for type
 'twenty-three' they may be 23 items long, or even longer for another type,
 so I can't create an index for all possible cases that way. And yet, all the
 information needed is in the primary index, I just don't know how to get
 PostgeSQL to use it.

 Arrays and PG (not sure how well other databases handle this case
 either) don't work too well.  Have you thought about normalising your
 schema a bit to give the database more help?

Normalizing the data loses the nice property of being able to order
the entire structure using a single index.  He's using the array as if
it was a string...it's basically an optimization.

 And why is it this way when I'm using an ARRAY[], and the other way when
 using ROW()?

 I'd say ROW is doing the wrong thing here, but I think other people may
 well disagree with me.  Composite/non-atomic types don't exist in the
 SQL spec much (AFAIK) hence their behavior is somewhat ad-hoc and tends
 to reflect the original use case rather than being too consistent.

yeah, pg composite type handling with nulls is all over the place.
you can get just about everything to work though.

merlin

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison prefix search

2009-12-05 Thread Denes Daniel
2009/12/5 Sam Mason s...@samason.me.uk


 Would a GIN index help?  You'd be able to ask if a 'foo' appears
 anywhere in the array (or some subset if you want).  You can then have a
 subsequent filter that actually expresses the clause you want.  Not sure
 what selectivity you're dealing with and if this would be a problem.


I think that wouldn't be good for me, since the table will be 2-3M rows
large and will be updated very often, and GIN indices are too slow at that.
(In fact, the whole table's goal is to avoid updating GIN indices so
frequently.)


 Arrays and PG (not sure how well other databases handle this case
 either) don't work too well.  Have you thought about normalising your
 schema a bit to give the database more help?


I don't have any idea how I could do that... except for creating separate
tables for all types. But I don't think that would be a better option. If
you have any other idea, I'd really appreciate it.


 I'd say ROW is doing the wrong thing here, but I think other people may
 well disagree with me.  Composite/non-atomic types don't exist in the
 SQL spec much (AFAIK) hence their behavior is somewhat ad-hoc and tends
 to reflect the original use case rather than being too consistent.


According to the documentation,
http://www.postgresql.org/docs/8.4/static/functions-comparisons.html#ROW-WISE-COMPARISON
Note: Prior to PostgreSQL 8.2, the , =,  and = cases were not handled
per SQL specification.
I think the way ROW comparisons work now is per SQL specification.

But wait! Thank you for making me read this part of the docs, because I've
just found what I was looking for, at the very end of the page:


 Note: The SQL specification requires row-wise comparison to return NULL if
 the result depends on comparing two NULL values or a NULL and a non-NULL.
 PostgreSQL does this only when comparing the results of two row constructors
 or comparing a row constructor to the output of a subquery (as in Section
 9.20). In other contexts where two composite-type values are compared, two
 NULL field values are considered equal, and a NULL is considered larger than
 a non-NULL. This is necessary in order to have consistent sorting and
 indexing behavior for composite types.


I was sure I've read this part of the docs a hundred times, so I've gone
after why I didn't find this before: this note is new in the 8.4 docs, it
wasn't there before (and I'm using 8.3).
http://www.postgresql.org/docs/8.3/static/functions-comparisons.html#ROW-WISE-COMPARISON
But I'm pretty sure now that I can rely on this.


Thanks,
Denes Daniel


Re: [GENERAL] Array comparison prefix search

2009-12-05 Thread Denes Daniel
2009/12/5 Merlin Moncure mmonc...@gmail.com


 AFAIK, your approach is the only solution given your requirements.  It
 works well...I've used it often, but usually for integers.  Maybe
 there is a missing operator for arrays kinda similar to the contains
 operator that would be btree indexable.


Yes, I also think that an array prefix equality operator would be good to
have... but now that I've found it in the documentation that this solution
can be relied on (see my other mail), I can work around the lack of that.

Thanks,
Denes Daniel


Re: [GENERAL] Array comparison prefix search

2009-12-05 Thread Merlin Moncure
On Sat, Dec 5, 2009 at 10:31 AM, Denes Daniel panthe...@freemail.hu wrote:
 According to the documentation,
 http://www.postgresql.org/docs/8.4/static/functions-comparisons.html#ROW-WISE-COMPARISON
 Note: Prior to PostgreSQL 8.2, the , =,  and = cases were not handled
 per SQL specification.
 I think the way ROW comparisons work now is per SQL specification.

 But wait! Thank you for making me read this part of the docs, because I've
 just found what I was looking for, at the very end of the page:


 Note: The SQL specification requires row-wise comparison to return NULL if
 the result depends on comparing two NULL values or a NULL and a non-NULL.
 PostgreSQL does this only when comparing the results of two row constructors
 or comparing a row constructor to the output of a subquery (as in Section
 9.20). In other contexts where two composite-type values are compared, two
 NULL field values are considered equal, and a NULL is considered larger than
 a non-NULL. This is necessary in order to have consistent sorting and
 indexing behavior for composite types.


 I was sure I've read this part of the docs a hundred times, so I've gone
 after why I didn't find this before: this note is new in the 8.4 docs, it
 wasn't there before (and I'm using 8.3).
 http://www.postgresql.org/docs/8.3/static/functions-comparisons.html#ROW-WISE-COMPARISON
 But I'm pretty sure now that I can rely on this.

Note, composite types != arrays.  Being able to index composite types
is new to 8.4 (you have been able to do arrays for longer than that).
Postgres handling of nullls in composite types is pretty funky, but
nulls being highval in arrays for indexing purposes is probably pretty
safe to rely on.

merlin

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison prefix search

2009-12-05 Thread Filip Rembiałkowski
without digging too much into the details - just a suggestion:

look at the ltree contrib. it actually provides an indexable array
prefix search.




2009/12/4 Denes Daniel panthe...@freemail.hu:
 Hi,

 I have a table like this:

 CREATE TABLE test (
 type text NOT NULL,
     ident text[] NOT NULL,
     ...
 );
 ALTER TABLE ONLY test ADD CONSTRAINT test_pkey PRIMARY KEY (type, ident);

 and I would like to query rows that have a specific type and whose ident
 array starts with a some given constants.
 I mean something like this:

 INSERT INTO test VALUES ('one', ARRAY['string']);
 INSERT INTO test VALUES ('two', ARRAY['tab', 'str1']);
 INSERT INTO test VALUES ('two', ARRAY['test', 'str1']);
 INSERT INTO test VALUES ('two', ARRAY['test', 'str2']);
 INSERT INTO test VALUES ('two', ARRAY['try', 'str1']);
 INSERT INTO test VALUES ('three', ARRAY['some', 'more', 'strings']);

 SELECT * FROM test WHERE type = 'two' AND ident[1] = 'test';

 But this query uses the primary key index only for the type field, and
 then filters for ident[1]. Is there a way to make it use the index for the
 array prefix search too, like with  textcol LIKE '123%'  ? The only way I
 can think of, is this:

 SELECT * FROM test WHERE type = 'two' AND (ident = ARRAY['test', ''] AND
 ident = ARRAY['test', NULL]);

 This uses the index as much as possible, so it's fast, and gives correct
 results. But something's strange, because it's based on the thing that all
 strings are greather than or equal to the empty string, and all are less
 than or equal to NULL... which is fine when ordering rows, so it's fine too
 in the B-tree (I think), but shouldn't it return no rows, because ('string'
 = NULL) is NULL?

 In fact, ('string' = NULL) is NULL if I test it directly, or use row-wise
 comparison, but when I use array comparison, NULL is greather than 'string'.
 SELECT 'string' = NULL::text, ARRAY['string'] = ARRAY[NULL::text];
 This gives me a NULL and a TRUE.
 Why? Can I rely on this? If I can't, is there another way to make the array
 prefix search use the index?

 Regards,
 Denes Daniel



-- 
Filip Rembiałkowski
JID,mailto:filip.rembialkow...@gmail.com
http://filip.rembialkowski.net/

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


[GENERAL] Array comparison prefix search

2009-12-04 Thread Denes Daniel
Hi,

I have a table like this:

CREATE TABLE test (
type text NOT NULL,
ident text[] NOT NULL,
...
);
ALTER TABLE ONLY test ADD CONSTRAINT test_pkey PRIMARY KEY (type, ident);

and I would like to query rows that have a specific type and whose ident
array starts with a some given constants.
I mean something like this:

 INSERT INTO test VALUES ('one', ARRAY['string']);
INSERT INTO test VALUES ('two', ARRAY['tab', 'str1']);
 INSERT INTO test VALUES ('two', ARRAY['test', 'str1']);
INSERT INTO test VALUES ('two', ARRAY['test', 'str2']);
 INSERT INTO test VALUES ('two', ARRAY['try', 'str1']);
 INSERT INTO test VALUES ('three', ARRAY['some', 'more', 'strings']);

SELECT * FROM test WHERE type = 'two' AND ident[1] = 'test';

But this query uses the primary key index only for the type field, and
then filters for ident[1]. Is there a way to make it use the index for the
array prefix search too, like with  textcol LIKE '123%'  ? The only way I
can think of, is this:

SELECT * FROM test WHERE type = 'two' AND (ident = ARRAY['test', ''] AND
ident = ARRAY['test', NULL]);

This uses the index as much as possible, so it's fast, and gives correct
results. But something's strange, because it's based on the thing that all
strings are greather than or equal to the empty string, and all are less
than or equal to NULL... which is fine when ordering rows, so it's fine too
in the B-tree (I think), but shouldn't it return no rows, because ('string'
= NULL) is NULL?

In fact, ('string' = NULL) is NULL if I test it directly, or use row-wise
comparison, but when I use array comparison, NULL is greather than 'string'.
SELECT 'string' = NULL::text, ARRAY['string'] = ARRAY[NULL::text];
This gives me a NULL and a TRUE.
Why? Can I rely on this? If I can't, is there another way to make the array
prefix search use the index?

Regards,
Denes Daniel


Re: [GENERAL] Array comparison prefix search

2009-12-04 Thread Sam Mason
On Fri, Dec 04, 2009 at 06:58:21PM +0100, Denes Daniel wrote:
 SELECT * FROM test WHERE type = 'two' AND ident[1] = 'test';
 
 this query uses the primary key index only for the type field, and
 then filters for ident[1]. Is there a way to make it use the index for the
 array prefix search too, like with  textcol LIKE '123%'  ? The only way I
 can think of, is this:

I think you want to create a functional index on ident[1], something
like:

  CREATE INDEX test_my_idx ON test (type,(ident[1]));

 In fact, ('string' = NULL) is NULL if I test it directly, or use row-wise
 comparison, but when I use array comparison, NULL is greather than 'string'.
 SELECT 'string' = NULL::text, ARRAY['string'] = ARRAY[NULL::text];
 This gives me a NULL and a TRUE.

The semantics of this are somewhat fuzzy; I think the behavior is
caused by the fact that the value as a whole isn't NULL, hence you get
a non-null result.  You only get a NULL result when the whole value is
null, hence values of integer type either have a value or they're null.
As you see, for values of non-atomic type it gets a bit more awkward and
there are various opinions about how they should be handled.

-- 
  Sam  http://samason.me.uk/

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison prefix search

2009-12-04 Thread Denes Daniel
2009/12/4 Sam Mason s...@samason.me.uk


 I think you want to create a functional index on ident[1], something
 like:

  CREATE INDEX test_my_idx ON test (type,(ident[1]));


Sorry, but this approach is no good, since I may search like:
SELECT * FROM test WHERE type = 'three' AND (ident[1] = 'foo' AND ident[2] =
'bar');
or for the first 3 items in an array with 6 items, or any other prefix...

The arrays are all the same length for a given type, but for type
'twenty-three' they may be 23 items long, or even longer for another type,
so I can't create an index for all possible cases that way. And yet, all the
information needed is in the primary index, I just don't know how to get
PostgeSQL to use it.



 The semantics of this are somewhat fuzzy; I think the behavior is
 caused by the fact that the value as a whole isn't NULL, hence you get
 a non-null result.  You only get a NULL result when the whole value is
 null, hence values of integer type either have a value or they're null.
 As you see, for values of non-atomic type it gets a bit more awkward and
 there are various opinions about how they should be handled.


I see, but the documentation says: Array comparisons compare the array
contents element-by-element, [...]. So, if we compare two arrays, where the
first difference is this 'string' / NULL thing, then we will reach a point
(after comparing all those items that are equal) where 'string' compares to
NULL, and the result is that NULL is greater. At least that's the only way I
can think of, how I'd get this TRUE result. So is NULL really greater than
all other text?
And why is it this way when I'm using an ARRAY[], and the other way when
using ROW()?

SELECT ARRAY['abc', 'string', 'z']  ARRAY['abc', NULL::text, 'a'];
-- returns TRUE
SELECT ROW('abc', 'string', 'z')  ROW('abc', NULL::text, 'a');
-- returns NULL


Regards,
Denes Daniel


Re: [GENERAL] Array comparison prefix search

2009-12-04 Thread Merlin Moncure
On Fri, Dec 4, 2009 at 12:58 PM, Denes Daniel panthe...@freemail.hu wrote:
 Hi,

 I have a table like this:

 CREATE TABLE test (
 type text NOT NULL,
     ident text[] NOT NULL,
     ...
 );
 ALTER TABLE ONLY test ADD CONSTRAINT test_pkey PRIMARY KEY (type, ident);

 and I would like to query rows that have a specific type and whose ident
 array starts with a some given constants.
 I mean something like this:

 INSERT INTO test VALUES ('one', ARRAY['string']);
 INSERT INTO test VALUES ('two', ARRAY['tab', 'str1']);
 INSERT INTO test VALUES ('two', ARRAY['test', 'str1']);
 INSERT INTO test VALUES ('two', ARRAY['test', 'str2']);
 INSERT INTO test VALUES ('two', ARRAY['try', 'str1']);
 INSERT INTO test VALUES ('three', ARRAY['some', 'more', 'strings']);

 SELECT * FROM test WHERE type = 'two' AND ident[1] = 'test';

 But this query uses the primary key index only for the type field, and
 then filters for ident[1]. Is there a way to make it use the index for the
 array prefix search too, like with  textcol LIKE '123%'  ? The only way I
 can think of, is this:

 SELECT * FROM test WHERE type = 'two' AND (ident = ARRAY['test', ''] AND
 ident = ARRAY['test', NULL]);

 This uses the index as much as possible, so it's fast, and gives correct
 results. But something's strange, because it's based on the thing that all
 strings are greather than or equal to the empty string, and all are less
 than or equal to NULL... which is fine when ordering rows, so it's fine too
 in the B-tree (I think), but shouldn't it return no rows, because ('string'
 = NULL) is NULL?

 In fact, ('string' = NULL) is NULL if I test it directly, or use row-wise
 comparison, but when I use array comparison, NULL is greather than 'string'.
 SELECT 'string' = NULL::text, ARRAY['string'] = ARRAY[NULL::text];
 This gives me a NULL and a TRUE.
 Why? Can I rely on this? If I can't, is there another way to make the array
 prefix search use the index?


AFAIK, your approach is the only solution given your requirements.  It
works well...I've used it often, but usually for integers.  Maybe
there is a missing operator for arrays kinda similar to the contains
operator that would be btree indexable.

merlin

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Array comparison - subset

2006-09-04 Thread Christopher Murtagh

On 9/3/06, Michael Fuhr [EMAIL PROTECTED] wrote:

On Fri, Sep 01, 2006 at 11:55:32AM -0400, Christopher Murtagh wrote:
 I've got a function that returns and array $foo, and an array $bar.
 Is there an elegant way to test if $bar is a subset of $foo? I've been
 looking through the docs and haven't found anything. Am I missing
 something obvious, or am I out of luck?

In the specific case of integer arrays you could use contrib/intarray.


Cool. This is exactly what I needed. Thanks a bunch!

Cheers,

Chris

---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


Re: [GENERAL] Array comparison - subset

2006-09-03 Thread Michael Fuhr
On Sun, Sep 03, 2006 at 12:59:08AM -0400, Tom Lane wrote:
 Michael Fuhr [EMAIL PROTECTED] writes:
  test= SELECT ARRAY[1, 2, 3, 4] @ ARRAY[1, 3];
   ?column? 
  --
   t
  (1 row)
 
  In 8.2 the above example will work in the stock installation for
  arrays of any type (i.e., with operands of type anyarray).
 
 [ blink... ]  When did that get in, and why don't I see it in the
 documentation?

Looks like it arrived with the gin code.

http://archives.postgresql.org/pgsql-committers/2006-05/msg7.php
http://developer.postgresql.org/cvsweb.cgi/pgsql/src/include/catalog/pg_operator.h.diff?r1=1.142r2=1.143

 The operand order seems exactly backward considering
 that all the pre-existing @ operators are contained in, not
 contains.  Should we flip this around before it's too late?

I'd favor consistency, although I see that contrib/intarray has had
it backwards for a long time :-(

-- 
Michael Fuhr

---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: [GENERAL] Array comparison - subset

2006-09-02 Thread Michael Fuhr
On Fri, Sep 01, 2006 at 11:55:32AM -0400, Christopher Murtagh wrote:
 I've got a function that returns and array $foo, and an array $bar.
 Is there an elegant way to test if $bar is a subset of $foo? I've been
 looking through the docs and haven't found anything. Am I missing
 something obvious, or am I out of luck?

In the specific case of integer arrays you could use contrib/intarray.

test= SELECT ARRAY[1, 2, 3, 4] @ ARRAY[1, 3];
 ?column? 
--
 t
(1 row)

test= SELECT ARRAY[1, 2, 3, 4] @ ARRAY[1, 5];
 ?column? 
--
 f
(1 row)

In 8.2 the above example will work in the stock installation for
arrays of any type (i.e., with operands of type anyarray).

-- 
Michael Fuhr

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [GENERAL] Array comparison - subset

2006-09-02 Thread Tom Lane
Michael Fuhr [EMAIL PROTECTED] writes:
 test= SELECT ARRAY[1, 2, 3, 4] @ ARRAY[1, 3];
  ?column? 
 --
  t
 (1 row)

 In 8.2 the above example will work in the stock installation for
 arrays of any type (i.e., with operands of type anyarray).

[ blink... ]  When did that get in, and why don't I see it in the
documentation?  The operand order seems exactly backward considering
that all the pre-existing @ operators are contained in, not
contains.  Should we flip this around before it's too late?

regards, tom lane

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


[GENERAL] Array comparison - subset

2006-09-01 Thread Christopher Murtagh

Greetings folks,

I've got a function that returns and array $foo, and an array $bar.
Is there an elegant way to test if $bar is a subset of $foo? I've been
looking through the docs and haven't found anything. Am I missing
something obvious, or am I out of luck?

Cheers,

Chris

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
  subscribe-nomail command to [EMAIL PROTECTED] so that your
  message can get through to the mailing list cleanly