Обсуждение: some improve JDBC
Hi all! My name is Victor, I lead the enterprise www.e-evolution.com, we are working in making a port of software Compiere (www.compiere.org) that now only works with oracle to PostgreSQL. Compiere use the RowSet implementation, I made some changes to the source AbstractJdbc2ResultSetMetaData method: /* * What is the column's normal maximum width in characters? * * @param column the first column is 1, the second is 2, etc. * @return the maximum width * @exception SQLException if a database access error occurs */ public int getColumnDisplaySize(int column) throws SQLException { Field f = getField(column); String type_name = getPGType(column); int typmod = f.getMod(); // I looked at other JDBC implementations and couldn't find a consistent // interpretation of the "display size" for numeric values, so this is our's // FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de // fixed length data types if (type_name.equals( "int2" )) return 6; // -32768 to +32768 (5 digits and a sign) if (type_name.equals( "int4" ) || type_name.equals( "oid" )) return 11; // -2147483648 to +2147483647 if (type_name.equals( "int8" )) return 20; // -9223372036854775808 to +9223372036854775807 if (type_name.equals( "money" )) return 12; // MONEY = DECIMAL(9,2) if (type_name.equals( "float4" )) return 11; // i checked it out ans wasn't able to produce more than 11 digits if (type_name.equals( "float8" )) return 20; // dito, 20 if (type_name.equals( "char" )) return 1; if (type_name.equals( "bool" )) return 1; int secondSize; switch (typmod) { case 0: secondSize = 0; break; case - 1: // six digits plus the decimal point secondSize = 7; break; default: // with an odd scale an even number of digits // are always show so timestamp(1) will print // two fractional digits. secondSize = typmod + (typmod % 2) + 1; break; } if (type_name.equals( "date" )) return 13; // "01/01/4713 BC" - "31/12/32767" // If we knew the timezone we could avoid having to possibly // account for fractional hour offsets (which adds three chars). // // Also the range of timestamp types is not exactly clear. // 4 digits is the common case for a year, but there are // version/compilation dependencies on the exact date ranges, // (notably --enable-integer-datetimes), but for now we'll // just ignore them and assume that a year is four digits. // if (type_name.equals( "time" )) return 8 + secondSize; // 00:00:00 + seconds if (type_name.equals( "timetz" )) return 8 + secondSize + 6; // 00:00.00 + .000000 + -00:00 if (type_name.equals( "timestamp" )) return 19 + secondSize; // 0000-00-00 00:00:00 + .000000; if (type_name.equals( "timestamptz" )) return 19 + secondSize + 6; // 0000-00-00 00:00:00 + .000000 + -00:00; //begin vpj-cd e-evolution if (type_name.equals( "text") || type_name.equals("bytea")) { if (typmod == -1) return 0; else return typmod; } if (type_name.equals( "unknown")) return 0; //end vpj-cd e-evolution // variable length fields typmod -= 4; if (type_name.equals( "bpchar" ) || type_name.equals( "varchar" )) // being vpj-cd e-evolution 07/30/2005 { if (typmod < 0) return 0; else return typmod; // VARHDRSZ=sizeof(int32)=4 } // end vpj-cd e-evolution 07/30/2005 if (type_name.equals( "numeric" )) { //return ( (typmod >> 16) & 0xffff ) // + 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = (p digits). (s digits) if( ((typmod >> 16) & 0xffff ) + 1 + ( typmod & 0xffff ) == -1) return 0; else return ( (typmod >> 16) & 0xffff ) + 1 + ( typmod & 0xffff ); } // if we don't know better return f.getLength(); } * JDBC driver build number 8.1dev-401 JDBC Source * Server version PostgreSQL 8.0.3 in Linux AMD64 Cheers Victor Pérez CEO e-Evolution,SC www.e-evolution.com
Víctor Pérez Juárez wrote: > Compiere use the RowSet implementation, I made some changes to the source > AbstractJdbc2ResultSetMetaData method: Can you send a diff? I can't see what you've changed from just this. -O
Of cosure! my changes are commnet with e-evolution //begin vpj-cd e-evolution if (type_name.equals( "text") || type_name.equals("bytea")) { if (typmod == -1) return 0; else return typmod; } if (type_name.equals( "unknown")) return 0; //end vpj-cd e-evolution // being vpj-cd e-evolution 07/30/2005 { if (typmod < 0) return 0; else return typmod; // VARHDRSZ=sizeof(int32)=4 } // end vpj-cd e-evolution 07/30/2005 --------------------------------------------------------------------------------------------------------------------------------------- the code complete: /* * What is the column's normal maximum width in characters? * * @param column the first column is 1, the second is 2, etc. * @return the maximum width * @exception SQLException if a database access error occurs */ public int getColumnDisplaySize(int column) throws SQLException { Field f = getField(column); String type_name = getPGType(column); int typmod = f.getMod(); // I looked at other JDBC implementations and couldn't find a consistent // interpretation of the "display size" for numeric values, so this is our's // FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de // fixed length data types if (type_name.equals( "int2" )) return 6; // -32768 to +32768 (5 digits and a sign) if (type_name.equals( "int4" ) || type_name.equals( "oid" )) return 11; // -2147483648 to +2147483647 if (type_name.equals( "int8" )) return 20; // -9223372036854775808 to +9223372036854775807 if (type_name.equals( "money" )) return 12; // MONEY = DECIMAL(9,2) if (type_name.equals( "float4" )) return 11; // i checked it out ans wasn't able to produce more than 11 digits if (type_name.equals( "float8" )) return 20; // dito, 20 if (type_name.equals( "char" )) return 1; if (type_name.equals( "bool" )) return 1; int secondSize; switch (typmod) { case 0: secondSize = 0; break; case - 1: // six digits plus the decimal point secondSize = 7; break; default: // with an odd scale an even number of digits // are always show so timestamp(1) will print // two fractional digits. secondSize = typmod + (typmod % 2) + 1; break; } if (type_name.equals( "date" )) return 13; // "01/01/4713 BC" - "31/12/32767" // If we knew the timezone we could avoid having to possibly // account for fractional hour offsets (which adds three chars). // // Also the range of timestamp types is not exactly clear. // 4 digits is the common case for a year, but there are // version/compilation dependencies on the exact date ranges, // (notably --enable-integer-datetimes), but for now we'll // just ignore them and assume that a year is four digits. // if (type_name.equals( "time" )) return 8 + secondSize; // 00:00:00 + seconds if (type_name.equals( "timetz" )) return 8 + secondSize + 6; // 00:00.00 + .000000 + -00:00 if (type_name.equals( "timestamp" )) return 19 + secondSize; // 0000-00-00 00:00:00 + .000000; if (type_name.equals( "timestamptz" )) return 19 + secondSize + 6; // 0000-00-00 00:00:00 + .000000 + -00:00; //begin vpj-cd e-evolution if (type_name.equals( "text") || type_name.equals("bytea")) { if (typmod == -1) return 0; else return typmod; } if (type_name.equals( "unknown")) return 0; //end vpj-cd e-evolution // variable length fields typmod -= 4; if (type_name.equals( "bpchar" ) || type_name.equals( "varchar" )) // being vpj-cd e-evolution 07/30/2005 { if (typmod < 0) return 0; else return typmod; // VARHDRSZ=sizeof(int32)=4 } // end vpj-cd e-evolution 07/30/2005 if (type_name.equals( "numeric" )) { //return ( (typmod >> 16) & 0xffff ) // + 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = (p digits). (s digits) if( ((typmod >> 16) & 0xffff ) + 1 + ( typmod & 0xffff ) == -1) return 0; else return ( (typmod >> 16) & 0xffff ) + 1 + ( typmod & 0xffff ); } // if we don't know better return f.getLength(); } * JDBC driver build number 8.1dev-401 JDBC Source * Server version PostgreSQL 8.0.3 in Linux AMD64 Cheers Victor Pérez CEO e-Evolution,SC www.e-evolution.com El Martes, 2 de Agosto de 2005 18:55, Oliver Jowett escribió: > Víctor Pérez Juárez wrote: > > Compiere use the RowSet implementation, I made some changes to the source > > AbstractJdbc2ResultSetMetaData method: > > Can you send a diff? I can't see what you've changed from just this. > > -O > > ---------------------------(end of broadcast)--------------------------- > TIP 3: Have you checked our extensive FAQ? > > http://www.postgresql.org/docs/faq
Victor, What we need is a cvs diff cvs diff -c .... Then we can apply it using patch after we read it and approve it Dave On 3-Aug-05, at 1:20 PM, Víctor Pérez Juárez wrote: > Of cosure! > > my changes are commnet with e-evolution > > //begin vpj-cd e-evolution > if (type_name.equals( "text") || type_name.equals("bytea")) > { > if (typmod == -1) > return 0; > else > return typmod; > } > if (type_name.equals( "unknown")) > return 0; > //end vpj-cd e-evolution > > // being vpj-cd e-evolution 07/30/2005 > { > if (typmod < 0) > return 0; > else > return typmod; // VARHDRSZ=sizeof(int32)=4 > } > // end vpj-cd e-evolution 07/30/2005 > ---------------------------------------------------------------------- > ----------------------------------------------------------------- > the code complete: > > /* > * What is the column's normal maximum width in characters? > * > * @param column the first column is 1, the second is 2, etc. > * @return the maximum width > * @exception SQLException if a database access error occurs > */ > > public int getColumnDisplaySize(int column) throws SQLException > { > Field f = getField(column); > String type_name = getPGType(column); > int typmod = f.getMod(); > > // I looked at other JDBC implementations and couldn't find a > consistent > // interpretation of the "display size" for numeric values, > so this is > our's > // FIXME: currently, only types with a SQL92 or SQL3 > pendant are > implemented - jens@jens.de > > // fixed length data types > if (type_name.equals( "int2" )) > return 6; // -32768 to +32768 (5 digits and a sign) > if (type_name.equals( "int4" ) > || type_name.equals( "oid" )) > return 11; // -2147483648 to +2147483647 > if (type_name.equals( "int8" )) > return 20; // -9223372036854775808 to +9223372036854775807 > if (type_name.equals( "money" )) > return 12; // MONEY = DECIMAL(9,2) > if (type_name.equals( "float4" )) > return 11; // i checked it out ans wasn't able to > produce more > than 11 digits > if (type_name.equals( "float8" )) > return 20; // dito, 20 > if (type_name.equals( "char" )) > return 1; > if (type_name.equals( "bool" )) > return 1; > > int secondSize; > switch (typmod) > { > case 0: > secondSize = 0; > break; > case - 1: > // six digits plus the decimal point > secondSize = 7; > break; > default: > // with an odd scale an even number of digits > // are always show so timestamp(1) will print > // two fractional digits. > secondSize = typmod + (typmod % 2) + 1; > break; > } > > if (type_name.equals( "date" )) > return 13; // "01/01/4713 BC" - "31/12/32767" > > // If we knew the timezone we could avoid having to possibly > // account for fractional hour offsets (which adds three > chars). > // > // Also the range of timestamp types is not exactly clear. > // 4 digits is the common case for a year, but there are > // version/compilation dependencies on the exact date ranges, > // (notably --enable-integer-datetimes), but for now we'll > // just ignore them and assume that a year is four digits. > // > if (type_name.equals( "time" )) > return 8 + secondSize; // 00:00:00 + seconds > if (type_name.equals( "timetz" )) > return 8 + secondSize + 6; // 00:00.00 + .000000 + -00:00 > if (type_name.equals( "timestamp" )) > return 19 + secondSize; // 0000-00-00 00:00:00 + .000000; > if (type_name.equals( "timestamptz" )) > return 19 + secondSize + 6; // 0000-00-00 00:00:00 + . > 000000 + > -00:00; > > //begin vpj-cd e-evolution > if (type_name.equals( "text") || type_name.equals("bytea")) > { > if (typmod == -1) > return 0; > else > return typmod; > } > if (type_name.equals( "unknown")) > return 0; > //end vpj-cd e-evolution > > > // variable length fields > typmod -= 4; > if (type_name.equals( "bpchar" ) > || type_name.equals( "varchar" )) > // being vpj-cd e-evolution 07/30/2005 > { > if (typmod < 0) > return 0; > else > return typmod; // VARHDRSZ=sizeof(int32)=4 > } > // end vpj-cd e-evolution 07/30/2005 > > if (type_name.equals( "numeric" )) > { > //return ( (typmod >> 16) & 0xffff ) > // + 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = > (p digits). > (s digits) > if( ((typmod >> 16) & 0xffff ) + 1 + ( typmod & > 0xffff ) == -1) > return 0; > else > return ( (typmod >> 16) & 0xffff ) > + 1 + ( typmod & 0xffff ); > } > // if we don't know better > return f.getLength(); > } > > > * JDBC driver build number > 8.1dev-401 JDBC Source > * Server version > PostgreSQL 8.0.3 in Linux AMD64 > > > Cheers > Victor Pérez > CEO > e-Evolution,SC > www.e-evolution.com > > > El Martes, 2 de Agosto de 2005 18:55, Oliver Jowett escribió: > >> Víctor Pérez Juárez wrote: >> >>> Compiere use the RowSet implementation, I made some changes to >>> the source >>> AbstractJdbc2ResultSetMetaData method: >>> >> >> Can you send a diff? I can't see what you've changed from just this. >> >> -O >> >> ---------------------------(end of >> broadcast)--------------------------- >> TIP 3: Have you checked our extensive FAQ? >> >> http://www.postgresql.org/docs/faq >> > > ---------------------------(end of > broadcast)--------------------------- > TIP 3: Have you checked our extensive FAQ? > > http://www.postgresql.org/docs/faq > >
Víctor Pérez Juárez wrote: > Of cosure! > > my changes are commnet with e-evolution [...] In the future, please supply a proper diff ('cvs diff -c' will do the trick if you are working from CVS). It's very hard to see the changes you've made otherwise. It appears to boil down to "return 0 instead of -1 for column display size when we don't know the actual length"? Why is 0 better than -1 in this case? I don't see anything in the JDBC spec that covers this.. -O
Hi Oliver! The problem is that RowSet launchs an exception when JDBC return -1 this cause my Aplicaction does not work the reasons are down. The source code in package javax.sql.rowset.RowSetMetaDataImpl.java /** * Sets the normal maximum number of chars in the designated column * to the given number. * * @param columnIndex the first column is 1, the second is 2, and so on; * must be between <code>1</code> and the number of columns, inclusive * @param size the maximum size of the column in chars; must be * <code>0</code> or more * @throws SQLException if a database access error occurs, * the given column number is out of bounds, or <i>size</i> is * less than <code>0</code> */ public void setColumnDisplaySize(int columnIndex, int size) throws SQLException { if (size < 0) { throw new SQLException("Invalid column display size. Cannot be less " + "than zero"); } checkColRange(columnIndex); colInfo[columnIndex].columnDisplaySize = size; } the same case is for setPrecision,setScale Cheers -- Víctor Pérez Juárez CEO e-Evolution,S.C. www.e-evolution.com victor.perez@e-evolution.com teléfono: (52)7711070937 skype: vpj-cd El Miércoles, 3 de Agosto de 2005 19:17, Oliver Jowett escribió: > Víctor Pérez Juárez wrote: > > Of cosure! > > > > my changes are commnet with e-evolution > > [...] > > In the future, please supply a proper diff ('cvs diff -c' will do the > trick if you are working from CVS). It's very hard to see the changes > you've made otherwise. > > It appears to boil down to "return 0 instead of -1 for column display > size when we don't know the actual length"? > > Why is 0 better than -1 in this case? I don't see anything in the JDBC > spec that covers this.. > > -O > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Have you searched our list archives? > > http://archives.postgresql.org
Víctor Pérez Juárez wrote: > The problem is that RowSet launchs an exception when JDBC return -1 this cause > my Aplicaction does not work the reasons are down. This has been discussed at some length in the past -- see the archives. It's not clear where the fault lies -- according to the JDBC spec, -1 seems like a perfectly valid value to return. As I understand it Sun were going to check their implementation and get back to us, but that hasn't happened yet. Kris was reluctant to change the driver code just for the sake of Sun's implementation. Have you contacted Sun about this to see if they are planning to change their code? -O