From 6fefe2afe3cc111c80a26f847b22f886bc25a37a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 8 Jan 2013 21:41:11 +0100 Subject: [PATCH] [#2108] SQLite returns NULL for val(new Date(0)).add(-1) and some other date time arithmetic expressions --- .../main/java/org/jooq/impl/Expression.java | 18 +++--- .../src/main/java/org/jooq/impl/MetaImpl.java | 59 ++++++++++++------- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Expression.java b/jOOQ/src/main/java/org/jooq/impl/Expression.java index 32b795466c..808738b808 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Expression.java +++ b/jOOQ/src/main/java/org/jooq/impl/Expression.java @@ -64,6 +64,7 @@ import static org.jooq.impl.Factory.bitOr; import static org.jooq.impl.Factory.bitXor; import static org.jooq.impl.Factory.field; import static org.jooq.impl.Factory.function; +import static org.jooq.impl.Factory.inline; import static org.jooq.impl.Factory.two; import static org.jooq.impl.Factory.val; @@ -403,14 +404,15 @@ class Expression extends AbstractFunction { } case SQLITE: { - String prefix = (sign > 0) ? "+" : "-"; + boolean ytm = rhs.get(0).getType() == YearToMonth.class; + Field interval = val(ytm ? rhsAsYTM().intValue() : rhsAsDTS().getTotalSeconds()); - if (rhs.get(0).getType() == YearToMonth.class) { - return field("{datetime}({0}, '" + prefix + rhsAsYTM().intValue() + " months')", getDataType(), lhs); - } - else { - return field("{datetime}({0}, '" + prefix + rhsAsDTS().getTotalSeconds() + " seconds')", getDataType(), lhs); + if (sign < 0) { + interval = interval.neg(); } + + interval = interval.concat(inline(ytm ? " months" : " seconds")); + return field("{datetime}({0}, {1})", getDataType(), lhs, interval); } case ORACLE: @@ -509,10 +511,10 @@ class Expression extends AbstractFunction { case SQLITE: if (operator == ADD) { - return field("{datetime}({0}, '+" + rhsAsNumber() + " day')", getDataType(), lhs); + return field("{datetime}({0}, {1})", getDataType(), lhs, rhsAsNumber().concat(inline(" day"))); } else { - return field("{datetime}({0}, '-" + rhsAsNumber() + " day')", getDataType(), lhs); + return field("{datetime}({0}, {1})", getDataType(), lhs, rhsAsNumber().neg().concat(inline(" day"))); } // These dialects can add / subtract days using +/- operators diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java index 6482580b53..f0a7fd8d1c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java @@ -35,6 +35,7 @@ */ package org.jooq.impl; +import static org.jooq.SQLDialect.SQLITE; import static org.jooq.impl.Factory.fieldByName; import java.sql.DatabaseMetaData; @@ -183,26 +184,6 @@ class MetaImpl implements Meta { } try { - columnCache = executor - .fetch( - meta().getColumns(null, getName(), "%", "%"), - - // Work around a bug in the SQL Server JDBC driver by - // coercing data types to the expected types - // The bug was reported here: - // https://connect.microsoft.com/SQLServer/feedback/details/775425/jdbc-4-0-databasemetadata-getcolumns-returns-a-resultset-whose-resultsetmetadata-is-inconsistent - String.class, // TABLE_CAT - String.class, // TABLE_SCHEM - String.class, // TABLE_NAME - String.class, // COLUMN_NAME - int.class, // DATA_TYPE - String.class, // TYPE_NAME - int.class, // COLUMN_SIZE - String.class, // BUFFER_LENGTH - int.class // DECIMAL_DIGITS - ) - .intoGroups(fieldByName(String.class, "TABLE_NAME")); - List> result = new ArrayList>(); Result tables = executor.fetch(meta().getTables(null, getName(), "%", null)); @@ -211,7 +192,7 @@ class MetaImpl implements Meta { // String schema = table.getValue(1, String.class); String name = table.getValue(2, String.class); - result.add(new MetaTable(name, this, columnCache.get(name))); + result.add(new MetaTable(name, this, getColumns(name))); // TODO: Find a more efficient way to do this // Result pkColumns = executor.fetch(meta().getPrimaryKeys(catalog, schema, name)) @@ -231,6 +212,42 @@ class MetaImpl implements Meta { throw new DataAccessException("Error while accessing DatabaseMetaData", e); } } + + private final Result getColumns(String tableName) throws SQLException { + + // SQLite JDBC's DatabaseMetaData.getColumns() can only return a single + // table's columns + if (columnCache == null && executor.getDialect() != SQLITE) { + columnCache = getColumns0("%").intoGroups(fieldByName(String.class, "TABLE_NAME")); + } + + if (columnCache != null) { + return columnCache.get(tableName); + } + else { + return getColumns0(tableName); + } + } + + private final Result getColumns0(String tableName) throws SQLException { + return executor.fetch( + meta().getColumns(null, null, tableName, "%"), + + // Work around a bug in the SQL Server JDBC driver by + // coercing data types to the expected types + // The bug was reported here: + // https://connect.microsoft.com/SQLServer/feedback/details/775425/jdbc-4-0-databasemetadata-getcolumns-returns-a-resultset-whose-resultsetmetadata-is-inconsistent + String.class, // TABLE_CAT + String.class, // TABLE_SCHEM + String.class, // TABLE_NAME + String.class, // COLUMN_NAME + int.class, // DATA_TYPE + String.class, // TYPE_NAME + int.class, // COLUMN_SIZE + String.class, // BUFFER_LENGTH + int.class // DECIMAL_DIGITS + ); + } } private class MetaTable extends TableImpl {