Thread: Domain breakage
Here's a fun one: in 7.3 or CVS tip, try regression=# create domain tint as int; CREATE DOMAIN regression=# select 1::tint > (-1);?column? ----------t (1 row) regression=# select 1::tint > (-1)::tint;?column? ----------f (1 row) How's that again? Well, when you dig into it you find that the second case is invoking the OID greater-than operator (oidgt), which does unsigned comparison. Why is it picking oidgt and not int4gt, considering that the domain is based on int4? Well, the problem is that the domain type is considered binary-compatible with both int4 and oid; there isn't any stronger connection to the base type than there is to any other type that's binary-compatible with the domain. So oper_select_candidate gets down to its third tiebreaker, preferred-type status ... and guess what, OID is a preferred type in its category while int4 is not preferred in its category. I suspect that the most workable fix for this is to reduce all the input typeids to base types before we start the operator or function type resolution routines. However, this would completely destroy any hope of making domain-specific operators. (I'm also reminded once again that I don't like the preferred-type heuristics. They're too likely to produce surprising choices.) A different line of attack would be to modify the operator/function resolution rules to take account of domain relationships explicitly, making the binding of domain to base type stronger than mere binary equivalence. But I'm not clear how that might work. Any ideas? regards, tom lane
Tom Lane wrote: > A different line of attack would be to modify the operator/function > resolution rules to take account of domain relationships explicitly, > making the binding of domain to base type stronger than mere binary > equivalence. But I'm not clear how that might work. > > Any ideas? In oper_select_candidate(), where it checks whether or not the input type is binary coercible , you could change the "best match" computation (line 454 of CVS tip as of now) to read as follows: nmatch = 0; for (i = 0; i < nargs; i++) { if (input_typeids[i] != UNKNOWNOID) { if (IsBinaryCoercible(input_typeids[i], current_typeids[i])) nmatch += nargs;if (IsDomainBaseTypeFor(input_typeids[i], current_typeids[i]) || IsDomainBaseTypeFor(current_typeids[i],input_typeids[i])) nmatch++; } } And then define a function, IsDomainBaseTypeFor(), which returns a bool indicating whether or not the first argument is the domain base type for the second argument (if we already have a function that will do this job, we can use it instead). The idea here is that a domain binding will increase the "score" of the entry, but the maximum number of such bindings can never outweigh an additional binary coercible argument. That relative weighting may be too extreme, but would definitely serve to handle the example problem you provided. -- Kevin Brown kevin@sysexperts.com
Awhile back I said: > Here's a fun one: in 7.3 or CVS tip, try > regression=# create domain tint as int; > CREATE DOMAIN > regression=# select 1::tint > (-1); > ?column? > ---------- > t > (1 row) > regression=# select 1::tint > (-1)::tint; > ?column? > ---------- > f > (1 row) > How's that again? Well, when you dig into it you find that the second > case is invoking the OID greater-than operator (oidgt), which does > unsigned comparison. > I suspect that the most workable fix for this is to reduce all the input > typeids to base types before we start the operator or function type > resolution routines. However, this would completely destroy any hope of > making domain-specific operators. I have repaired this problem by doing the above. It turns out that this does not completely foreclose building domain-specific operators: the check for exact-match operators is done beforehand, so you can use a domain-specific operator as long as it's an exact match to the input datatypes. But as soon as there's not an exact match, operators on the base type will be preferred. This seems a workable compromise to me. regards, tom lane
This is now fixed in CVS, I believe by Tom's recent commit:test=> create domain tint as int;CREATE DOMAINtest=> select 1::tint> (-1); ?column?---------- t(1 row)test=> select 1::tint > (-1)::tint; ?column?---------- t(1 row) --------------------------------------------------------------------------- Tom Lane wrote: > Here's a fun one: in 7.3 or CVS tip, try > > regression=# create domain tint as int; > CREATE DOMAIN > regression=# select 1::tint > (-1); > ?column? > ---------- > t > (1 row) > > regression=# select 1::tint > (-1)::tint; > ?column? > ---------- > f > (1 row) > > How's that again? Well, when you dig into it you find that the second > case is invoking the OID greater-than operator (oidgt), which does > unsigned comparison. Why is it picking oidgt and not int4gt, > considering that the domain is based on int4? Well, the problem is that > the domain type is considered binary-compatible with both int4 and oid; > there isn't any stronger connection to the base type than there is to > any other type that's binary-compatible with the domain. So > oper_select_candidate gets down to its third tiebreaker, preferred-type > status ... and guess what, OID is a preferred type in its category while > int4 is not preferred in its category. > > I suspect that the most workable fix for this is to reduce all the input > typeids to base types before we start the operator or function type > resolution routines. However, this would completely destroy any hope of > making domain-specific operators. > > (I'm also reminded once again that I don't like the preferred-type > heuristics. They're too likely to produce surprising choices.) > > A different line of attack would be to modify the operator/function > resolution rules to take account of domain relationships explicitly, > making the binding of domain to base type stronger than mere binary > equivalence. But I'm not clear how that might work. > > Any ideas? > > regards, tom lane > > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Don't 'kill -9' the postmaster > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001+ If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania19073