$Id: odbc.txt 2850 2009-02-23 22:27:10Z unsaved $ | |
This file documents various aspects of HyerSQL's ODBC support. | |
It does not document driver-side issues (at least once we can discriminate), | |
since those issues will be documented with the dedicated ODBC driver product. | |
Critical server-side todo items. | |
+ Support passing of size/precision/scale values for columns to the ODBC | |
client. I guess the client uses this for display formatting purposes (I | |
don't know any other reason why the client would want the value, since | |
the database, not the client, enforces conformance). | |
It's quite possible that no real purpose is served. In that case we can | |
greatly improve efficiency of the PgType class by sharing a static list | |
of elements instead of making tons of PgType instances. | |
+ Support binary database data types (BINARY, OBJECT, etc.) | |
+ Support TIME and DATETIME database data types (DATEs already supported) | |
(May want to postpone *INTERVAL* types for another iteration). | |
+ Verify tactic used to generate numeric "object identifiers" for tables | |
is adequate: Java hash of String "schema.tablename". | |
+ Fix column oid (numeric object identifier) generation tactic. I am | |
just returning the sequence in the generated result set. The problem | |
with this tactic is that the number for a column is dependent upon | |
the query instead of on the table definition. | |
KNOWN LIMITATIONS | |
Limitations corresponding to the TODO items above. | |
Can't fetch the same column (or virtual column) twice from JDBC, even with | |
different getters like rs.getInt() and rs.getObject(). I don't know what | |
product is responsible for this limitation. | |
No metadata querying ability, other than the ones implicit with setting | |
up prepared statements (including the 'D'). | |
Don't know if it is a bug with Sun's jdbc:odbc or with psqlodbc, but | |
all fetchsize settings are rejected with a message saying that the | |
value is unacceptable. | |
psqlodbc can handle compound commands (*;*) only in SIMPLE (Q) mode; and | |
even that needs to be tested to see if server will generate the expected | |
number of reply packets. | |
POSTGRESQL DEPENDENCIES TO BE ELIMINATED (uncertain whether will handle these | |
on client or server side). | |
Search ServerConnection.java (from odbcproto1 branch) for comments about | |
"stub" and "swallow", ignoring stuff about client side swallowing. | |
Over-the-wire Postgresql-specific SQL commands that must be handled. | |
SELECT | |
PREPARE/EXECUTE/DEALLOCATE | |
SET/SHOW | |
DECLARE/FETCH/MOVE/CLOSE | |
psqlodbc source code locations | |
The info30.c file seems to be good (ODBC v.3 metadata) | |
connect.c | |
select oid,... upon startup. | |
current_schema() | |
convert.c | |
Uses ctid pseudo-column | |
convert_escape() generates queries. Func. should probably be | |
eliminated. | |
copy_statement_with_parameters looks dependent upon PostgresQL | |
PREPARE SQL statements. | |
(this calls Prepare_and_convert(), which also depends on them). | |
multibyte.c | |
CC_lookup_cs_new() Not run from Linux driver. Test whether | |
called from CC_lookup_characterset() from Windows ANSI client. | |
parse.c | |
CheckHasOids() | |
getCOLIfromTable() | |
results.c | |
tupleExists() uses ctid pseudo-column | |
Literal commands known to be sent over the wire: | |
select n.nspname, c.relname, a.attname, a.atttypid,t.typname, a.attnum, a.attlen, a.atttypmod, a.attnotnull, c.relhasrules, c.relkind, c.oid, d.adsrc from (((pg_catalog.pg_class c inner join pg_catalog.pg_namespace n on n.oid = c.relnamespace and c.oid = 3411470544) inner join pg_catalog.pg_attribute a on (not a.attisdropped) and a.attnum > 0 and a.attrelid = c.oid) inner join pg_catalog.pg_type t on t.oid = a.atttypid) left outer join pg_attrdef d on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum order by n.nspname, c.relname, attnum | |
select current_schema() | |
select oid, typbasetype from pg_type where typname = 'lo' | |
deallocate <cursorname> (all cases I've encountered so far seem to be | |
an over-zealous attempt by the driver to free cursors managed completely | |
EXTENDED protocol, and therefore my server code can handle these). | |
set client_encoding to... | |
Literal commands I see in code, but have not yet taken the time to confirm or | |
reject as will ever be sent to our server. Repeat: THESE STATEMENTS MAY | |
NEVER BE SENT. I will have a definitive answer about several of these shortly.: | |
"select oid, 0 from pg_type where typname='" PG_TYPE_LO_NAME "'" | |
Dynamic queries with: " where ctid = '(0,0)';select \"ctid"... from... | |
All sorts of metadata/data-dictionary stuff in "info.c" file. | |
select relhasoids, c.oid from pg_class c, pg_namespace n where relname = '%s' and nspname = '%s' and c.relnamespace = n.oid" | |
"select a.attname, a.atttypid from pg_index i, pg_attribute a where indrelid=%u and indnatts=1 and indisunique | |
and indexprs is null and indpred is null and i.indrelid = a.attrelid and a.attnum=i.indkey[0] and attnotnull and atttypid in (%d, %d)" | |
"select nspname from pg_namespace n, pg_class c" | |
"select 1 from \"%s\" where ctid = '(%d,%d)'" | |
Complex dynamic parsing or genereration code in convert.c:convert_escape(). | |
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL * | |
show max_identifier_length | |
Show Client_Encoding | |
DATA TYPE SUPPORT MATRIX (type synonyms not listed) @=Yet-to-be-Implemented | |
HyperSQL type wid prec scale | Driver type oid adtsz atttypm | |
--------------------------- --- ---- ----- - ----------- --- --- --- | |
TINYINT 8 3 0 | HSQL_TINYINT 9999 1 -1 | |
SMALLINT 16 5 0 | int2 21 2 -1 | |
INTEGER 32 10 0 | int4 23 4 -1 | |
BIGINT 64 19 0 | int8 20 8 -1 | |
NUMERIC(p?,s?) [100] [0] | numeric 1700 -1 [-1]** | |
FLOAT(p?) 128 [0] 0 | float8 701 8 -1** | |
DOUBLE 128 0 0 | float8 701 8 -1 | |
BOOLEAN 0 0 | bool 16 1 -1 | |
CHAR(1l)* = [1]++ 0 | bpchar 1042 -1 [1] | |
VARCHAR(1l) [0] 0 | varchar 1043 -1 [-1] | |
If precision unlimited/0: | text 25 -1 -1 | |
LITERAL, simple atomic str+:CHARACTER len 0 | unknown 705 -2 -1 | |
DERIVED, compound str+: VARCHAR prtlen 0 | text 25 -1 -1 | |
CLOB(1l) [0] 0 | @ | |
BINARY(1l)* [0] 0 | bytea 17 -1 -1 | |
VARBINARY(1l) [0] 0 | bytea 17 -1 -1 | |
BLOB(1l) [0] 0 | @ | |
BIT(1l)* [1] 0 | bit 1560 -1 -1 | |
BIT VARYING(1l) [0] 0 | varbit 1562 -1 -1 | |
OTHER 0 0 | @ | |
DATE 0 0 | date 1082 4 -1 | |
TIME(p0) 0 [0] | time 1083 8 [-1] | |
TIME(p0) WITH TIME ZONE 0 [0] | time_with_tmzone 1266 12 [-1] | |
TIMESTAMP(p0) 0 [6] | timestamp_no_tmzone 1114 8[-1] | |
TIMESTAMP (p0) WITH TIME ZONE 0 [6] | datetime ?1184 8 [-1]***** | |
INTERVAL...(p2,p0) [2] [6] | tinterval 1186 16 [-1]**** | |
* these types present at least a facade of data values always padded to the | |
specified length. | |
** atttypmod for numerics determines column size and scale. | |
atttypmod = (precision << 16) + scale + 4 | |
(but there seems to be a bug in psqlodbc where this still does not work). | |
*** Postgresql seems to use the FLOAT(x) precisions specifier just to decide | |
whether to create a float4 or float8 column. | |
**** I get atttypmod value of 2147418111 for INTERVAL(3) | |
= short of 32767 + short of -1 and 217418110 for INTERVAL(2) | |
So far unsuccessful to reverse engineer atttypmods for INTERVALs. | |
As of today, support for following HyperSQL INTERVAL variants: | |
DAY TO SECOND, HOUR TO SECOND, MINUTE TO SECOND, SECOND. | |
***** Seems to be a driver bug here. Should return 1296 for TIMESTAMP, not | |
1184 for DATETIME. | |
+: If HyperSQL determines the output is a known constant size, it sets the | |
precision to that. That seems to be the intention of Postgresql, but PG is | |
not as smart about figuring out when expressions will resolve to a constant. | |
When combining a constant and a col., HyperSQL confusingly some really | |
crazy lengths. I haven't figured out the method or intention. | |
++: This defaults to 1 instead of 0 if sql.enforce_strict_size is set. | |
Interval types seem to be wildly different between PG and HyperSQL. | |
I believe that for all interval literals, precisions will automatically be set | |
to preserve the specified value (unless you specify the precisions). | |
Therefore, in practice, precision specs are usually only useful in col. defs. | |
PG: INTERVAL(p); Where [0] <= p <= 6 (sub-sec. resolution, trunk/round vary!) | |
Resolution years to microsecond. Literals: | |
'1 12:59:10 ago' == '1 day 12 hours 59 min 10 sec ago' | |
'1.234' = '1.234 sec' | |
'-8 days - 12:59:10.472' | |
HS: Resolution is either in months or (sub)seconds. Can't mix. | |
p1 [2], p2[0]. | |
INTERVAL NON_SECOND(p1) TO NON_SECOND | |
Or | |
INTERVAL NON_SECOND(p1) TO SECOND(p2) | |
Or | |
INTERVAL NON_SECOND(p1) | |
Or | |
INTERVAL SECOND(p1,p2) | |
Literals | |
INTERVAL '145 23:12:19.345' DAY(3) TO SECOND(3) | |
= INTERVAL '3503:12:19.345' HOUR TO SECOND(3) | |
INTERVAL '19.345' SECOND(4,3) | |
REFERENCES | |
JDBC type mapping tables. Section "Tables for Type Mapping" of Sun's | |
"Getting Started with the JDBC API", which is section 9.9 of the current | |
version, but this section number changes with document revisions. | |
http://java.sun.com/javase/6/docs/technotes/guides/jdbc/getstart/mapping.html#1038075 | |
psqlodbc code repository. Module "psqlodbc" at | |
:pserver:anonymous@cvs.pgfoundry.org:/cvsroot/psqlodbc | |
This is the code base that our odbc driver forked from. | |
Protocol specification: | |
http://www.postgresql.org/docs/8.3/interactive/protocol.html | |
Article on ODBC escape sequences. May support these some day. | |
http://www.ibprovider.com/eng/documentation/odbc_escape_sequences_eng.html |