Thread: Bug in user-defined types?
Hi, In response to comments made here, I have been rewriting the unsigned types as externally loadable. Using the same routines that worked fine when linked statically into the backend gives me core-dumps only. Creating only a single uint2 type with I/O routines, I get test=# create table u2 ( u uint2); CREATE test=# insert into u2 values (12::uint2); pqReadData() -- backend closed the channel unexpectedly. This probably means the backend terminated abnormally before or while processing the request. Running this under gdb (I tried this on alpha as well) backend> insert into u2 values (12::uint2); (no debugging symbols found)... Program received signal SIGSEGV, Segmentation fault. 0x40115573 in memcpy () from /lib/libc.so.6 (gdb) where #0 0x40115573 in memcpy () from /lib/libc.so.6 #1 0x80cfb92 in _copyConst () #2 0x80d25d9 in copyObject () #3 0x80ebad9 in expression_tree_mutator () #4 0x80eb407 in eval_const_expressions_mutator () #5 0x80ebe42 in expression_tree_mutator () #6 0x80eb407 in eval_const_expressions_mutator () #7 0x80ebdf2 in expression_tree_mutator () #8 0x80eb407 in eval_const_expressions_mutator () #9 0x80eaf87 in eval_const_expressions () #10 0x80e6d2a in preprocess_expression () #11 0x80e6751 in subquery_planner () #12 0x80e66c0 in planner () #13 0x81036e7 in pg_plan_query () #14 0x81038d9 in pg_exec_query_string () #15 0x81049d4 in PostgresMain () #16 0x80ce884 in main () #17 0x400d8a42 in __libc_start_main () from /lib/libc.so.6 (gdb) It never seems to get to my code. So either I've defined something incorrectly or there is a bug. I'd appreciate it if somebody more knowledgable than I could have a look at it. I've included a tar with the definitions. BTW it may be good to update the complex example to the new C-calling interface, as there is no example of creating a type with the new calling interface. Cheers, Adriaan
Attachment
Adriaan Joubert <a.joubert@albourne.com> writes: > In response to comments made here, I have been rewriting the unsigned > types as externally loadable. Using the same routines that worked fine > when linked statically into the backend gives me core-dumps only. Seems unlikely that that code could have worked either way, since you forgot to mark type uint2 as PASSEDBYVALUE... regards, tom lane
Tom Lane wrote: > > Seems unlikely that that code could have worked either way, since you > forgot to mark type uint2 as PASSEDBYVALUE... > Aargh! Thanks! Yes, when implementing it in the backend, that was just a field to fill in, so I did it there. All seems well now. One ends up with a vast number of combinations of types combinations for different operators. As C takes care of the conversions, I wrote a 30-line perl script to generate me nearly 1600 lines of C for all the type combinations (+ ~1700 lines of sql to define the functions/operators). I cannot help feeling that that is not the right way: if it can be done in a few lines of perl and relies on C cross-type operations underneath anyway, it seems wrong to have to generate all this code. The problem is that there is not a clean hierarchy of SQL types, but for many cases one could either convert the operands to int4 or float8 and then numeric(?) and then convert back. At least the conversion operators check for overflow, which is better than the current situation. And precision wise it cannot be much worse: after all, large integer constants already end up as floats. Is the SQL standard pedantic about this? BTW I could not find the discussion on entry-points to shared libraries that Thomas mentioned. I've got some rushed dead-lines at the moment, so I will not be able to look at anything for the next 3-4 weeks though. Adriaan
> The problem is that there is not a clean hierarchy of SQL types, but for > many cases one could either convert the operands to int4 or float8 and > then numeric(?) and then convert back. At least the conversion operators > check for overflow, which is better than the current situation. And > precision wise it cannot be much worse: after all, large integer > constants already end up as floats. Is the SQL standard pedantic about > this? Yes. The implicit "big integer" -> float8 done in the scanner is an expedient hack to keep from rejecting the large number entirely, but is likely not in the spirit of the SQL standard. The Right Way would have us set the large integer string to int8 and/or numeric, but the scanner does not know about those types at the moment, mostly for historical reasons. If we made the scanner aware of integers larger than int4, we would have to choose between int8 (not supported on all platforms, but mostly OK) and numeric, which is markedly slower to process and handle. I recall that Tom Lane had the proposal to use a more loosely categorized "some kind of numeric type" in the scanner, postponing the hard assignment of type to later in the parser. That might get around the performance issues, since numeric would only be used if the context required it. - Thomas
Thomas Lockhart <lockhart@alumni.caltech.edu> writes: > If we made the scanner aware of integers larger than int4, we would have > to choose between int8 (not supported on all platforms, but mostly OK) > and numeric, which is markedly slower to process and handle. I recall > that Tom Lane had the proposal to use a more loosely categorized "some > kind of numeric type" in the scanner, postponing the hard assignment of > type to later in the parser. That might get around the performance > issues, since numeric would only be used if the context required it. Yes, I was thinking of treating numerical literals more like we already treat unknown-type string literals: keep the value in string format until we deduce from context which type it should be, then convert. Internally this already happens for literals that don't fit in int4, but we still prejudge the type sooner than I think we should. IIRC, the main reason this isn't done yet was that we hadn't come to a conclusion about the appropriate type promotion hierarchy for numeric values. regards, tom lane