Ok, perhaps it needs to wait until the C api matures a bit. One other
observation though, if I may. DatabaseMetaData.getColumns() returns
yet another data type code:
My revised test driver produces the following output:
*** Before insert (empty table) ***
Column type from DatabaseMetaData: 12
Column type name from DatabaseMetaData: INTEGER
Column type from ResultSetMetaData: 0
Column type name from ResultSetMetaData: integer
*** After insert (one record table) ***
Column type from DatabaseMetaData: 12
Column type name from DatabaseMetaData: INTEGER
Column type from ResultSetMetaData: 4
Column type name from ResultSetMetaData: integer
Perhaps the DatabaseMetaData implementation could be used to implement
ResultSetMetaData.getColumnType/getColumnTypeName implementation to
make the values returned consistent? At least that way the type
information is consistent (albeit, misleading as in this case it is
identified as a TEXT / VARCHAR type field). Unless of course the
implementation for DatabaseMetaData.getColumns is hard-coded to always
return TEXT / VARCHAR. In that case then it's not really helpful.
I'm not sure how the value of a column could ever be returned as it's
type. I'm not seeing that in my test - at lease I don't think I am.
The new test case is below.
Rob
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
public class TestSQLite
{
public static void main(String[] args) throws Exception
{
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:/tmp/
test.dbf");
Statement stat = conn.createStatement();
stat.executeUpdate("drop table if exists test");
stat.executeUpdate("create table test (myid integer)");
stat.close();
System.out.println("\t *** Before insert (empty table) *** \n");
getDatabaseMetaDataType(conn, "test", "myid");
printColumnTypeAndName(conn);
PreparedStatement prep = conn.prepareStatement("insert into test
values (?)");
prep.setInt(1, 1);
prep.executeUpdate();
System.out.println("\t *** After insert (one record table) ***
\n");
getDatabaseMetaDataType(conn, "test", "myid");
printColumnTypeAndName(conn);
conn.close();
}
private static void printColumnTypeAndName(Connection conn) throws
Exception
{
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from test");
ResultSetMetaData md = rs.getMetaData();
System.out.println("Column type from ResultSetMetaData: " +
md.getColumnType(1));
System.out.println("Column type name from ResultSetMetaData: " +
md.getColumnTypeName(1) + "\n");
rs.close();
}
private static int getDatabaseMetaDataType(Connection conn, String
tableName, String columnName) throws Exception {
int result = -1;
ResultSet rs = conn.getMetaData().getColumns(null, null,
tableName,
columnName);
while (rs.next()) {
int columnType = rs.getInt(5);
String columnTypeName = rs.getString(6);
System.out.println("Column type from DatabaseMetaData:
"+columnType);
System.out.println("Column type name from
DatabaseMetaData:
"+columnTypeName+"\n");
}
rs.close();
return result;
}
}
On Jun 17, 7:58 pm, "David Crawshaw" <[EMAIL PROTECTED]> wrote:
> I do not think it is possible to access the column type affinity
> through the SQLite C interface. So I cannot have getColumnType() work
> the way you would like.
>
> Right now, getCoulmnTypeName() is doing something silly, it is
> returning the name given to the type by the user. This means if
> something does this:
>
> create table t1 (col1 blahtype);
>
> Then getColumnTypeName() will return "blahtype". Which is not helpful.
> Worse, someone can do this:
>
> create table t1 (col1 integer);
> insert into t1 values ('hello');
>
> And then any poor program that relied on the meta data gets "hello"
> instead of an integer. I think the only thing to do here is to make
> getColumnTypeName() return a string version of getColumnType(), which
> returns the affinity type of the current row. I know this is even
> further from what you want, but such is life when interfacing manifest
> typing with strict typing.
>
> d.
>
> 2008/6/17 [EMAIL PROTECTED] <[EMAIL PROTECTED]>:
>
>
>
> > From the article you referenced, I believe that the
> > ResultSetMetaData.getColumnType method should provide the column
> > affinity, if the table was created using a type:
>
> > "The type affinity of a column is determined by the declared type of
> > the column, according to the following rules:
>
> > 1. If the datatype contains the string "INT" then it is assigned
> > INTEGER affinity."
>
> > This example (from the documentation) seems to speak to what I mean:
>
> > 2.2 Column Affinity Example
>
> > CREATE TABLE t1(
> > t TEXT,
> > nu NUMERIC,
> > i INTEGER,
> > no BLOB
> > );
>
> > -- Storage classes for the following row:
> > -- TEXT, REAL, INTEGER, TEXT
> > INSERT INTO t1 VALUES('500.0', '500.0', '500.0', '500.0');
>
> > -- Storage classes for the following row:
> > -- TEXT, REAL, INTEGER, REAL
> > INSERT INTO t1 VALUES(500.0, 500.0, 500.0, 500.0);
>
> > Notice how in the first insert statement, the data value for the
> > INTEGER column (i) is '500.0', but the storage class is INTEGER
> > because the column was created using the INTEGER type. The column
> > affinity doesn't appear to be affected by the number of rows in the
> > table - which is the behavior that the driver seems to have currently
> > - but only for the type code. The type column name appears to be
> > correct (my test output erroneously refers to this value as
> > getColumnName, when it was actually the getColumnTypeName value)
>
> > In the test case I provided, also notice how the column type name
> > (getColumnName) is "integer" in both cases, whereas the type code
> > switched from 0 to 4 when records were added. I don't see how this
> > driver behavior is consistent with the documentation.
>
> > Rob
>
> > On Jun 17, 1:51 am, "David Crawshaw" <[EMAIL PROTECTED]> wrote:
> >> Robert. M. Manning wrote:
> >> > I'm trying to add support for SQLiteJDBC to SQuirreL SQL Client and I
> >> > came across some odd behavior. If I declare a table with a single
> >> > integer column, select from it (no records - just an emtpy ResultSet)
> >> > and look at the ResultSet's MetaData, the column type is returned as
> >> > zero (java.sql.Types.NULL). However when I insert a record into it,
> >> > and do another select, the column type is reported to be integer
> >> > (java.sql.Types.INTEGER). Shouldn't the column type be consistent
> >> > regardless of whether or not the table has data? My test below yields
> >> > the following output:
>
> >> > getColumnType: 0
> >> > getColumnName: integer
> >> > getColumnType: 4
> >> > getColumnName: integer
>
> >> This is the nature of SQLite, it is not strictly typed. To quote:
>
> >> In SQLite version 3, the type of a value is associated with the
> >> value itself, not with the column or variable in which the value
> >> is stored. (This is sometimes called manifest typing.)
>
> >>http://sqlite.org/datatype3.html
>
> >> d.
>
>
--~--~---------~--~----~------------~-------~--~----~
Mailing List: http://groups.google.com/group/sqlitejdbc?hl=en
To unsubscribe, send email to [EMAIL PROTECTED]
-~----------~----~----~----~------~----~------~--~---