Re: [HACKERS] Re: type coersion (was OR clause status)

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: "Thomas G(dot) Lockhart" <lockhart(at)alumni(dot)caltech(dot)edu>
Cc: PostgreSQL-development <hackers(at)postgreSQL(dot)org>
Subject: Re: [HACKERS] Re: type coersion (was OR clause status)
Date: 1998-08-08 19:16:51
Message-ID: 1799.902603811@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

"Thomas G. Lockhart" <lockhart(at)alumni(dot)caltech(dot)edu> writes:
>> ... have an int2 column called i2, how do you place the conversion
>> functions when it is being compared to an in4 constant?
>> i2 = int2(500)
>> int4(i2) = 500
>> The first is good for indexing, the second is not. If they are both
>> variables or both constants, the handling does not matter.

> Yes the handling does matter *in general*, since
> while i4 = 500.1
> cannot be evaluated as
> while i4 = int4(500.1)
> and get the right result.
> Even for the types in your example,
> while i2 = 4000000
> should execute correctly, even though we both know that *for this case*
> it doesn't make a lot of sense since the constant exceeds the range of
> the column.

This is all a good point. I wonder whether it wouldn't help to make the
parser's initial assignment of types to constants depend on how big the
constants are. In other words, if I write "400" the parser would
implicitly mark this as "int2", whereas if I write "400000" it would be
implicitly marked "int4". Then, subsequent implicit upward promotion
would cast 400::int2 to 400::int4 if int4 was actually the most
appropriate thing to use *in context*.

It seems to me that this handles all the cases cited correctly:
where i2 = 400
will get implemented directly as int2 eq int2,
where i4 = 400
will promote 400::int2 to 400::int4 and then use an int4 eq int4
comparison op (of course we have to address the current failure to
reduce int4(constant) to a constant, but IMHO that has to happen
anyway),
where i2 = 400000
will get promoted to where int4(i2) = 400000::int4 and executed
correctly (in this case returning no rows, but that's not a reason
not to do it right --- "where i2 < 32768" might be a more compelling
example). Likewise
where i4 = 500.1
will be executed with correct semantics as float8(i4) = 500.1::float8
since the parser will know that float8 is a "wider" type than int4.

It'd be nice if the same answer would work for
where f4 = 500.1
but I'm not sure that I care to see the parser deciding that "float4
is good enough for this constant". We could too easily find that in
where f8 = 500.1
the parser might cast the constant down to float4 and back up to float8
with catastrophic loss of precision.

In the float case, is there some way that a constant might be marked
as "float of unspecified width" (with the actual value held as a float8)
until the type resolution pass is done? This would need to be
considered "equivalent" to both float4 and float8, so that in
where f4 = 500.1
the type resolver doesn't decide it must rewrite f4 as float8(f4).
Then at some late stage of the game we resolve the constant to float4
rather than float8 if the context is float4. I'm not sure how the
details should work, however. If we *could* make this work it might
be best to handle int2 vs. int4 constants the same way.

regards, tom lane

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 1998-08-08 19:23:20 Re: [HACKERS] re: Informix on Linux
Previous Message Tom Lane 1998-08-08 18:41:00 Re: [HACKERS] Re: type coersion (was OR clause status)