Re: [HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-08 Thread David E. Wheeler
On Mar 7, 2012, at 8:23 PM, Tom Lane wrote:

 You have not told the system that your operator is equality for the
 datatype.  It's just a random operator that happens to be named =.
 We try to avoid depending on operator names as cues to semantics.
 
 You need to incorporate it into a default hash or btree opclass before
 the composite-type logic will accept it as the thing to use for
 comparing that column.

Ah, okay. Just need more stuff, I guess:

CREATE OR REPLACE FUNCTION json_cmp(
json,
json
) RETURNS INTEGER LANGUAGE SQL STRICT IMMUTABLE AS $$
SELECT bttextcmp($1::text, $2::text);
$$;

CREATE OR REPLACE FUNCTION json_eq(
json,
json
) RETURNS BOOLEAN LANGUAGE SQL STRICT IMMUTABLE AS $$
SELECT bttextcmp($1::text, $2::text) = 0;
$$;

CREATE OPERATOR = (
LEFTARG   = json,
RIGHTARG  = json,
PROCEDURE = json_eq
);

CREATE OPERATOR CLASS json_ops
DEFAULT FOR TYPE JSON USING btree AS
OPERATOR3   =  (json, json),
FUNCTION1   json_cmp(json, json);

This seems to work.

Best,

David


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


Re: [HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-08 Thread Tom Lane
David E. Wheeler da...@justatheory.com writes:
 CREATE OPERATOR CLASS json_ops
 DEFAULT FOR TYPE JSON USING btree AS
 OPERATOR3   =  (json, json),
 FUNCTION1   json_cmp(json, json);

 This seems to work.

Urk.  You really ought to provide the whole opclass (all 5 operators).
I'm not sure what will blow up if you leave it like that, but it won't
be pretty.

regards, tom lane

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


Re: [HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-08 Thread Andrew Dunstan



On 03/08/2012 02:16 PM, Tom Lane wrote:

David E. Wheelerda...@justatheory.com  writes:

 CREATE OPERATOR CLASS json_ops
 DEFAULT FOR TYPE JSON USING btree AS
 OPERATOR3   =  (json, json),
 FUNCTION1   json_cmp(json, json);
This seems to work.

Urk.  You really ought to provide the whole opclass (all 5 operators).
I'm not sure what will blow up if you leave it like that, but it won't
be pretty.


Yeah. Note too that this is at best dubious:

CREATE OR REPLACE FUNCTION json_cmp(
json,
json
) RETURNS INTEGER LANGUAGE SQL STRICT IMMUTABLE AS $$
SELECT bttextcmp($1::text, $2::text);
$$;


Two pieces of JSON might well be textually different but semantically 
identical (e.g. by one having additional non-semantic whitespace).



cheers

andrew

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


Re: [HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-08 Thread David E. Wheeler
On Mar 8, 2012, at 11:16 AM, Tom Lane wrote:

 This seems to work.
 
 Urk.  You really ought to provide the whole opclass (all 5 operators).
 I'm not sure what will blow up if you leave it like that, but it won't
 be pretty.

Yes, I expect to have to fill in gaps as I go. These are just for unit tests, 
so I’m not too worried about it (yet).

David


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


Re: [HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-08 Thread David E. Wheeler
On Mar 8, 2012, at 11:27 AM, Andrew Dunstan wrote:

 Yeah. Note too that this is at best dubious:
 
CREATE OR REPLACE FUNCTION json_cmp(
json,
json
) RETURNS INTEGER LANGUAGE SQL STRICT IMMUTABLE AS $$
SELECT bttextcmp($1::text, $2::text);
$$;
 
 
 Two pieces of JSON might well be textually different but semantically 
 identical (e.g. by one having additional non-semantic whitespace).

Yes. This is just for unit tests, and is fine for the moment. If I end up with 
abnormalities, I will likely rewrite json_cmp() in Perl and use JSON::XS to do 
normalization. Not needed yet, though.

Thanks,

David


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


[HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-07 Thread David E. Wheeler
Hackers,

I’m doing some development with the new JSON type (actually, Andrew’s backport 
to 9.1) and needed to do some very basic equivalence testing. So I created a 
custom operator:

CREATE OR REPLACE FUNCTION json_eq(
json,
json
) RETURNS BOOLEAN LANGUAGE SQL STRICT IMMUTABLE AS $$
SELECT $1::text = $2::text;
$$;

CREATE OPERATOR = (
LEFTARG   = json,
RIGHTARG  = json,
PROCEDURE = json_eq
);

With this in place, these work:

 SELECT '{}'::json = '{}'::json;
 SELECT ROW('{}'::json) = ROW('{}'::json);

However this does not:

create type ajson AS (a json);
SELECT ROW('{}'::json)::ajson = ROW('{}'::json)::ajson;

That last line emits an error:

ERROR:  could not identify an equality operator for type json

To which my response was: WTF? Is this expected behavior? Is there something 
about custom operators that they can’t be used to compare the values of values 
in composite types?

I’ve worked around it by writing a separate operator to compare ajson types 
using

SELECT $1::text = $2::text

But it’s a bit annoying.

Thanks,

David


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


Re: [HACKERS] Custom Operators Cannot be Found for Composite Type Values

2012-03-07 Thread Tom Lane
David E. Wheeler da...@justatheory.com writes:
 I’m doing some development with the new JSON type (actually, Andrew’s 
 backport to 9.1) and needed to do some very basic equivalence testing. So I 
 created a custom operator:

 CREATE OR REPLACE FUNCTION json_eq(
 json,
 json
 ) RETURNS BOOLEAN LANGUAGE SQL STRICT IMMUTABLE AS $$
 SELECT $1::text = $2::text;
 $$;

 CREATE OPERATOR = (
 LEFTARG   = json,
 RIGHTARG  = json,
 PROCEDURE = json_eq
 );

 With this in place, these work:

  SELECT '{}'::json = '{}'::json;
  SELECT ROW('{}'::json) = ROW('{}'::json);

 However this does not:

 create type ajson AS (a json);
 SELECT ROW('{}'::json)::ajson = ROW('{}'::json)::ajson;

 That last line emits an error:

 ERROR:  could not identify an equality operator for type json

 To which my response was: WTF?

You have not told the system that your operator is equality for the
datatype.  It's just a random operator that happens to be named =.
We try to avoid depending on operator names as cues to semantics.

You need to incorporate it into a default hash or btree opclass before
the composite-type logic will accept it as the thing to use for
comparing that column.

regards, tom lane

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