add more date/time routines with java.time where possible
This commit is contained in:
parent
bfe943606e
commit
44e9eac4ac
35 changed files with 703 additions and 619 deletions
gradle.properties
jdbc-mariadb/src
jdbc-oracle/src
jdbc-postgresql/src
main/java/org/xbib/jdbc/postgresql
test/java/org/xbib/jdbc/postgresql/test
jdbc-query/src
main/java/org/xbib/jdbc/query
DatabaseImpl.javaDatabaseProvider.javaFlavor.javaOptions.javaOptionsDefault.javaOptionsOverride.javaRow.javaRowsAdapter.javaSchema.javaSqlInsert.javaSqlInsertImpl.javaSqlSelect.javaSqlSelectImpl.javaSqlUpdateImpl.javaStatementAdapter.java
flavor
test/java/org/xbib/jdbc/query/test
jdbc-sqlserver
jdbc-test/src/main/java/org/xbib/jdbc/test
settings.gradle
|
@ -1,3 +1,3 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = database
|
name = database
|
||||||
version = 2.3.3
|
version = 2.4.0
|
||||||
|
|
|
@ -103,13 +103,23 @@ public class MariaDB implements Flavor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDateTime() {
|
public String typeInstant() {
|
||||||
return "datetime(3)";
|
return "timestamp(3)"; // 3 = millisecond resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String columnTypeLocalDateTime() {
|
public String typeLocalDateTime() {
|
||||||
return "DATETIME";
|
return "timestamp(3)"; // 3 = millisecond resolution
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeOffsetDateTime() {
|
||||||
|
return "datetime(3)"; // 3 = millisecond resolution
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeZonedDateTime() {
|
||||||
|
return "datetime(3)"; // 3 = millisecond resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,7 +44,11 @@ public class MariaDBTest extends CommonTest {
|
||||||
@Override
|
@Override
|
||||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) {
|
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) {
|
||||||
return DatabaseProvider.builder(getClass().getClassLoader(),
|
return DatabaseProvider.builder(getClass().getClassLoader(),
|
||||||
mariaDBContainer.getJdbcUrl(), null, null, "testUser", "testPassword")
|
mariaDBContainer.getJdbcUrl(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"testUser",
|
||||||
|
"testPassword")
|
||||||
.withSqlParameterLogging()
|
.withSqlParameterLogging()
|
||||||
.withSqlInExceptionMessages()
|
.withSqlInExceptionMessages()
|
||||||
.withOptions(options)
|
.withOptions(options)
|
||||||
|
@ -154,7 +158,7 @@ public class MariaDBTest extends CommonTest {
|
||||||
.argClobString("hello again")
|
.argClobString("hello again")
|
||||||
.argBlobBytes(new byte[]{'1', '2'})
|
.argBlobBytes(new byte[]{'1', '2'})
|
||||||
.argBoolean(true)
|
.argBoolean(true)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow)
|
.argLocalDate(localDateNow)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
|
|
||||||
|
@ -170,7 +174,7 @@ public class MariaDBTest extends CommonTest {
|
||||||
.argClobString("bye again")
|
.argClobString("bye again")
|
||||||
.argBlobBytes(new byte[]{'3', '4'})
|
.argBlobBytes(new byte[]{'3', '4'})
|
||||||
.argBoolean(false)
|
.argBoolean(false)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow)
|
.argLocalDate(localDateNow)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
|
|
||||||
|
@ -227,7 +231,7 @@ public class MariaDBTest extends CommonTest {
|
||||||
.argString("str_lob", "bye again")
|
.argString("str_lob", "bye again")
|
||||||
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
||||||
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
||||||
.argLocalDateTime("date_millis", now)
|
.argLocalDateTime("date_millis", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow),
|
.argLocalDate("local_date", localDateNow),
|
||||||
new SqlArgs()
|
new SqlArgs()
|
||||||
.argInteger("nbr_integer", Integer.MAX_VALUE)
|
.argInteger("nbr_integer", Integer.MAX_VALUE)
|
||||||
|
@ -240,7 +244,7 @@ public class MariaDBTest extends CommonTest {
|
||||||
.argString("str_lob", "hello again")
|
.argString("str_lob", "hello again")
|
||||||
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
||||||
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
||||||
.argLocalDateTime("date_millis", now)
|
.argLocalDateTime("date_millis", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow)),
|
.argLocalDate("local_date", localDateNow)),
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
||||||
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
||||||
|
|
|
@ -50,16 +50,6 @@ public class Oracle implements Flavor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Override
|
|
||||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
|
||||||
if (preparedStatement instanceof ProxyPreparedStatement) {
|
|
||||||
ProxyPreparedStatement proxyPreparedStatement = (ProxyPreparedStatement) preparedStatement;
|
|
||||||
((OraclePreparedStatement) proxyPreparedStatement.getDelegate()).setBinaryFloat(i, floatValue);
|
|
||||||
} else {
|
|
||||||
((OraclePreparedStatement) preparedStatement).setBinaryFloat(i, floatValue);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeDouble() {
|
public String typeDouble() {
|
||||||
return "binary_double";
|
return "binary_double";
|
||||||
|
@ -71,16 +61,6 @@ public class Oracle implements Flavor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Override
|
|
||||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
|
||||||
if (preparedStatement instanceof ProxyPreparedStatement) {
|
|
||||||
ProxyPreparedStatement proxyPreparedStatement = (ProxyPreparedStatement) preparedStatement;
|
|
||||||
((OraclePreparedStatement) proxyPreparedStatement.getDelegate()).setBinaryDouble(i, doubleValue);
|
|
||||||
} else {
|
|
||||||
((OraclePreparedStatement) preparedStatement).setBinaryDouble(i, doubleValue);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeBigDecimal(int size, int precision) {
|
public String typeBigDecimal(int size, int precision) {
|
||||||
return "numeric(" + size + "," + precision + ")";
|
return "numeric(" + size + "," + precision + ")";
|
||||||
|
@ -102,17 +82,28 @@ public class Oracle implements Flavor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDateTime() {
|
public String typeInstant() {
|
||||||
return "timestamp(3)";
|
return "timestamp";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String columnTypeLocalDateTime() {
|
public String typeLocalDateTime() {
|
||||||
return "TIMESTAMP";
|
return "timestamp";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeOffsetDateTime() {
|
||||||
|
return "timestamp with time zone";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeZonedDateTime() {
|
||||||
|
return "timestamp with time zone";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDate() {
|
public String typeLocalDate() {
|
||||||
|
// well, this is a full blown timestamp in Oracle
|
||||||
return "date";
|
return "date";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,11 @@ public class OracleTest extends CommonTest {
|
||||||
@Override
|
@Override
|
||||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
||||||
return DatabaseProvider.builder(getClass().getClassLoader(),
|
return DatabaseProvider.builder(getClass().getClassLoader(),
|
||||||
oracleContainer.getJdbcUrl(), null, null, "testUser", "testPassword")
|
oracleContainer.getJdbcUrl(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"testUser",
|
||||||
|
"testPassword")
|
||||||
.withSqlParameterLogging()
|
.withSqlParameterLogging()
|
||||||
.withSqlInExceptionMessages()
|
.withSqlInExceptionMessages()
|
||||||
.withOptions(options)
|
.withOptions(options)
|
||||||
|
|
|
@ -100,15 +100,25 @@ public class Postgresql implements Flavor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDateTime() {
|
public String typeInstant() {
|
||||||
return "timestamp(3)";
|
return "timestamp";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String columnTypeLocalDateTime() {
|
public String typeLocalDateTime() {
|
||||||
return "timestamp";
|
return "timestamp";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeOffsetDateTime() {
|
||||||
|
return "timestamp with time zone";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeZonedDateTime() {
|
||||||
|
return "timestamp with time zone";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDate() {
|
public String typeLocalDate() {
|
||||||
return "date";
|
return "date";
|
||||||
|
|
|
@ -20,7 +20,6 @@ public class PostgresqlTest extends CommonTest {
|
||||||
static PostgreSQLContainer<?> postgreSQLContainer;
|
static PostgreSQLContainer<?> postgreSQLContainer;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// postgresql 9.6.12
|
|
||||||
postgreSQLContainer = new PostgreSQLContainer<>("postgres")
|
postgreSQLContainer = new PostgreSQLContainer<>("postgres")
|
||||||
.withDatabaseName("testDB")
|
.withDatabaseName("testDB")
|
||||||
.withUsername("testUser")
|
.withUsername("testUser")
|
||||||
|
@ -39,12 +38,12 @@ public class PostgresqlTest extends CommonTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
||||||
Config config = ConfigSupplier.of()
|
return DatabaseProvider.builder(getClass().getClassLoader(),
|
||||||
.property("database.url", postgreSQLContainer.getJdbcUrl())
|
postgreSQLContainer.getJdbcUrl(),
|
||||||
.property("database.user", "testUser")
|
null,
|
||||||
.property("database.password", "testPassword")
|
null,
|
||||||
.get();
|
"testUser",
|
||||||
return DatabaseProvider.builder(config)
|
"testPassword")
|
||||||
.withSqlParameterLogging()
|
.withSqlParameterLogging()
|
||||||
.withSqlInExceptionMessages()
|
.withSqlInExceptionMessages()
|
||||||
.withOptions(options)
|
.withOptions(options)
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.logging.Logger;
|
||||||
*/
|
*/
|
||||||
public class DatabaseImpl implements Database {
|
public class DatabaseImpl implements Database {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Database.class.getName());
|
private static final Logger logger = Logger.getLogger(DatabaseImpl.class.getName());
|
||||||
|
|
||||||
private final Connection connection;
|
private final Connection connection;
|
||||||
|
|
||||||
|
@ -354,15 +354,17 @@ public class DatabaseImpl implements Database {
|
||||||
ResultSetMetaData md = rows.getMetadata();
|
ResultSetMetaData md = rows.getMetadata();
|
||||||
List<Object> columnLabels = new ArrayList<>();
|
List<Object> columnLabels = new ArrayList<>();
|
||||||
List<Object> classNames = new ArrayList<>();
|
List<Object> classNames = new ArrayList<>();
|
||||||
|
List<Object> columnTypeNames = new ArrayList<>();
|
||||||
for (int i = 1; i <= md.getColumnCount(); i++) {
|
for (int i = 1; i <= md.getColumnCount(); i++) {
|
||||||
columnLabels.add(md.getColumnLabel(i));
|
columnLabels.add(md.getColumnLabel(i));
|
||||||
classNames.add(md.getColumnClassName(i));
|
classNames.add(md.getColumnClassName(i));
|
||||||
|
columnTypeNames.add(md.getColumnTypeName(i));
|
||||||
}
|
}
|
||||||
table.add(columnLabels);
|
table.add(columnLabels);
|
||||||
table.add(classNames);
|
table.add(classNames);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (rows.next() && (limit <= 0 || i++ < limit)) {
|
while (rows.next() && (limit <= 0 || i++ < limit)) {
|
||||||
table.add(getRow(rows, classNames));
|
table.add(getRow(rows, classNames, columnTypeNames));
|
||||||
}
|
}
|
||||||
table.setTotal(rows.rowCount());
|
table.setTotal(rows.rowCount());
|
||||||
return true;
|
return true;
|
||||||
|
@ -382,15 +384,17 @@ public class DatabaseImpl implements Database {
|
||||||
ResultSetMetaData md = rows.getMetadata();
|
ResultSetMetaData md = rows.getMetadata();
|
||||||
List<Object> columnLabels = new ArrayList<>();
|
List<Object> columnLabels = new ArrayList<>();
|
||||||
List<Object> classNames = new ArrayList<>();
|
List<Object> classNames = new ArrayList<>();
|
||||||
|
List<Object> columnTypeNames = new ArrayList<>();
|
||||||
for (int i = 1; i <= md.getColumnCount(); i++) {
|
for (int i = 1; i <= md.getColumnCount(); i++) {
|
||||||
columnLabels.add(md.getColumnLabel(i));
|
columnLabels.add(md.getColumnLabel(i));
|
||||||
classNames.add(md.getColumnClassName(i));
|
classNames.add(md.getColumnClassName(i));
|
||||||
|
columnTypeNames.add(md.getColumnTypeName(i));
|
||||||
}
|
}
|
||||||
consumer.accept(columnLabels);
|
consumer.accept(columnLabels);
|
||||||
consumer.accept(classNames);
|
consumer.accept(classNames);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (rows.next() && (limit <= 0 || i++ < limit)) {
|
while (rows.next() && (limit <= 0 || i++ < limit)) {
|
||||||
consumer.accept(getRow(rows, classNames));
|
consumer.accept(getRow(rows, classNames, columnTypeNames));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -517,20 +521,28 @@ public class DatabaseImpl implements Database {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> getRow(Rows rows, List<Object> classNames) {
|
private List<Object> getRow(Rows rows, List<Object> classNames, List<Object> columnTypeNames) {
|
||||||
List<Object> row = new ArrayList<>();
|
List<Object> row = new ArrayList<>();
|
||||||
|
// we may have some column type names that need special treatment
|
||||||
|
|
||||||
for (int i = 0; i < classNames.size(); i++) {
|
for (int i = 0; i < classNames.size(); i++) {
|
||||||
String className = classNames.get(i).toString();
|
String columnTypeName = columnTypeNames.get(i).toString();
|
||||||
switch (className) {
|
if ("TIMESTAMPTZ".equals(columnTypeName)) {
|
||||||
case "java.lang.Character", "java.lang.String" -> row.add(rows.getStringOrEmpty(i + 1));
|
row.add(rows.getOffsetDateTimeOrNull(i + 1));
|
||||||
case "java.lang.Integer" -> row.add(rows.getIntegerOrNull(i + 1));
|
} else {
|
||||||
case "java.lang.Long" -> row.add(rows.getLongOrNull(i + 1));
|
String className = classNames.get(i).toString();
|
||||||
case "java.lang.Boolean" -> row.add(rows.getBooleanOrFalse(i + 1));
|
switch (className) {
|
||||||
case "java.sql.Clob", "oracle.jdbc.OracleClob" -> row.add(rows.getClobStringOrEmpty(i + 1));
|
case "java.lang.Character", "java.lang.String" -> row.add(rows.getStringOrEmpty(i + 1));
|
||||||
case "java.sql.Date" -> row.add(rows.getLocalDateOrNull(i + 1));
|
case "java.lang.Integer" -> row.add(rows.getIntegerOrNull(i + 1));
|
||||||
case "java.sql.Timestamp", "oracle.sql.TIMESTAMP" -> row.add(rows.getLocalDateTimeOrNull(i + 1));
|
case "java.lang.Long" -> row.add(rows.getLongOrNull(i + 1));
|
||||||
case "java.math.BigDecimal" -> row.add(rows.getBigDecimalOrNull(i + 1));
|
case "java.lang.Boolean" -> row.add(rows.getBooleanOrFalse(i + 1));
|
||||||
default -> throw new DatabaseException("unexpected column class name: " + className);
|
case "java.sql.Clob", "oracle.jdbc.OracleClob" -> row.add(rows.getClobStringOrEmpty(i + 1));
|
||||||
|
case "java.sql.Date" -> row.add(rows.getLocalDateOrNull(i + 1));
|
||||||
|
case "oracle.sql.TIMESTAMPTZ" -> row.add(rows.getOffsetDateTimeOrNull(i + 1));
|
||||||
|
case "java.sql.Timestamp", "oracle.sql.TIMESTAMP" -> row.add(rows.getLocalDateTimeOrNull(i + 1));
|
||||||
|
case "java.math.BigDecimal" -> row.add(rows.getBigDecimalOrNull(i + 1));
|
||||||
|
default -> throw new DatabaseException("unexpected column class name: " + className);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return row;
|
return row;
|
||||||
|
|
|
@ -384,7 +384,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
||||||
public DatabaseProviderBuilder withDatePerAppOnly() {
|
public DatabaseProviderBuilder withDatePerAppOnly() {
|
||||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||||
@Override
|
@Override
|
||||||
public boolean useLocalDateTimeOnly() {
|
public boolean useClientClock() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}.withParent(this.options));
|
}.withParent(this.options));
|
||||||
|
|
|
@ -38,9 +38,13 @@ public interface Flavor {
|
||||||
|
|
||||||
String typeBlob();
|
String typeBlob();
|
||||||
|
|
||||||
|
String typeInstant();
|
||||||
|
|
||||||
String typeLocalDateTime();
|
String typeLocalDateTime();
|
||||||
|
|
||||||
String columnTypeLocalDateTime();
|
String typeOffsetDateTime();
|
||||||
|
|
||||||
|
String typeZonedDateTime();
|
||||||
|
|
||||||
String typeLocalDate();
|
String typeLocalDate();
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ public interface Options {
|
||||||
* This is useful for testing purposes as you can use OptionsOverride to provide your
|
* This is useful for testing purposes as you can use OptionsOverride to provide your
|
||||||
* own clock that will be used.
|
* own clock that will be used.
|
||||||
*/
|
*/
|
||||||
boolean useLocalDateTimeOnly();
|
boolean useClientClock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of characters to print in debug SQL for a given String type
|
* The maximum number of characters to print in debug SQL for a given String type
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class OptionsDefault implements Options {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useLocalDateTimeOnly() {
|
public boolean useClientClock() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,8 @@ public class OptionsOverride implements Options {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useLocalDateTimeOnly() {
|
public boolean useClientClock() {
|
||||||
return parent.useLocalDateTimeOnly();
|
return parent.useClientClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,9 +4,12 @@ import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.ResultSetMetaData;
|
import java.sql.ResultSetMetaData;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for reading results from a database query.
|
* Interface for reading results from a database query.
|
||||||
|
@ -355,15 +358,29 @@ public interface Row {
|
||||||
|
|
||||||
InputStream getBlobInputStreamOrEmpty(String columnName);
|
InputStream getBlobInputStreamOrEmpty(String columnName);
|
||||||
|
|
||||||
|
Instant getInstantOrNull();
|
||||||
|
|
||||||
|
Instant getInstantOrNull(int columnOneBased);
|
||||||
|
|
||||||
|
Instant getInstantOrNull(String columnName);
|
||||||
|
|
||||||
LocalDateTime getLocalDateTimeOrNull();
|
LocalDateTime getLocalDateTimeOrNull();
|
||||||
|
|
||||||
LocalDateTime getLocalDateTimeOrNull(int columnOneBased);
|
LocalDateTime getLocalDateTimeOrNull(int columnOneBased);
|
||||||
|
|
||||||
LocalDateTime getLocalDateTimeOrNull(int columnOneBased, ZoneId zoneId);
|
|
||||||
|
|
||||||
LocalDateTime getLocalDateTimeOrNull(String columnName);
|
LocalDateTime getLocalDateTimeOrNull(String columnName);
|
||||||
|
|
||||||
LocalDateTime getLocalDateTimeOrNull(String columnName, ZoneId zoneId);
|
OffsetDateTime getOffsetDateTimeOrNull();
|
||||||
|
|
||||||
|
OffsetDateTime getOffsetDateTimeOrNull(int columnOneBase);
|
||||||
|
|
||||||
|
OffsetDateTime getOffsetDateTimeOrNull(String columnName);
|
||||||
|
|
||||||
|
ZonedDateTime getZonedDateTimeOrNull();
|
||||||
|
|
||||||
|
ZonedDateTime getZonedDateTimeOrNull(int columnOneBase);
|
||||||
|
|
||||||
|
ZonedDateTime getZonedDateTimeOrNull(String columnName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve column as LocalDate, .i.e, date with no time.
|
* Retrieve column as LocalDate, .i.e, date with no time.
|
||||||
|
|
|
@ -5,13 +5,15 @@ import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.ResultSetMetaData;
|
import java.sql.ResultSetMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safely wrap a ResultSet and provide access to the data it contains.
|
* Safely wrap a ResultSet and provide access to the data it contains.
|
||||||
|
@ -20,13 +22,10 @@ class RowsAdapter implements Rows {
|
||||||
|
|
||||||
private final ResultSet rs;
|
private final ResultSet rs;
|
||||||
|
|
||||||
private final Options options;
|
|
||||||
|
|
||||||
private int column = 1;
|
private int column = 1;
|
||||||
|
|
||||||
public RowsAdapter(ResultSet rs, Options options) {
|
public RowsAdapter(ResultSet rs) {
|
||||||
this.rs = rs;
|
this.rs = rs;
|
||||||
this.options = options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,6 +38,15 @@ class RowsAdapter implements Rows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultSetMetaData getMetadata() {
|
||||||
|
try {
|
||||||
|
return rs.getMetaData();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException("Unable to retrieve metadata from ResultSet", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getColumnLabels() {
|
public String[] getColumnLabels() {
|
||||||
try {
|
try {
|
||||||
|
@ -52,16 +60,7 @@ class RowsAdapter implements Rows {
|
||||||
throw new DatabaseException("Unable to retrieve metadata from ResultSet", e);
|
throw new DatabaseException("Unable to retrieve metadata from ResultSet", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResultSetMetaData getMetadata() {
|
|
||||||
try {
|
|
||||||
return rs.getMetaData();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new DatabaseException("Unable to retrieve metadata from ResultSet", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean getBooleanOrNull() {
|
public Boolean getBooleanOrNull() {
|
||||||
return getBooleanOrNull(column++);
|
return getBooleanOrNull(column++);
|
||||||
|
@ -200,7 +199,7 @@ class RowsAdapter implements Rows {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getLongOrNull() {
|
public Long getLongOrNull() {
|
||||||
return getLongOrNull(column++);
|
return getLongOrNull(column++);
|
||||||
|
@ -411,7 +410,7 @@ class RowsAdapter implements Rows {
|
||||||
try {
|
try {
|
||||||
column = columnOneBased + 1;
|
column = columnOneBased + 1;
|
||||||
String result = rs.getString(columnOneBased);
|
String result = rs.getString(columnOneBased);
|
||||||
if (result != null && result.length() == 0) {
|
if (result != null && result.isEmpty()) {
|
||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -425,7 +424,7 @@ class RowsAdapter implements Rows {
|
||||||
try {
|
try {
|
||||||
column = rs.findColumn(columnName) + 1;
|
column = rs.findColumn(columnName) + 1;
|
||||||
String result = rs.getString(columnName);
|
String result = rs.getString(columnName);
|
||||||
if (result != null && result.length() == 0) {
|
if (result != null && result.isEmpty()) {
|
||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -467,7 +466,7 @@ class RowsAdapter implements Rows {
|
||||||
try {
|
try {
|
||||||
column = columnOneBased + 1;
|
column = columnOneBased + 1;
|
||||||
String result = rs.getString(columnOneBased);
|
String result = rs.getString(columnOneBased);
|
||||||
if (result != null && result.length() == 0) {
|
if (result != null && result.isEmpty()) {
|
||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -481,7 +480,7 @@ class RowsAdapter implements Rows {
|
||||||
try {
|
try {
|
||||||
column = rs.findColumn(columnName) + 1;
|
column = rs.findColumn(columnName) + 1;
|
||||||
String result = rs.getString(columnName);
|
String result = rs.getString(columnName);
|
||||||
if (result != null && result.length() == 0) {
|
if (result != null && result.isEmpty()) {
|
||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -656,7 +655,32 @@ class RowsAdapter implements Rows {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getInstantOrNull() {
|
||||||
|
return getInstantOrNull(column++);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getInstantOrNull(int columnOneBased) {
|
||||||
|
try {
|
||||||
|
column = columnOneBased + 1;
|
||||||
|
return rs.getObject(columnOneBased, Instant.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getInstantOrNull(String columnName) {
|
||||||
|
try {
|
||||||
|
column = rs.findColumn(columnName) + 1;
|
||||||
|
return rs.getObject(columnName, Instant.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime getLocalDateTimeOrNull() {
|
public LocalDateTime getLocalDateTimeOrNull() {
|
||||||
return getLocalDateTimeOrNull(column++);
|
return getLocalDateTimeOrNull(column++);
|
||||||
|
@ -672,22 +696,6 @@ class RowsAdapter implements Rows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalDateTime getLocalDateTimeOrNull(int columnOneBased, ZoneId zoneId) {
|
|
||||||
try {
|
|
||||||
column = columnOneBased + 1;
|
|
||||||
LocalDateTime localDateTime = rs.getObject(columnOneBased, LocalDateTime.class);
|
|
||||||
Timestamp timestamp = rs.getTimestamp(columnOneBased);
|
|
||||||
if (zoneId != null) {
|
|
||||||
return localDateTime != null ? localDateTime.atZone(zoneId).toLocalDateTime() : null;
|
|
||||||
} else {
|
|
||||||
return localDateTime;
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new DatabaseException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime getLocalDateTimeOrNull(String columnName) {
|
public LocalDateTime getLocalDateTimeOrNull(String columnName) {
|
||||||
try {
|
try {
|
||||||
|
@ -698,17 +706,6 @@ class RowsAdapter implements Rows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalDateTime getLocalDateTimeOrNull(String columnName, ZoneId zoneId) {
|
|
||||||
try {
|
|
||||||
column = rs.findColumn(columnName) + 1;
|
|
||||||
LocalDateTime localDateTime = rs.getObject(columnName, LocalDateTime.class);
|
|
||||||
return localDateTime != null ? localDateTime.atZone(zoneId).toLocalDateTime() : null;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new DatabaseException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDate getLocalDateOrNull() {
|
public LocalDate getLocalDateOrNull() {
|
||||||
return getLocalDateOrNull(column++);
|
return getLocalDateOrNull(column++);
|
||||||
|
@ -736,6 +733,56 @@ class RowsAdapter implements Rows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OffsetDateTime getOffsetDateTimeOrNull() {
|
||||||
|
return getOffsetDateTimeOrNull(column++);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OffsetDateTime getOffsetDateTimeOrNull(int columnOneBased) {
|
||||||
|
try {
|
||||||
|
column = columnOneBased + 1;
|
||||||
|
return rs.getObject(columnOneBased, OffsetDateTime.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OffsetDateTime getOffsetDateTimeOrNull(String columnName) {
|
||||||
|
try {
|
||||||
|
column = rs.findColumn(columnName) + 1;
|
||||||
|
return rs.getObject(columnName, OffsetDateTime.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getZonedDateTimeOrNull() {
|
||||||
|
return getZonedDateTimeOrNull(column++);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getZonedDateTimeOrNull(int columnOneBased) {
|
||||||
|
try {
|
||||||
|
column = columnOneBased + 1;
|
||||||
|
return rs.getObject(columnOneBased, ZonedDateTime.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getZonedDateTimeOrNull(String columnName) {
|
||||||
|
try {
|
||||||
|
column = rs.findColumn(columnName) + 1;
|
||||||
|
return rs.getObject(columnName, ZonedDateTime.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer rowCount() {
|
public Integer rowCount() {
|
||||||
try {
|
try {
|
||||||
|
@ -750,7 +797,7 @@ class RowsAdapter implements Rows {
|
||||||
if (val.scale() > 0) {
|
if (val.scale() > 0) {
|
||||||
val = val.stripTrailingZeros();
|
val = val.stripTrailingZeros();
|
||||||
if (val.scale() < 0) {
|
if (val.scale() < 0) {
|
||||||
val = val.setScale(0);
|
val = val.setScale(0, RoundingMode.FLOOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -141,7 +141,6 @@ public class Schema {
|
||||||
// This is the type dates and times with time and time zone associated.
|
// This is the type dates and times with time and time zone associated.
|
||||||
// Note that Oracle dates are always really Timestamps.
|
// Note that Oracle dates are always really Timestamps.
|
||||||
case Types.TIMESTAMP:
|
case Types.TIMESTAMP:
|
||||||
case Types.TIMESTAMP_WITH_TIMEZONE:
|
|
||||||
// Check if we really have a LocalDate implemented by the DB as a timestamp
|
// Check if we really have a LocalDate implemented by the DB as a timestamp
|
||||||
if (metadata.getScale(i + 1) == 0) {
|
if (metadata.getScale(i + 1) == 0) {
|
||||||
// If the scale is 0, this is a LocalDate (no time/timezone).
|
// If the scale is 0, this is a LocalDate (no time/timezone).
|
||||||
|
@ -151,6 +150,9 @@ public class Schema {
|
||||||
table.addColumn(names[i]).asLocalDateTime();
|
table.addColumn(names[i]).asLocalDateTime();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Types.TIMESTAMP_WITH_TIMEZONE:
|
||||||
|
table.addColumn(names[i]).asOffsetDateTime();
|
||||||
|
break;
|
||||||
case Types.NVARCHAR:
|
case Types.NVARCHAR:
|
||||||
case Types.VARCHAR:
|
case Types.VARCHAR:
|
||||||
case Types.LONGVARCHAR:
|
case Types.LONGVARCHAR:
|
||||||
|
@ -227,9 +229,18 @@ public class Schema {
|
||||||
case StringFixed:
|
case StringFixed:
|
||||||
sql.append(flavor.typeStringFixed(column.scale));
|
sql.append(flavor.typeStringFixed(column.scale));
|
||||||
break;
|
break;
|
||||||
|
case Instant:
|
||||||
|
sql.append(flavor.typeInstant());
|
||||||
|
break;
|
||||||
case LocalDateTime:
|
case LocalDateTime:
|
||||||
sql.append(flavor.typeLocalDateTime());
|
sql.append(flavor.typeLocalDateTime());
|
||||||
break;
|
break;
|
||||||
|
case OffsetDateTime:
|
||||||
|
sql.append(flavor.typeOffsetDateTime());
|
||||||
|
break;
|
||||||
|
case ZonedDateTime:
|
||||||
|
sql.append(flavor.typeZonedDateTime());
|
||||||
|
break;
|
||||||
case LocalDate:
|
case LocalDate:
|
||||||
sql.append(flavor.typeLocalDate());
|
sql.append(flavor.typeLocalDate());
|
||||||
break;
|
break;
|
||||||
|
@ -395,7 +406,21 @@ public class Schema {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ColumnType {
|
public enum ColumnType {
|
||||||
Integer, Long, Float, Double, BigDecimal, StringVar, StringFixed, Clob, Blob, LocalDateTime, LocalDate, Boolean
|
Integer,
|
||||||
|
Long,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
BigDecimal,
|
||||||
|
StringVar,
|
||||||
|
StringFixed,
|
||||||
|
Clob,
|
||||||
|
Blob,
|
||||||
|
Instant,
|
||||||
|
LocalDateTime,
|
||||||
|
OffsetDateTime,
|
||||||
|
ZonedDateTime,
|
||||||
|
LocalDate,
|
||||||
|
Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Sequence {
|
public class Sequence {
|
||||||
|
@ -902,10 +927,22 @@ public class Schema {
|
||||||
return asType(ColumnType.StringFixed);
|
return asType(ColumnType.StringFixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Column asInstant() {
|
||||||
|
return asType(ColumnType.Instant);
|
||||||
|
}
|
||||||
|
|
||||||
public Column asLocalDateTime() {
|
public Column asLocalDateTime() {
|
||||||
return asType(ColumnType.LocalDateTime);
|
return asType(ColumnType.LocalDateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Column asOffsetDateTime() {
|
||||||
|
return asType(ColumnType.OffsetDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Column asZonedateTime() {
|
||||||
|
return asType(ColumnType.ZonedDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
public Column asLocalDate() {
|
public Column asLocalDate() {
|
||||||
return asType(ColumnType.LocalDate);
|
return asType(ColumnType.LocalDate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,12 @@ package org.xbib.jdbc.query;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for configuring (setting parameters) and executing a chunk of SQL.
|
* Interface for configuring (setting parameters) and executing a chunk of SQL.
|
||||||
|
@ -40,12 +43,22 @@ public interface SqlInsert {
|
||||||
|
|
||||||
SqlInsert argString( String argName, String arg);
|
SqlInsert argString( String argName, String arg);
|
||||||
|
|
||||||
|
SqlInsert argInstant(Instant arg);
|
||||||
|
|
||||||
|
SqlInsert argInstant(String argName, Instant arg);
|
||||||
|
|
||||||
SqlInsert argLocalDateTime(LocalDateTime arg);
|
SqlInsert argLocalDateTime(LocalDateTime arg);
|
||||||
|
|
||||||
SqlInsert argLocalDateTime(LocalDateTime arg, ZoneId zoneId);
|
|
||||||
|
|
||||||
SqlInsert argLocalDateTime(String argName, LocalDateTime arg);
|
SqlInsert argLocalDateTime(String argName, LocalDateTime arg);
|
||||||
|
|
||||||
|
SqlInsert argOffsetDateTime(OffsetDateTime arg);
|
||||||
|
|
||||||
|
SqlInsert argOffsetDateTime(String argName, OffsetDateTime arg);
|
||||||
|
|
||||||
|
SqlInsert argZonedDateTime(ZonedDateTime arg);
|
||||||
|
|
||||||
|
SqlInsert argZonedDateTime(String argName, ZonedDateTime arg);
|
||||||
|
|
||||||
SqlInsert argLocalDate(LocalDate arg);
|
SqlInsert argLocalDate(LocalDate arg);
|
||||||
|
|
||||||
SqlInsert argLocalDate( String argName, LocalDate arg);
|
SqlInsert argLocalDate( String argName, LocalDate arg);
|
||||||
|
|
|
@ -13,9 +13,11 @@ import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -142,13 +144,18 @@ public class SqlInsertImpl implements SqlInsert {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlInsert argLocalDateTime(LocalDateTime arg) {
|
public SqlInsert argInstant(Instant arg) {
|
||||||
return positionalArg(adaptor.nullLocalDateTime(arg));
|
return positionalArg(adaptor.nullInstant(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlInsert argLocalDateTime(LocalDateTime arg, ZoneId zoneId) {
|
public SqlInsert argInstant(String argName, Instant arg) {
|
||||||
return positionalArg(adaptor.nullLocalDateTime(arg, zoneId));
|
return namedArg(argName, adaptor.nullInstant(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlInsert argLocalDateTime(LocalDateTime arg) {
|
||||||
|
return positionalArg(adaptor.nullLocalDateTime(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -165,10 +172,30 @@ public class SqlInsertImpl implements SqlInsert {
|
||||||
public SqlInsert argLocalDate(LocalDate arg) {
|
public SqlInsert argLocalDate(LocalDate arg) {
|
||||||
return positionalArg(adaptor.nullLocalDate(arg));
|
return positionalArg(adaptor.nullLocalDate(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlInsert argOffsetDateTime(OffsetDateTime arg) {
|
||||||
|
return positionalArg(adaptor.nullOffsetDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlInsert argOffsetDateTime(String argName, OffsetDateTime arg) {
|
||||||
|
return namedArg(argName, adaptor.nullOffsetDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlInsert argZonedDateTime(ZonedDateTime arg) {
|
||||||
|
return positionalArg(adaptor.nullZonedDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlInsert argZonedDateTime(String argName, ZonedDateTime arg) {
|
||||||
|
return namedArg(argName, adaptor.nullZonedDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlInsert argLocalDateTimeNowPerDb() {
|
public SqlInsert argLocalDateTimeNowPerDb() {
|
||||||
if (options.useLocalDateTimeOnly()) {
|
if (options.useClientClock()) {
|
||||||
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||||
}
|
}
|
||||||
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
@ -176,7 +203,7 @@ public class SqlInsertImpl implements SqlInsert {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlInsert argLocalDateTimeNowPerDb(String argName) {
|
public SqlInsert argLocalDateTimeNowPerDb(String argName) {
|
||||||
if (options.useLocalDateTimeOnly()) {
|
if (options.useClientClock()) {
|
||||||
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||||
}
|
}
|
||||||
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
@ -602,7 +629,7 @@ public class SqlInsertImpl implements SqlInsert {
|
||||||
}
|
}
|
||||||
rs = ps.getGeneratedKeys();
|
rs = ps.getGeneratedKeys();
|
||||||
final ResultSet finalRs = rs;
|
final ResultSet finalRs = rs;
|
||||||
T result = handler.process(new RowsAdapter(finalRs, options));
|
T result = handler.process(new RowsAdapter(finalRs));
|
||||||
metric.checkpoint("read");
|
metric.checkpoint("read");
|
||||||
isSuccess = true;
|
isSuccess = true;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package org.xbib.jdbc.query;
|
package org.xbib.jdbc.query;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,13 +41,29 @@ public interface SqlSelect {
|
||||||
|
|
||||||
SqlSelect argString( String argName, String arg);
|
SqlSelect argString( String argName, String arg);
|
||||||
|
|
||||||
|
SqlSelect argInstant(Instant arg);
|
||||||
|
|
||||||
|
SqlSelect argInstant(String argName, Instant arg);
|
||||||
|
|
||||||
SqlSelect argLocalDateTime(LocalDateTime arg);
|
SqlSelect argLocalDateTime(LocalDateTime arg);
|
||||||
|
|
||||||
SqlSelect argLocalDateTime(String argName, LocalDateTime arg);
|
SqlSelect argLocalDateTime(String argName, LocalDateTime arg);
|
||||||
|
|
||||||
|
SqlSelect argOffsetDateTime(OffsetDateTime arg);
|
||||||
|
|
||||||
|
SqlSelect argOffsetDateTime(String argName, OffsetDateTime arg);
|
||||||
|
|
||||||
|
SqlSelect argZonedDateTime(ZonedDateTime arg);
|
||||||
|
|
||||||
|
SqlSelect argZonedDateTime(String argName, ZonedDateTime arg);
|
||||||
|
|
||||||
SqlSelect argLocalDate(LocalDate arg);
|
SqlSelect argLocalDate(LocalDate arg);
|
||||||
|
|
||||||
SqlSelect argLocalDate( String argName, LocalDate arg);
|
SqlSelect argLocalDate(String argName, LocalDate arg);
|
||||||
|
|
||||||
|
SqlSelect argInstantNowPerDb();
|
||||||
|
|
||||||
|
SqlSelect argInstantNowPerDb(String argName);
|
||||||
|
|
||||||
SqlSelect argLocalDateTimeNowPerDb();
|
SqlSelect argLocalDateTimeNowPerDb();
|
||||||
|
|
||||||
|
@ -113,13 +131,17 @@ public interface SqlSelect {
|
||||||
*/
|
*/
|
||||||
List<String> queryStrings();
|
List<String> queryStrings();
|
||||||
|
|
||||||
LocalDateTime queryLocalDateTimeOrNull();
|
Instant queryInstantOrNull();
|
||||||
|
|
||||||
LocalDateTime queryLocalDateTimeOrNull(ZoneId zoneId);
|
List<Instant> queryInstants();
|
||||||
|
|
||||||
|
LocalDateTime queryLocalDateTimeOrNull();
|
||||||
|
|
||||||
List<LocalDateTime> queryLocalDateTimes();
|
List<LocalDateTime> queryLocalDateTimes();
|
||||||
|
|
||||||
List<LocalDateTime> queryLocalDateTimes(ZoneId zoneId);
|
ZonedDateTime queryZonedDateTimeOrNull();
|
||||||
|
|
||||||
|
List<ZonedDateTime> queryZonedDateTimes();
|
||||||
|
|
||||||
LocalDate queryLocalDateOrNull();
|
LocalDate queryLocalDateOrNull();
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,11 @@ import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -24,7 +26,7 @@ import java.util.logging.Logger;
|
||||||
*/
|
*/
|
||||||
public class SqlSelectImpl implements SqlSelect {
|
public class SqlSelectImpl implements SqlSelect {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Database.class.getName());
|
private static final Logger logger = Logger.getLogger(SqlSelectImpl.class.getName());
|
||||||
|
|
||||||
private final Connection connection;
|
private final Connection connection;
|
||||||
|
|
||||||
|
@ -134,7 +136,17 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
public SqlSelect argString(String argName, String arg) {
|
public SqlSelect argString(String argName, String arg) {
|
||||||
return namedArg(argName, adaptor.nullString(arg));
|
return namedArg(argName, adaptor.nullString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argInstant(Instant arg) {
|
||||||
|
return positionalArg(adaptor.nullInstant(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argInstant(String argName, Instant arg) {
|
||||||
|
return namedArg(argName, adaptor.nullInstant(arg));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlSelect argLocalDateTime(LocalDateTime arg) {
|
public SqlSelect argLocalDateTime(LocalDateTime arg) {
|
||||||
return positionalArg(adaptor.nullLocalDateTime(arg));
|
return positionalArg(adaptor.nullLocalDateTime(arg));
|
||||||
|
@ -144,7 +156,27 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
public SqlSelect argLocalDateTime(String argName, LocalDateTime arg) {
|
public SqlSelect argLocalDateTime(String argName, LocalDateTime arg) {
|
||||||
return namedArg(argName, adaptor.nullLocalDateTime(arg));
|
return namedArg(argName, adaptor.nullLocalDateTime(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argOffsetDateTime(OffsetDateTime arg) {
|
||||||
|
return positionalArg(adaptor.nullOffsetDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argOffsetDateTime(String argName, OffsetDateTime arg) {
|
||||||
|
return namedArg(argName, adaptor.nullOffsetDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argZonedDateTime(ZonedDateTime arg) {
|
||||||
|
return positionalArg(adaptor.nullZonedDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argZonedDateTime(String argName, ZonedDateTime arg) {
|
||||||
|
return namedArg(argName, adaptor.nullZonedDateTime(arg));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlSelect argLocalDate(LocalDate arg) {
|
public SqlSelect argLocalDate(LocalDate arg) {
|
||||||
return positionalArg(adaptor.nullLocalDate(arg));
|
return positionalArg(adaptor.nullLocalDate(arg));
|
||||||
|
@ -155,9 +187,25 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
return namedArg(argName, adaptor.nullLocalDate(arg));
|
return namedArg(argName, adaptor.nullLocalDate(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argInstantNowPerDb() {
|
||||||
|
if (options.useClientClock()) {
|
||||||
|
return positionalArg(adaptor.nullInstant(Instant.now()));
|
||||||
|
}
|
||||||
|
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelect argInstantNowPerDb(String argName) {
|
||||||
|
if (options.useClientClock()) {
|
||||||
|
return namedArg(argName, adaptor.nullInstant(Instant.now()));
|
||||||
|
}
|
||||||
|
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlSelect argLocalDateTimeNowPerDb() {
|
public SqlSelect argLocalDateTimeNowPerDb() {
|
||||||
if (options.useLocalDateTimeOnly()) {
|
if (options.useClientClock()) {
|
||||||
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||||
}
|
}
|
||||||
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
@ -165,7 +213,7 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlSelect argLocalDateTimeNowPerDb(String argName) {
|
public SqlSelect argLocalDateTimeNowPerDb(String argName) {
|
||||||
if (options.useLocalDateTimeOnly()) {
|
if (options.useClientClock()) {
|
||||||
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||||
}
|
}
|
||||||
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
@ -429,17 +477,37 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime queryLocalDateTimeOrNull() {
|
public Instant queryInstantOrNull() {
|
||||||
return queryLocalDateTimeOrNull(null);
|
return queryWithTimeout(rs -> {
|
||||||
|
if (rs.next()) {
|
||||||
|
return rs.getInstantOrNull(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime queryLocalDateTimeOrNull(ZoneId zoneId) {
|
public List<Instant> queryInstants() {
|
||||||
|
return queryWithTimeout(rs -> {
|
||||||
|
List<Instant> result = new ArrayList<>();
|
||||||
|
while (rs.next()) {
|
||||||
|
Instant value = rs.getInstantOrNull(1);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime queryLocalDateTimeOrNull() {
|
||||||
return queryWithTimeout(rs -> {
|
return queryWithTimeout(rs -> {
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
return rs.getLocalDateTimeOrNull(1, zoneId);
|
return rs.getLocalDateTimeOrNull(1);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
@ -447,15 +515,34 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<LocalDateTime> queryLocalDateTimes() {
|
public List<LocalDateTime> queryLocalDateTimes() {
|
||||||
return queryLocalDateTimes(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<LocalDateTime> queryLocalDateTimes(ZoneId zoneId) {
|
|
||||||
return queryWithTimeout(rs -> {
|
return queryWithTimeout(rs -> {
|
||||||
List<LocalDateTime> result = new ArrayList<>();
|
List<LocalDateTime> result = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
LocalDateTime value = rs.getLocalDateTimeOrNull(1, zoneId);
|
LocalDateTime value = rs.getLocalDateTimeOrNull(1);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime queryZonedDateTimeOrNull() {
|
||||||
|
return queryWithTimeout(rs -> {
|
||||||
|
if (rs.next()) {
|
||||||
|
return rs.getZonedDateTimeOrNull(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ZonedDateTime> queryZonedDateTimes() {
|
||||||
|
return queryWithTimeout(rs -> {
|
||||||
|
List<ZonedDateTime> result = new ArrayList<>();
|
||||||
|
while (rs.next()) {
|
||||||
|
ZonedDateTime value = rs.getZonedDateTimeOrNull(1);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
result.add(value);
|
result.add(value);
|
||||||
}
|
}
|
||||||
|
@ -605,9 +692,9 @@ public class SqlSelectImpl implements SqlSelect {
|
||||||
adaptor.addParameters(ps, parameters);
|
adaptor.addParameters(ps, parameters);
|
||||||
metric.checkpoint("prep");
|
metric.checkpoint("prep");
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
|
final ResultSet resultSet = rs;
|
||||||
metric.checkpoint("exec");
|
metric.checkpoint("exec");
|
||||||
final ResultSet finalRs = rs;
|
T result = handler.process(new RowsAdapter(resultSet));
|
||||||
T result = handler.process(new RowsAdapter(finalRs, options));
|
|
||||||
metric.checkpoint("read");
|
metric.checkpoint("read");
|
||||||
isSuccess = true;
|
isSuccess = true;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -142,7 +142,7 @@ public class SqlUpdateImpl implements SqlUpdate {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlUpdate argLocalDateTimeNowPerDb() {
|
public SqlUpdate argLocalDateTimeNowPerDb() {
|
||||||
if (options.useLocalDateTimeOnly()) {
|
if (options.useClientClock()) {
|
||||||
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||||
}
|
}
|
||||||
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
@ -150,7 +150,7 @@ public class SqlUpdateImpl implements SqlUpdate {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlUpdate argLocalDateTimeNowPerDb(String argName) {
|
public SqlUpdate argLocalDateTimeNowPerDb(String argName) {
|
||||||
if (options.useLocalDateTimeOnly()) {
|
if (options.useClientClock()) {
|
||||||
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||||
}
|
}
|
||||||
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||||
|
|
|
@ -11,9 +11,13 @@ import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -25,8 +29,6 @@ import java.util.stream.Collectors;
|
||||||
*/
|
*/
|
||||||
public class StatementAdapter {
|
public class StatementAdapter {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(StatementAdapter.class.getName());
|
|
||||||
|
|
||||||
private final Options options;
|
private final Options options;
|
||||||
|
|
||||||
public StatementAdapter(Options options) {
|
public StatementAdapter(Options options) {
|
||||||
|
@ -53,8 +55,7 @@ public class StatementAdapter {
|
||||||
+ " or use SqlNull in place of null values to this query.", e);
|
+ " or use SqlNull in place of null values to this query.", e);
|
||||||
}
|
}
|
||||||
ps.setNull(i + 1, parameterType);
|
ps.setNull(i + 1, parameterType);
|
||||||
} else if (parameter instanceof SqlNull) {
|
} else if (parameter instanceof SqlNull sqlNull) {
|
||||||
SqlNull sqlNull = (SqlNull) parameter;
|
|
||||||
if (options.useBytesForBlob() && sqlNull.getType() == Types.BLOB) {
|
if (options.useBytesForBlob() && sqlNull.getType() == Types.BLOB) {
|
||||||
// The setNull() seems more correct, but PostgreSQL chokes on it
|
// The setNull() seems more correct, but PostgreSQL chokes on it
|
||||||
ps.setBytes(i + 1, null);
|
ps.setBytes(i + 1, null);
|
||||||
|
@ -63,13 +64,9 @@ public class StatementAdapter {
|
||||||
}
|
}
|
||||||
} else if (parameter instanceof java.sql.Date) {
|
} else if (parameter instanceof java.sql.Date) {
|
||||||
ps.setDate(i + 1, (java.sql.Date) parameter);
|
ps.setDate(i + 1, (java.sql.Date) parameter);
|
||||||
} else if (parameter instanceof Date) {
|
} else if (parameter instanceof Date date) {
|
||||||
Date date = (Date) parameter;
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
||||||
ps.setTimestamp(i + 1, Timestamp.valueOf(localDateTime));
|
ps.setTimestamp(i + 1, Timestamp.valueOf(localDateTime));
|
||||||
// this will correct the millis and nanos according to the JDBC spec
|
|
||||||
// if a correct Timestamp is passed in, this will detect that and leave it alone
|
|
||||||
//ps.setTimestamp(i + 1, toSqlTimestamp((Date) parameter), options.calendarForTimestamps());
|
|
||||||
} else if (parameter instanceof Reader) {
|
} else if (parameter instanceof Reader) {
|
||||||
if (options.useStringForClob()) {
|
if (options.useStringForClob()) {
|
||||||
try (BufferedReader reader = new BufferedReader((Reader) parameter)) {
|
try (BufferedReader reader = new BufferedReader((Reader) parameter)) {
|
||||||
|
@ -100,12 +97,20 @@ public class StatementAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object nullInstant(Instant arg) {
|
||||||
|
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg.atOffset(ZoneOffset.UTC).toLocalDateTime());
|
||||||
|
}
|
||||||
|
|
||||||
public Object nullLocalDateTime(LocalDateTime arg) {
|
public Object nullLocalDateTime(LocalDateTime arg) {
|
||||||
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg);
|
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object nullLocalDateTime(LocalDateTime arg, ZoneId zoneId) {
|
public Object nullZonedDateTime(ZonedDateTime arg) {
|
||||||
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg.atZone(zoneId).toLocalDateTime());
|
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg.toLocalDateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object nullOffsetDateTime(OffsetDateTime arg) {
|
||||||
|
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg.toLocalDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object nullLocalDate(LocalDate arg) {
|
public Object nullLocalDate(LocalDate arg) {
|
||||||
|
|
|
@ -95,14 +95,24 @@ public class Derby implements Flavor {
|
||||||
return "blob";
|
return "blob";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeInstant() {
|
||||||
|
return "timestamp";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDateTime() {
|
public String typeLocalDateTime() {
|
||||||
return "timestamp";
|
return "timestamp";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String columnTypeLocalDateTime() {
|
public String typeOffsetDateTime() {
|
||||||
return "timestamp";
|
return "timestamptz";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeZonedDateTime() {
|
||||||
|
return "timestamptz";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -95,14 +95,24 @@ public class H2 implements Flavor {
|
||||||
return "blob(2G)";
|
return "blob(2G)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeInstant() {
|
||||||
|
return "timestamp";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDateTime() {
|
public String typeLocalDateTime() {
|
||||||
return "timestamp(3)";
|
return "timestamp(3)";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String columnTypeLocalDateTime() {
|
public String typeOffsetDateTime() {
|
||||||
return "timestamp";
|
return "timestamptz";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeZonedDateTime() {
|
||||||
|
return "timestamptz";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -95,14 +95,24 @@ public class Hsql implements Flavor {
|
||||||
return "blob(2G)";
|
return "blob(2G)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeInstant() {
|
||||||
|
return "timestamp";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeLocalDateTime() {
|
public String typeLocalDateTime() {
|
||||||
|
return "timestamp";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String typeOffsetDateTime() {
|
||||||
return "timestamp with time zone";
|
return "timestamp with time zone";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String columnTypeLocalDateTime() {
|
public String typeZonedDateTime() {
|
||||||
return "TIMESTAMP WITH TIME ZONE";
|
return "timestamp with time zone";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.xbib.jdbc.query.test;
|
package org.xbib.jdbc.query.test;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.xbib.jdbc.query.Config;
|
import org.xbib.jdbc.query.Config;
|
||||||
|
@ -24,15 +23,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
*/
|
*/
|
||||||
public class HsqldbTest extends CommonTest {
|
public class HsqldbTest extends CommonTest {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(HsqldbTest.class.getName());
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) {
|
||||||
String propertiesFile = "hsqldb.properties";
|
String propertiesFile = "hsqldb.properties";
|
||||||
Config config = ConfigSupplier.of()
|
Config config = ConfigSupplier.of()
|
||||||
.properties(getClass().getResourceAsStream(propertiesFile))
|
.properties(getClass().getResourceAsStream(propertiesFile))
|
||||||
.get();
|
.get();
|
||||||
return DatabaseProvider.builder(config)
|
return DatabaseProvider.builder(getClass().getClassLoader(),
|
||||||
|
config.getString("database.url"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
config.getString("database.user"),
|
||||||
|
config.getString("database.password"))
|
||||||
.withSqlParameterLogging()
|
.withSqlParameterLogging()
|
||||||
.withSqlInExceptionMessages()
|
.withSqlInExceptionMessages()
|
||||||
.withOptions(options)
|
.withOptions(options)
|
||||||
|
@ -79,7 +81,7 @@ public class HsqldbTest extends CommonTest {
|
||||||
.argClobString("hello again")
|
.argClobString("hello again")
|
||||||
.argBlobBytes(new byte[]{'1', '2'})
|
.argBlobBytes(new byte[]{'1', '2'})
|
||||||
.argBoolean(true)
|
.argBoolean(true)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow)
|
.argLocalDate(localDateNow)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ public class HsqldbTest extends CommonTest {
|
||||||
.argClobString("bye again")
|
.argClobString("bye again")
|
||||||
.argBlobBytes(new byte[]{'3', '4'})
|
.argBlobBytes(new byte[]{'3', '4'})
|
||||||
.argBoolean(false)
|
.argBoolean(false)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow)
|
.argLocalDate(localDateNow)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
|
|
||||||
|
@ -150,7 +152,7 @@ public class HsqldbTest extends CommonTest {
|
||||||
.argClobString("str_lob", "bye again")
|
.argClobString("str_lob", "bye again")
|
||||||
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
||||||
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
||||||
.argLocalDateTime("date_millis", now)
|
.argLocalDateTime("date_millis", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow),
|
.argLocalDate("local_date", localDateNow),
|
||||||
new SqlArgs()
|
new SqlArgs()
|
||||||
.argInteger("nbr_integer", Integer.MAX_VALUE)
|
.argInteger("nbr_integer", Integer.MAX_VALUE)
|
||||||
|
@ -163,7 +165,7 @@ public class HsqldbTest extends CommonTest {
|
||||||
.argClobString("str_lob", "hello again")
|
.argClobString("str_lob", "hello again")
|
||||||
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
||||||
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
||||||
.argLocalDateTime("date_millis", now)
|
.argLocalDateTime("date_millis", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow)),
|
.argLocalDate("local_date", localDateNow)),
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
||||||
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
||||||
|
|
|
@ -10,9 +10,12 @@ import java.io.StringReader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.ResultSetMetaData;
|
import java.sql.ResultSetMetaData;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -578,6 +581,23 @@ public class RowStub {
|
||||||
return new ByteArrayInputStream(getBlobBytesOrZeroLen(columnName));
|
return new ByteArrayInputStream(getBlobBytesOrZeroLen(columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getInstantOrNull() {
|
||||||
|
return toInstant(rows.get(row)[++col]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getInstantOrNull(int columnOneBased) {
|
||||||
|
col = columnOneBased;
|
||||||
|
return toInstant(rows.get(row)[columnOneBased - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getInstantOrNull(String columnName) {
|
||||||
|
col = columnIndexByName(columnName) + 1;
|
||||||
|
return toInstant(rows.get(row)[columnIndexByName(columnName)]);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime getLocalDateTimeOrNull() {
|
public LocalDateTime getLocalDateTimeOrNull() {
|
||||||
return toLocalDateTime(rows.get(row)[++col]);
|
return toLocalDateTime(rows.get(row)[++col]);
|
||||||
|
@ -589,12 +609,6 @@ public class RowStub {
|
||||||
return toLocalDateTime(rows.get(row)[columnOneBased - 1]);
|
return toLocalDateTime(rows.get(row)[columnOneBased - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalDateTime getLocalDateTimeOrNull(int columnOneBased, ZoneId zoneId) {
|
|
||||||
col = columnOneBased;
|
|
||||||
return toLocalDateTime(rows.get(row)[columnOneBased - 1], zoneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime getLocalDateTimeOrNull(String columnName) {
|
public LocalDateTime getLocalDateTimeOrNull(String columnName) {
|
||||||
col = columnIndexByName(columnName) + 1;
|
col = columnIndexByName(columnName) + 1;
|
||||||
|
@ -602,36 +616,50 @@ public class RowStub {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime getLocalDateTimeOrNull(String columnName, ZoneId zoneId) {
|
public OffsetDateTime getOffsetDateTimeOrNull() {
|
||||||
return null;
|
return toOffsetDateTime(rows.get(row)[++col]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns a java.time.LocalDate. It will have no timezone or other time data.
|
public OffsetDateTime getOffsetDateTimeOrNull(int columnOneBased) {
|
||||||
* If you require time, use the Date APIs instead.
|
col = columnOneBased;
|
||||||
*/
|
return toOffsetDateTime(rows.get(row)[columnOneBased - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OffsetDateTime getOffsetDateTimeOrNull(String columnName) {
|
||||||
|
col = columnIndexByName(columnName) + 1;
|
||||||
|
return toOffsetDateTime(rows.get(row)[columnIndexByName(columnName)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getZonedDateTimeOrNull() {
|
||||||
|
return toZonedDateTime(rows.get(row)[++col]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getZonedDateTimeOrNull(int columnOneBased) {
|
||||||
|
col = columnOneBased;
|
||||||
|
return toZonedDateTime(rows.get(row)[columnOneBased - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getZonedDateTimeOrNull(String columnName) {
|
||||||
|
col = columnIndexByName(columnName) + 1;
|
||||||
|
return toZonedDateTime(rows.get(row)[columnIndexByName(columnName)]);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDate getLocalDateOrNull() {
|
public LocalDate getLocalDateOrNull() {
|
||||||
return toLocalDate(rows.get(row)[++col]);
|
return toLocalDate(rows.get(row)[++col]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a java.time.LocalDate. It will have no timezone or other time data.
|
|
||||||
* If you require time, use the Date APIs instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDate getLocalDateOrNull(int columnOneBased) {
|
public LocalDate getLocalDateOrNull(int columnOneBased) {
|
||||||
col = columnOneBased;
|
col = columnOneBased;
|
||||||
return toLocalDate(rows.get(row)[columnOneBased - 1]);
|
return toLocalDate(rows.get(row)[columnOneBased - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a java.time.LocalDate. It will have no timezone or other time data.
|
|
||||||
* If you require time, use the Date APIs instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDate getLocalDateOrNull(String columnName) {
|
public LocalDate getLocalDateOrNull(String columnName) {
|
||||||
col = columnIndexByName(columnName) + 1;
|
col = columnIndexByName(columnName) + 1;
|
||||||
|
@ -707,32 +735,60 @@ public class RowStub {
|
||||||
return (BigDecimal) o;
|
return (BigDecimal) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDateTime toLocalDateTime(Object o) {
|
private Instant toInstant(Object o) {
|
||||||
return toLocalDateTime(o, ZoneId.systemDefault());
|
if (o instanceof String s) {
|
||||||
|
if (s.length() == "yyyy-MM-dd".length()) {
|
||||||
|
return Instant.parse(s);
|
||||||
|
}
|
||||||
|
if (s.length() == "yyyy-MM-ddThh:mm:ss".length()) {
|
||||||
|
return Instant.parse(s);
|
||||||
|
}
|
||||||
|
throw new DatabaseException("Didn't understand date string: " + s);
|
||||||
|
}
|
||||||
|
return (Instant) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDateTime toLocalDateTime(Object o, ZoneId zoneId) {
|
private LocalDateTime toLocalDateTime(Object o) {
|
||||||
if (o instanceof String) {
|
if (o instanceof String s) {
|
||||||
String s = (String) o;
|
|
||||||
if (s.length() == "yyyy-MM-dd".length()) {
|
if (s.length() == "yyyy-MM-dd".length()) {
|
||||||
return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
|
return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
|
||||||
.atZone(zoneId).toLocalDateTime();
|
.atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||||
}
|
}
|
||||||
if (s.length() == "yyyy-MM-ddThh:mm:ss".length()) {
|
if (s.length() == "yyyy-MM-ddThh:mm:ss".length()) {
|
||||||
return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-ddThh:mm:ss"))
|
return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-ddThh:mm:ss"))
|
||||||
.atZone(zoneId).toLocalDateTime();
|
.atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||||
}
|
}
|
||||||
throw new DatabaseException("Didn't understand date string: " + s);
|
throw new DatabaseException("Didn't understand date string: " + s);
|
||||||
}
|
}
|
||||||
return (LocalDateTime) o;
|
return (LocalDateTime) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private OffsetDateTime toOffsetDateTime(Object o) {
|
||||||
* Returns a LocalDate (no time).
|
if (o instanceof String s) {
|
||||||
* If the object is a String, it should be in ISO 8601 format.
|
if (s.length() == "yyyy-MM-dd".length()) {
|
||||||
*
|
return OffsetDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
* @return a LocalDate representation of the object
|
}
|
||||||
*/
|
if (s.length() == "yyyy-MM-ddThh:mm:ss".length()) {
|
||||||
|
return OffsetDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-ddThh:mm:ss"));
|
||||||
|
}
|
||||||
|
throw new DatabaseException("Didn't understand date string: " + s);
|
||||||
|
}
|
||||||
|
return (OffsetDateTime) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ZonedDateTime toZonedDateTime(Object o) {
|
||||||
|
if (o instanceof String s) {
|
||||||
|
if (s.length() == "yyyy-MM-dd".length()) {
|
||||||
|
return ZonedDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
}
|
||||||
|
if (s.length() == "yyyy-MM-ddThh:mm:ss".length()) {
|
||||||
|
return ZonedDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-ddThh:mm:ss"));
|
||||||
|
}
|
||||||
|
throw new DatabaseException("Didn't understand date string: " + s);
|
||||||
|
}
|
||||||
|
return (ZonedDateTime) o;
|
||||||
|
}
|
||||||
|
|
||||||
private LocalDate toLocalDate(Object o) {
|
private LocalDate toLocalDate(Object o) {
|
||||||
if (o instanceof String) {
|
if (o instanceof String) {
|
||||||
return LocalDate.parse((String) o);
|
return LocalDate.parse((String) o);
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api project(':jdbc-query')
|
|
||||||
testImplementation project(':jdbc-test')
|
|
||||||
testImplementation testLibs.testcontainers
|
|
||||||
testImplementation testLibs.testcontainers.junit.jupiter
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
systemProperty 'user.timezone', 'GMT'
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import org.xbib.jdbc.query.Flavor;
|
|
||||||
import org.xbib.jdbc.sqlserver.SqlServer;
|
|
||||||
|
|
||||||
module org.xbib.jdbc.sqlserver {
|
|
||||||
requires org.xbib.jdbc.query;
|
|
||||||
requires java.sql;
|
|
||||||
uses Flavor;
|
|
||||||
exports org.xbib.jdbc.sqlserver;
|
|
||||||
provides Flavor with SqlServer;
|
|
||||||
}
|
|
|
@ -1,214 +0,0 @@
|
||||||
package org.xbib.jdbc.sqlserver;
|
|
||||||
|
|
||||||
import org.xbib.jdbc.query.Flavor;
|
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
public class SqlServer implements Flavor {
|
|
||||||
|
|
||||||
public SqlServer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "sqlServer";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String url) {
|
|
||||||
return url.startsWith("jdbc:sqlserver:");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String driverClass() {
|
|
||||||
return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String normalizeTableName(String tableName) {
|
|
||||||
if (tableName == null) {
|
|
||||||
return tableName;
|
|
||||||
}
|
|
||||||
if (tableName.length() > 2) {
|
|
||||||
if (tableName.startsWith("\"") && tableName.endsWith("\"")) {
|
|
||||||
return tableName.substring(1, tableName.length() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeFloat() {
|
|
||||||
return "float(24)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
|
||||||
preparedStatement.setFloat(i, floatValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeDouble() {
|
|
||||||
return "float(53)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
|
||||||
preparedStatement.setDouble(i, doubleValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeBigDecimal(int size, int precision) {
|
|
||||||
return "numeric(" + size + "," + precision + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeInteger() {
|
|
||||||
return "numeric(10)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeBoolean() {
|
|
||||||
return "char(1)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeLong() {
|
|
||||||
return "numeric(19)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeLocalDateTime() {
|
|
||||||
return "datetime2(3)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String columnTypeLocalDateTime() {
|
|
||||||
return "datetime2";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeLocalDate() {
|
|
||||||
return "date";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean useStringForClob() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean useBytesForBlob() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceNextVal(String sequenceName) {
|
|
||||||
return "next value for " + sequenceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceSelectNextVal(String sequenceName) {
|
|
||||||
return "select next value for " + sequenceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceDrop(String dbtestSeq) {
|
|
||||||
return "drop sequence " + dbtestSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String tableDrop(String table) {
|
|
||||||
return "drop table " + table;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeStringVar(int length) {
|
|
||||||
return "varchar(" + length + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeStringFixed(int length) {
|
|
||||||
return "char(" + length + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeClob() {
|
|
||||||
return "varchar(max)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String typeBlob() {
|
|
||||||
return "varbinary(max)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceOrderClause(boolean order) {
|
|
||||||
// Not supported
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceCycleClause(boolean cycle) {
|
|
||||||
return cycle ? " cycle" : " no cycle";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportsInsertReturning() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dbTimeMillis() {
|
|
||||||
return "current_timestamp";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceCacheClause(int nbrValuesToCache) {
|
|
||||||
if (nbrValuesToCache < 2) {
|
|
||||||
return " no cache";
|
|
||||||
}
|
|
||||||
return " cache " + nbrValuesToCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String fromAny() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sequenceOptions() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAutoCommitOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String queueLength(String table) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String writeNextIntoQueue(String table) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String readNextFromQueue(String table) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String succeedInQueue(String table) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String failInQueue(String table) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
org.xbib.jdbc.sqlserver.SqlServer
|
|
|
@ -1,87 +0,0 @@
|
||||||
package org.xbib.jdbc.sqlserver.test;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.xbib.jdbc.query.Config;
|
|
||||||
import org.xbib.jdbc.query.ConfigSupplier;
|
|
||||||
import org.xbib.jdbc.query.DatabaseProvider;
|
|
||||||
import org.xbib.jdbc.query.OptionsOverride;
|
|
||||||
import org.xbib.jdbc.query.Schema;
|
|
||||||
import org.xbib.jdbc.test.CommonTest;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exercise Database functionality with a real SQL server database.
|
|
||||||
*/
|
|
||||||
@Disabled
|
|
||||||
public class SqlServerTest extends CommonTest {
|
|
||||||
@Override
|
|
||||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
|
||||||
String propertiesFile = System.getProperty("local.properties", "local.properties");
|
|
||||||
Config config = ConfigSupplier.of()
|
|
||||||
.systemProperties()
|
|
||||||
.properties(propertiesFile)
|
|
||||||
.excludePrefix("database.")
|
|
||||||
.removePrefix("sqlserver.")
|
|
||||||
.get();
|
|
||||||
return DatabaseProvider.builder(config)
|
|
||||||
.withSqlParameterLogging()
|
|
||||||
.withSqlInExceptionMessages()
|
|
||||||
.withOptions(options).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Disabled("SQL Server prohibits NaN and Infinity")
|
|
||||||
@Test
|
|
||||||
public void argFloatNaN() {
|
|
||||||
super.argFloatNaN();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Disabled("SQL Server prohibits NaN and Infinity")
|
|
||||||
@Test
|
|
||||||
public void argFloatInfinity() {
|
|
||||||
super.argFloatInfinity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Disabled("SQL Server prohibits NaN and Infinity")
|
|
||||||
@Test
|
|
||||||
public void argDoubleNaN() {
|
|
||||||
super.argDoubleNaN();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Disabled("SQL Server prohibits NaN and Infinity")
|
|
||||||
@Test
|
|
||||||
public void argDoubleInfinity() {
|
|
||||||
super.argDoubleInfinity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Disabled("SQL Server seems to have incorrect min value for float (rounds to zero)")
|
|
||||||
@Test
|
|
||||||
public void argFloatMinMax() {
|
|
||||||
super.argFloatMinMax();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Disabled("SQL Server doesn't support the interval syntax for date arithmetic")
|
|
||||||
@Test
|
|
||||||
public void intervals() {
|
|
||||||
super.intervals();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SQL Server seems to have different behavior in that is does not convert
|
|
||||||
* column names to uppercase (it preserves the case).
|
|
||||||
* I haven't figured out how to smooth over this difference, since all databases
|
|
||||||
* seem to respect the provided case when it is inside quotes, but don't provide
|
|
||||||
* a way to tell whether a particular parameter was quoted.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Test
|
|
||||||
public void metadataColumnNames() {
|
|
||||||
db.dropTableQuietly("dbtest");
|
|
||||||
new Schema().addTable("dbtest").addColumn("pk").primaryKey().schema().execute(db);
|
|
||||||
db.toSelect("select Pk, Pk as Foo, Pk as \"Foo\" from dbtest").query(rs -> {
|
|
||||||
assertArrayEquals(new String[]{"Pk", "Foo", "Foo"}, rs.getColumnLabels());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
|
||||||
.level=ALL
|
|
||||||
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
|
|
||||||
java.util.logging.ConsoleHandler.level=ALL
|
|
||||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
|
||||||
java.util.logging.FileHandler.level=ALL
|
|
||||||
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
|
||||||
java.util.logging.FileHandler.pattern=build/database.log
|
|
||||||
jdk.event.security.level=INFO
|
|
||||||
javax.management.level=INFO
|
|
|
@ -29,8 +29,10 @@ import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -58,29 +60,33 @@ public abstract class CommonTest {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(CommonTest.class.getName());
|
private static final Logger logger = Logger.getLogger(CommonTest.class.getName());
|
||||||
|
|
||||||
final static String TEST_TABLE_NAME = "dbtest";
|
|
||||||
|
|
||||||
protected static DatabaseProvider dbp;
|
protected static DatabaseProvider dbp;
|
||||||
|
|
||||||
protected Database db;
|
protected Database db;
|
||||||
|
|
||||||
protected LocalDateTime now;
|
protected LocalDateTime localDateTimeNow;
|
||||||
|
|
||||||
protected LocalDate localDateNow;
|
protected LocalDate localDateNow;
|
||||||
|
|
||||||
|
protected OffsetDateTime offsetDateTimeNow;
|
||||||
|
|
||||||
|
protected ZonedDateTime zonedDateTimeNow;
|
||||||
|
|
||||||
protected abstract DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception;
|
protected abstract DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setupJdbc() throws Exception {
|
public void setupJdbc() throws Exception {
|
||||||
now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
localDateTimeNow = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
||||||
localDateNow = LocalDate.now();
|
localDateNow = LocalDate.now();
|
||||||
|
offsetDateTimeNow = OffsetDateTime.now();
|
||||||
|
zonedDateTimeNow = ZonedDateTime.now();
|
||||||
dbp = createDatabaseProvider(new OptionsOverride() {
|
dbp = createDatabaseProvider(new OptionsOverride() {
|
||||||
});
|
});
|
||||||
db = dbp.get();
|
db = dbp.get();
|
||||||
if (!db.probe(15)) {
|
if (!db.probe(15)) {
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
db.dropTableQuietly(TEST_TABLE_NAME);
|
db.dropTableQuietly("dbtest");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
|
@ -99,12 +105,12 @@ public abstract class CommonTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tableExists() {
|
public void tableExists() {
|
||||||
// Verify dbtest table does not exist
|
// Verify table does not exist
|
||||||
String lowercaseTable = TEST_TABLE_NAME.toLowerCase();
|
String lowercaseTable = "dbtest";
|
||||||
testTableLookup(lowercaseTable);
|
testTableLookup(lowercaseTable);
|
||||||
db.dropTableQuietly(lowercaseTable);
|
db.dropTableQuietly(lowercaseTable);
|
||||||
// Let's try creating a table with an upper case name and verify it works
|
// Let's try creating a table with an upper case name and verify it works
|
||||||
String uppercaseTable = TEST_TABLE_NAME.toUpperCase();
|
String uppercaseTable = "DBTEST";
|
||||||
testTableLookup(uppercaseTable);
|
testTableLookup(uppercaseTable);
|
||||||
db.dropTableQuietly(uppercaseTable);
|
db.dropTableQuietly(uppercaseTable);
|
||||||
// Verify that null or empty name is handled gracefully
|
// Verify that null or empty name is handled gracefully
|
||||||
|
@ -127,8 +133,8 @@ public abstract class CommonTest {
|
||||||
String camelCaseTableName = "\"DbTest\"";
|
String camelCaseTableName = "\"DbTest\"";
|
||||||
assertEquals(camelCaseTableName.substring(1, camelCaseTableName.length() - 1),
|
assertEquals(camelCaseTableName.substring(1, camelCaseTableName.length() - 1),
|
||||||
db.flavor().normalizeTableName(camelCaseTableName));
|
db.flavor().normalizeTableName(camelCaseTableName));
|
||||||
assertEquals(TEST_TABLE_NAME.toUpperCase(Locale.ENGLISH),
|
assertEquals("DBTEST",
|
||||||
db.flavor().normalizeTableName(TEST_TABLE_NAME).toUpperCase(Locale.ENGLISH));
|
db.flavor().normalizeTableName("dbtest").toUpperCase(Locale.ENGLISH));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -145,13 +151,29 @@ public abstract class CommonTest {
|
||||||
.addColumn("str_lob").asClob().table()
|
.addColumn("str_lob").asClob().table()
|
||||||
.addColumn("bin_blob").asBlob().table()
|
.addColumn("bin_blob").asBlob().table()
|
||||||
.addColumn("date_millis").asLocalDateTime().table()
|
.addColumn("date_millis").asLocalDateTime().table()
|
||||||
.addColumn("local_date").asLocalDate().table().schema().execute(db);
|
.addColumn("local_date").asLocalDate().table()
|
||||||
|
.addColumn("offset_date_time").asOffsetDateTime().table()
|
||||||
|
.addColumn("tz_date_time").asZonedateTime().table()
|
||||||
|
.schema()
|
||||||
|
.execute(db);
|
||||||
BigDecimal bigDecimal = new BigDecimal("5.3");
|
BigDecimal bigDecimal = new BigDecimal("5.3");
|
||||||
db.toInsert("insert into dbtest values (?,?,?,?,?,?,?,?,?,?,?)").argInteger(1).argLong(2L).argFloat(3.2f).argDouble(4.2)
|
db.toInsert("insert into dbtest values (?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||||
.argBigDecimal(bigDecimal).argString("Hello").argString("T").argClobString("World")
|
.argInteger(1)
|
||||||
.argBlobBytes("More".getBytes()).argLocalDateTime(now).argLocalDate(localDateNow).insert(1);
|
.argLong(2L)
|
||||||
|
.argFloat(3.2f)
|
||||||
|
.argDouble(4.2)
|
||||||
|
.argBigDecimal(bigDecimal)
|
||||||
|
.argString("Hello")
|
||||||
|
.argString("T")
|
||||||
|
.argClobString("World")
|
||||||
|
.argBlobBytes("More".getBytes())
|
||||||
|
.argLocalDateTime(localDateTimeNow)
|
||||||
|
.argLocalDate(localDateNow)
|
||||||
|
.argOffsetDateTime(offsetDateTimeNow)
|
||||||
|
.argZonedDateTime(zonedDateTimeNow)
|
||||||
|
.insert(1);
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
||||||
+ "bin_blob, date_millis, local_date from dbtest")
|
+ "bin_blob, date_millis, local_date, offset_date_time, tz_date_time from dbtest")
|
||||||
.query((RowsHandler<Void>) rs -> {
|
.query((RowsHandler<Void>) rs -> {
|
||||||
assertTrue(rs.next());
|
assertTrue(rs.next());
|
||||||
assertEquals(Integer.valueOf(1), rs.getIntegerOrNull(1));
|
assertEquals(Integer.valueOf(1), rs.getIntegerOrNull(1));
|
||||||
|
@ -190,15 +212,22 @@ public abstract class CommonTest {
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob"));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob"));
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen(9));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen(9));
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen("bin_blob"));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen("bin_blob"));
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull(10));
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull(10));
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull("date_millis"));
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull("date_millis"));
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull(11));
|
assertEquals(localDateNow, rs.getLocalDateOrNull(11));
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull("local_date"));
|
assertEquals(localDateNow, rs.getLocalDateOrNull("local_date"));
|
||||||
|
assertEquals(offsetDateTimeNow.truncatedTo(ChronoUnit.SECONDS),
|
||||||
|
rs.getOffsetDateTimeOrNull(12).truncatedTo(ChronoUnit.SECONDS));
|
||||||
|
assertEquals(offsetDateTimeNow.truncatedTo(ChronoUnit.SECONDS),
|
||||||
|
rs.getOffsetDateTimeOrNull("offset_date_time").truncatedTo(ChronoUnit.SECONDS));
|
||||||
|
// org.postgresql.util.PSQLException: conversion to class java.time.ZonedDateTime from timestamptz not supported
|
||||||
|
// assertEquals(zonedDateTimeNow, rs.getZonedDateTimeOrNull(13));
|
||||||
|
// assertEquals(zonedDateTimeNow, rs.getZonedDateTimeOrNull("tz_date_time"));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
// Repeat the above query, using the various methods that automatically infer the column
|
// Repeat the above query, using the various methods that automatically infer the column
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
||||||
+ "bin_blob, date_millis, local_date from dbtest")
|
+ "bin_blob, date_millis, local_date, offset_date_time, tz_date_time from dbtest")
|
||||||
.query((RowsHandler<Void>) rs -> {
|
.query((RowsHandler<Void>) rs -> {
|
||||||
assertTrue(rs.next());
|
assertTrue(rs.next());
|
||||||
assertEquals(Integer.valueOf(1), rs.getIntegerOrNull());
|
assertEquals(Integer.valueOf(1), rs.getIntegerOrNull());
|
||||||
|
@ -210,12 +239,15 @@ public abstract class CommonTest {
|
||||||
assertEquals("T", rs.getStringOrNull());
|
assertEquals("T", rs.getStringOrNull());
|
||||||
assertEquals("World", rs.getClobStringOrNull());
|
assertEquals("World", rs.getClobStringOrNull());
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull());
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull());
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull());
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull());
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull());
|
assertEquals(localDateNow, rs.getLocalDateOrNull());
|
||||||
|
assertEquals(offsetDateTimeNow.truncatedTo(ChronoUnit.SECONDS), rs.getOffsetDateTimeOrNull().truncatedTo(ChronoUnit.SECONDS));
|
||||||
|
// org.postgresql.util.PSQLException: conversion to class java.time.ZonedDateTime from timestamptz not supported
|
||||||
|
//assertEquals(zonedDateTimeNow, rs.getZonedDateTimeOrNull());
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
||||||
+ "bin_blob, date_millis, local_date from dbtest")
|
+ "bin_blob, date_millis, local_date, offset_date_time, tz_date_time from dbtest")
|
||||||
.query((RowsHandler<Void>) rs -> {
|
.query((RowsHandler<Void>) rs -> {
|
||||||
assertTrue(rs.next());
|
assertTrue(rs.next());
|
||||||
assertEquals(1, rs.getIntegerOrZero());
|
assertEquals(1, rs.getIntegerOrZero());
|
||||||
|
@ -227,6 +259,11 @@ public abstract class CommonTest {
|
||||||
assertEquals("T", rs.getStringOrEmpty());
|
assertEquals("T", rs.getStringOrEmpty());
|
||||||
assertEquals("World", rs.getClobStringOrEmpty());
|
assertEquals("World", rs.getClobStringOrEmpty());
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen());
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen());
|
||||||
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull());
|
||||||
|
assertEquals(localDateNow, rs.getLocalDateOrNull());
|
||||||
|
assertEquals(offsetDateTimeNow.truncatedTo(ChronoUnit.SECONDS), rs.getOffsetDateTimeOrNull().truncatedTo(ChronoUnit.SECONDS));
|
||||||
|
// org.postgresql.util.PSQLException: conversion to class java.time.ZonedDateTime from timestamptz not supported
|
||||||
|
//assertEquals(zonedDateTimeNow, rs.getZonedDateTimeOrNull());
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
db.toSelect("select str_lob, bin_blob from dbtest").query((RowsHandler<Void>) rs -> {
|
db.toSelect("select str_lob, bin_blob from dbtest").query((RowsHandler<Void>) rs -> {
|
||||||
|
@ -275,16 +312,16 @@ public abstract class CommonTest {
|
||||||
.argBigDecimal("bd", bigDecimal)
|
.argBigDecimal("bd", bigDecimal)
|
||||||
.argString("s", "Hello")
|
.argString("s", "Hello")
|
||||||
.argString("sf", "T")
|
.argString("sf", "T")
|
||||||
.argLocalDateTime("date", now)
|
.argLocalDateTime("date", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow)
|
.argLocalDate("local_date", localDateNow)
|
||||||
.queryLongOrNull());
|
.queryLongOrNull());
|
||||||
List<Long> result = db.toSelect("select count(*) from dbtest where nbr_integer=:i and nbr_long=:l and "
|
List<Long> result = db.toSelect("select count(*) from dbtest where nbr_integer=:i and nbr_long=:l and "
|
||||||
+ "abs(nbr_float-:f)<0.01 and abs(nbr_double-:d)<0.01 and nbr_big_decimal=:bd and str_varchar=:s "
|
+ "abs(nbr_float-:f)<0.01 and abs(nbr_double-:d)<0.01 and nbr_big_decimal=:bd and str_varchar=:s "
|
||||||
+ "and str_fixed=:sf and date_millis=:date and local_date=:local_date").argInteger("i", 1).argLong("l", 2L).argFloat("f", 3.2f)
|
+ "and str_fixed=:sf and date_millis=:date and local_date=:local_date").argInteger("i", 1).argLong("l", 2L).argFloat("f", 3.2f)
|
||||||
.argDouble("d", 4.2).argBigDecimal("bd", bigDecimal).argString("s", "Hello").argString("sf", "T")
|
.argDouble("d", 4.2).argBigDecimal("bd", bigDecimal).argString("s", "Hello").argString("sf", "T")
|
||||||
.argLocalDateTime("date", now).argLocalDate("local_date", localDateNow).queryLongs();
|
.argLocalDateTime("date", localDateTimeNow).argLocalDate("local_date", localDateNow).queryLongs();
|
||||||
assertEquals(1, result.size());
|
assertEquals(1, result.size());
|
||||||
assertEquals(Long.valueOf(1), result.get(0));
|
assertEquals(Long.valueOf(1), result.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -316,7 +353,7 @@ public abstract class CommonTest {
|
||||||
.argString("T")
|
.argString("T")
|
||||||
.argClobString("World")
|
.argClobString("World")
|
||||||
.argBlobBytes("More".getBytes())
|
.argBlobBytes("More".getBytes())
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow).insert());
|
.argLocalDate(localDateNow).insert());
|
||||||
db.toUpdate("update dbtest set nbr_integer=?, nbr_long=?, nbr_float=?, nbr_double=?, nbr_big_decimal=?, "
|
db.toUpdate("update dbtest set nbr_integer=?, nbr_long=?, nbr_float=?, nbr_double=?, nbr_big_decimal=?, "
|
||||||
+ "str_varchar=?, str_fixed=?, str_lob=?, bin_blob=?, date_millis=?, local_date=?").argInteger(null).argLong(null)
|
+ "str_varchar=?, str_fixed=?, str_lob=?, bin_blob=?, date_millis=?, local_date=?").argInteger(null).argLong(null)
|
||||||
|
@ -352,7 +389,7 @@ public abstract class CommonTest {
|
||||||
assertEquals(1, db.toUpdate("update dbtest set nbr_integer=?, nbr_long=?, nbr_float=?, nbr_double=?, "
|
assertEquals(1, db.toUpdate("update dbtest set nbr_integer=?, nbr_long=?, nbr_float=?, nbr_double=?, "
|
||||||
+ "nbr_big_decimal=?, str_varchar=?, str_fixed=?, str_lob=?, bin_blob=?, date_millis=?, local_date=?").argInteger(1)
|
+ "nbr_big_decimal=?, str_varchar=?, str_fixed=?, str_lob=?, bin_blob=?, date_millis=?, local_date=?").argInteger(1)
|
||||||
.argLong(2L).argFloat(3.2f).argDouble(4.2).argBigDecimal(bigDecimal).argString("Hello").argString("T")
|
.argLong(2L).argFloat(3.2f).argDouble(4.2).argBigDecimal(bigDecimal).argString("Hello").argString("T")
|
||||||
.argClobString("World").argBlobBytes("More".getBytes()).argLocalDateTime(now).argLocalDate(localDateNow).update());
|
.argClobString("World").argBlobBytes("More".getBytes()).argLocalDateTime(localDateTimeNow).argLocalDate(localDateNow).update());
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
||||||
+ "bin_blob, date_millis, local_date from dbtest").query((RowsHandler<Void>) rs -> {
|
+ "bin_blob, date_millis, local_date from dbtest").query((RowsHandler<Void>) rs -> {
|
||||||
assertTrue(rs.next());
|
assertTrue(rs.next());
|
||||||
|
@ -374,8 +411,8 @@ public abstract class CommonTest {
|
||||||
assertEquals("World", rs.getClobStringOrNull("str_lob"));
|
assertEquals("World", rs.getClobStringOrNull("str_lob"));
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull(9));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull(9));
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob"));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob"));
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull(10));
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull(10));
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull("date_millis"));
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull("date_millis"));
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull(11));
|
assertEquals(localDateNow, rs.getLocalDateOrNull(11));
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull("local_date"));
|
assertEquals(localDateNow, rs.getLocalDateOrNull("local_date"));
|
||||||
return null;
|
return null;
|
||||||
|
@ -422,7 +459,7 @@ public abstract class CommonTest {
|
||||||
.argLong(":b", 2L).argFloat(":c", 3.2f).argDouble(":d", 4.2).argBigDecimal(":e", bigDecimal)
|
.argLong(":b", 2L).argFloat(":c", 3.2f).argDouble(":d", 4.2).argBigDecimal(":e", bigDecimal)
|
||||||
.argString(":f", "Hello").argString(":sf", "T")
|
.argString(":f", "Hello").argString(":sf", "T")
|
||||||
.argClobString(":g", "World").argBlobBytes(":h", "More".getBytes())
|
.argClobString(":g", "World").argBlobBytes(":h", "More".getBytes())
|
||||||
.argLocalDateTime(":i", now).argLocalDate(":j", localDateNow).insert(1);
|
.argLocalDateTime(":i", localDateTimeNow).argLocalDate(":j", localDateNow).insert(1);
|
||||||
db.toUpdate("update dbtest set nbr_integer=:a, nbr_long=:b, nbr_float=:c, nbr_double=:d, nbr_big_decimal=:e, "
|
db.toUpdate("update dbtest set nbr_integer=:a, nbr_long=:b, nbr_float=:c, nbr_double=:d, nbr_big_decimal=:e, "
|
||||||
+ "str_varchar=:f, str_fixed=:sf, str_lob=:g, bin_blob=:h, date_millis=:i, local_date=:j").argInteger(":a", null)
|
+ "str_varchar=:f, str_fixed=:sf, str_lob=:g, bin_blob=:h, date_millis=:i, local_date=:j").argInteger(":a", null)
|
||||||
.argLong(":b", null).argFloat(":c", null).argDouble(":d", null).argBigDecimal(":e", null)
|
.argLong(":b", null).argFloat(":c", null).argDouble(":d", null).argBigDecimal(":e", null)
|
||||||
|
@ -461,7 +498,7 @@ public abstract class CommonTest {
|
||||||
.argLong(":b", 2L).argFloat(":c", 3.2f).argDouble(":d", 4.2).argBigDecimal(":e", bigDecimal)
|
.argLong(":b", 2L).argFloat(":c", 3.2f).argDouble(":d", 4.2).argBigDecimal(":e", bigDecimal)
|
||||||
.argString(":f", "Hello").argString(":sf", "T")
|
.argString(":f", "Hello").argString(":sf", "T")
|
||||||
.argClobString(":g", "World").argBlobBytes(":h", "More".getBytes())
|
.argClobString(":g", "World").argBlobBytes(":h", "More".getBytes())
|
||||||
.argLocalDateTime(":i", now).argLocalDate(":j", localDateNow).update(1);
|
.argLocalDateTime(":i", localDateTimeNow).argLocalDate(":j", localDateNow).update(1);
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar, str_fixed, str_lob, "
|
||||||
+ "bin_blob, date_millis, local_date from dbtest")
|
+ "bin_blob, date_millis, local_date from dbtest")
|
||||||
.query((RowsHandler<Void>) rs -> {
|
.query((RowsHandler<Void>) rs -> {
|
||||||
|
@ -484,8 +521,8 @@ public abstract class CommonTest {
|
||||||
assertEquals("World", rs.getClobStringOrNull("str_lob"));
|
assertEquals("World", rs.getClobStringOrNull("str_lob"));
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull(9));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull(9));
|
||||||
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob"));
|
assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob"));
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull(10));
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull(10));
|
||||||
assertEquals(now, rs.getLocalDateTimeOrNull("date_millis"));
|
assertEquals(localDateTimeNow, rs.getLocalDateTimeOrNull("date_millis"));
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull(11));
|
assertEquals(localDateNow, rs.getLocalDateOrNull(11));
|
||||||
assertEquals(localDateNow, rs.getLocalDateOrNull("local_date"));
|
assertEquals(localDateNow, rs.getLocalDateOrNull("local_date"));
|
||||||
return null;
|
return null;
|
||||||
|
@ -595,16 +632,17 @@ public abstract class CommonTest {
|
||||||
.addTable("dbtest")
|
.addTable("dbtest")
|
||||||
.addColumn(timestampColumnName).asLocalDateTime().table()
|
.addColumn(timestampColumnName).asLocalDateTime().table()
|
||||||
.addColumn(dateColumnName).asLocalDate().table()
|
.addColumn(dateColumnName).asLocalDate().table()
|
||||||
.schema().execute(db);
|
.schema()
|
||||||
|
.execute(db);
|
||||||
db.toSelect("select * from dbtest").query((RowsHandler<Void>) rs -> {
|
db.toSelect("select * from dbtest").query((RowsHandler<Void>) rs -> {
|
||||||
ResultSetMetaData metadata = rs.getMetadata();
|
ResultSetMetaData metadata = rs.getMetadata();
|
||||||
for (int i = 1; i <= metadata.getColumnCount(); i++) {
|
for (int i = 1; i <= metadata.getColumnCount(); i++) {
|
||||||
String columnName = metadata.getColumnName(i);
|
String columnName = metadata.getColumnName(i);
|
||||||
String columnType = metadata.getColumnTypeName(i);
|
String columnType = metadata.getColumnTypeName(i).toUpperCase(Locale.ROOT);
|
||||||
if (columnName.equalsIgnoreCase(timestampColumnName)) {
|
if (columnName.equalsIgnoreCase(timestampColumnName)) {
|
||||||
assertEquals(db.flavor().columnTypeLocalDateTime(), columnType);
|
assertEquals("TIMESTAMP", columnType);
|
||||||
} else if (columnName.equalsIgnoreCase(dateColumnName)) {
|
} else if (columnName.equalsIgnoreCase(dateColumnName)) {
|
||||||
assertEquals("DATE", columnType.toUpperCase());
|
assertEquals("DATE", columnType);
|
||||||
} else {
|
} else {
|
||||||
fail("Unexpected column " + columnName + " of type " + columnType);
|
fail("Unexpected column " + columnName + " of type " + columnType);
|
||||||
}
|
}
|
||||||
|
@ -616,10 +654,10 @@ public abstract class CommonTest {
|
||||||
@Test
|
@Test
|
||||||
public void intervals() {
|
public void intervals() {
|
||||||
new Schema().addTable("dbtest").addColumn("d").asLocalDateTime().schema().execute(db);
|
new Schema().addTable("dbtest").addColumn("d").asLocalDateTime().schema().execute(db);
|
||||||
db.toInsert("insert into dbtest (d) values (?)").argLocalDateTime(now).insert(1);
|
db.toInsert("insert into dbtest (d) values (?)").argLocalDateTime(localDateTimeNow).insert(1);
|
||||||
assertEquals(1, db.toSelect("select count(1) from dbtest where d - interval '1' hour * ? < ?")
|
assertEquals(1, db.toSelect("select count(1) from dbtest where d - interval '1' hour * ? < ?")
|
||||||
.argInteger(2)
|
.argInteger(2)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.queryIntegerOrZero());
|
.queryIntegerOrZero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +682,7 @@ public abstract class CommonTest {
|
||||||
.argDouble(Double.MAX_VALUE).argBigDecimal(new BigDecimal("123.456"))
|
.argDouble(Double.MAX_VALUE).argBigDecimal(new BigDecimal("123.456"))
|
||||||
.argString("hello").argString("Z").argClobString("hello again")
|
.argString("hello").argString("Z").argClobString("hello again")
|
||||||
.argBlobBytes(new byte[]{'1', '2'}).argBoolean(true)
|
.argBlobBytes(new byte[]{'1', '2'}).argBoolean(true)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow).insert(1);
|
.argLocalDate(localDateNow).insert(1);
|
||||||
db.toInsert("insert into dbtest (nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar,"
|
db.toInsert("insert into dbtest (nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar,"
|
||||||
+ " str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date) values (?,?,?,?,?,?,?,?,?,?,?,?)")
|
+ " str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date) values (?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||||
|
@ -652,7 +690,7 @@ public abstract class CommonTest {
|
||||||
.argDouble(Double.MIN_VALUE).argBigDecimal(new BigDecimal("-123.456"))
|
.argDouble(Double.MIN_VALUE).argBigDecimal(new BigDecimal("-123.456"))
|
||||||
.argString("goodbye").argString("A").argClobString("bye again")
|
.argString("goodbye").argString("A").argClobString("bye again")
|
||||||
.argBlobBytes(new byte[]{'3', '4'}).argBoolean(false)
|
.argBlobBytes(new byte[]{'3', '4'}).argBoolean(false)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow).insert(1);
|
.argLocalDate(localDateNow).insert(1);
|
||||||
String expectedSchema = new Schema().addTable("dbtest2")
|
String expectedSchema = new Schema().addTable("dbtest2")
|
||||||
.addColumn("nbr_integer").asInteger().table()
|
.addColumn("nbr_integer").asInteger().table()
|
||||||
|
@ -707,7 +745,7 @@ public abstract class CommonTest {
|
||||||
.argClobString("str_lob", "bye again")
|
.argClobString("str_lob", "bye again")
|
||||||
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
||||||
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
||||||
.argLocalDateTime("date_millis", now)
|
.argLocalDateTime("date_millis", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow),
|
.argLocalDate("local_date", localDateNow),
|
||||||
new SqlArgs().argInteger("nbr_integer", Integer.MAX_VALUE)
|
new SqlArgs().argInteger("nbr_integer", Integer.MAX_VALUE)
|
||||||
.argLong("nbr_long", Long.MAX_VALUE)
|
.argLong("nbr_long", Long.MAX_VALUE)
|
||||||
|
@ -719,7 +757,7 @@ public abstract class CommonTest {
|
||||||
.argClobString("str_lob", "hello again")
|
.argClobString("str_lob", "hello again")
|
||||||
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
||||||
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
||||||
.argLocalDateTime("date_millis", now)
|
.argLocalDateTime("date_millis", localDateTimeNow)
|
||||||
.argLocalDate("local_date", localDateNow)),
|
.argLocalDate("local_date", localDateNow)),
|
||||||
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
||||||
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
||||||
|
@ -1318,7 +1356,7 @@ public abstract class CommonTest {
|
||||||
new Schema().addTable("dbtest").addColumn("i").asBigDecimal(38, 38).schema().execute(db);
|
new Schema().addTable("dbtest").addColumn("i").asBigDecimal(38, 38).schema().execute(db);
|
||||||
BigDecimal value = new BigDecimal("0.99999999999999999999999999999999999999"); // 38 digits
|
BigDecimal value = new BigDecimal("0.99999999999999999999999999999999999999"); // 38 digits
|
||||||
db.toInsert("insert into dbtest (i) values (?)").argBigDecimal(value).insert(1);
|
db.toInsert("insert into dbtest (i) values (?)").argBigDecimal(value).insert(1);
|
||||||
logger.info(db.toSelect("select i from dbtest").queryBigDecimalOrNull().toString());
|
String s = db.toSelect("select i from dbtest").queryBigDecimalOrNull().toString();
|
||||||
assertEquals(value,
|
assertEquals(value,
|
||||||
db.toSelect("select i from dbtest where i=?").argBigDecimal(value).queryBigDecimalOrNull());
|
db.toSelect("select i from dbtest where i=?").argBigDecimal(value).queryBigDecimalOrNull());
|
||||||
}
|
}
|
||||||
|
@ -1367,15 +1405,15 @@ public abstract class CommonTest {
|
||||||
.execute(db);
|
.execute(db);
|
||||||
db.toInsert("insert into dbtest (pk, d) values (:seq, :d)")
|
db.toInsert("insert into dbtest (pk, d) values (:seq, :d)")
|
||||||
.argPkSeq(":seq", "dbtest_seq")
|
.argPkSeq(":seq", "dbtest_seq")
|
||||||
.argLocalDateTime(":d", now)
|
.argLocalDateTime(":d", localDateTimeNow)
|
||||||
.insertReturning("dbtest", "pk", rs -> {
|
.insertReturning("dbtest", "pk", rs -> {
|
||||||
assertTrue(rs.next());
|
assertTrue(rs.next());
|
||||||
assertEquals(Long.valueOf(1L), rs.getLongOrNull(1));
|
assertEquals(Long.valueOf(1L), rs.getLongOrNull(1));
|
||||||
assertThat(rs.getLocalDateTimeOrNull(2, ZoneId.systemDefault()), equalTo(now));
|
assertThat(rs.getLocalDateTimeOrNull(2), equalTo(localDateTimeNow));
|
||||||
assertFalse(rs.next());
|
assertFalse(rs.next());
|
||||||
return null;
|
return null;
|
||||||
}, "d");
|
}, "d");
|
||||||
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d=?").argLocalDateTime(now).queryLongOrNull());
|
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d=?").argLocalDateTime(localDateTimeNow).queryLongOrNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1393,7 +1431,7 @@ public abstract class CommonTest {
|
||||||
.execute(db);
|
.execute(db);
|
||||||
db.toInsert("insert into dbtest (pk, d, d3, s) values (?,?,?,?)")
|
db.toInsert("insert into dbtest (pk, d, d3, s) values (?,?,?,?)")
|
||||||
.argLong(1L)
|
.argLong(1L)
|
||||||
.argLocalDateTime(now)
|
.argLocalDateTime(localDateTimeNow)
|
||||||
.argLocalDate(localDateNow)
|
.argLocalDate(localDateNow)
|
||||||
.argString("foo")
|
.argString("foo")
|
||||||
.insert(1);
|
.insert(1);
|
||||||
|
@ -1424,10 +1462,10 @@ public abstract class CommonTest {
|
||||||
assertEquals("foo", db.toSelect("select s from dbtest").queryStrings().get(0));
|
assertEquals("foo", db.toSelect("select s from dbtest").queryStrings().get(0));
|
||||||
assertTrue(db.toSelect("select s from dbtest where 1=0").queryStrings().isEmpty());
|
assertTrue(db.toSelect("select s from dbtest where 1=0").queryStrings().isEmpty());
|
||||||
assertTrue(db.toSelect("select s2 from dbtest").queryStrings().isEmpty());
|
assertTrue(db.toSelect("select s2 from dbtest").queryStrings().isEmpty());
|
||||||
assertEquals(now, db.toSelect("select d from dbtest").queryLocalDateTimeOrNull());
|
assertEquals(localDateTimeNow, db.toSelect("select d from dbtest").queryLocalDateTimeOrNull());
|
||||||
assertNull(db.toSelect("select d from dbtest where 1=0").queryLocalDateTimeOrNull());
|
assertNull(db.toSelect("select d from dbtest where 1=0").queryLocalDateTimeOrNull());
|
||||||
assertNull(db.toSelect("select d2 from dbtest").queryLocalDateTimeOrNull());
|
assertNull(db.toSelect("select d2 from dbtest").queryLocalDateTimeOrNull());
|
||||||
assertEquals(db.toSelect("select d from dbtest").queryLocalDateTimes().get(0), now);
|
assertEquals(db.toSelect("select d from dbtest").queryLocalDateTimes().get(0), localDateTimeNow);
|
||||||
assertTrue(db.toSelect("select d from dbtest where 1=0").queryLocalDateTimes().isEmpty());
|
assertTrue(db.toSelect("select d from dbtest where 1=0").queryLocalDateTimes().isEmpty());
|
||||||
assertTrue(db.toSelect("select d2 from dbtest").queryLocalDateTimes().isEmpty());
|
assertTrue(db.toSelect("select d2 from dbtest").queryLocalDateTimes().isEmpty());
|
||||||
|
|
||||||
|
@ -1570,27 +1608,32 @@ public abstract class CommonTest {
|
||||||
for (int attempts = 1; attempts <= 10; attempts++) {
|
for (int attempts = 1; attempts <= 10; attempts++) {
|
||||||
new Schema()
|
new Schema()
|
||||||
.addTable("dbtest")
|
.addTable("dbtest")
|
||||||
.addColumn("d").asLocalDateTime().table().schema()
|
.addColumn("d").asLocalDateTime()
|
||||||
|
.table()
|
||||||
|
.schema()
|
||||||
.execute(db);
|
.execute(db);
|
||||||
db.toInsert("insert into dbtest (d) values (?)")
|
db.toInsert("insert into dbtest (d) values (?)")
|
||||||
.argLocalDateTimeNowPerDb()
|
.argLocalDateTimeNowPerDb()
|
||||||
.insert(1);
|
.insert(1);
|
||||||
LocalDateTime dbNow = db.toSelect("select d from dbtest").queryLocalDateTimeOrNull();
|
LocalDateTime dbNow = db.toSelect("select d from dbtest").queryLocalDateTimeOrNull();
|
||||||
if (dbNow != null && dbNow.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() % 10 != 0) {
|
if (dbNow != null && dbNow.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() % 10 != 0) {
|
||||||
|
// done
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.info("Zero in least significant digit (attempt " + attempts + ")");
|
logger.log(Level.INFO, "Zero in least significant digit (attempt " + attempts + ")");
|
||||||
db.dropTableQuietly(TEST_TABLE_NAME);
|
db.dropTableQuietly("dbtest");
|
||||||
}
|
}
|
||||||
fail("Timestamp had zero in the least significant digit");
|
fail("unable to match dateMillis");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dateRoundTrip() {
|
public void dateRoundTrip() {
|
||||||
new Schema()
|
new Schema()
|
||||||
.addTable("dbtest")
|
.addTable("dbtest")
|
||||||
.addColumn("d1").asLocalDateTime().table()
|
.addColumn("d1").asLocalDateTime()
|
||||||
.addColumn("d2").asLocalDateTime().table()
|
.table()
|
||||||
|
.addColumn("d2").asLocalDateTime()
|
||||||
|
.table()
|
||||||
.schema()
|
.schema()
|
||||||
.execute(db);
|
.execute(db);
|
||||||
db.toInsert("insert into dbtest (d1) values (?)")
|
db.toInsert("insert into dbtest (d1) values (?)")
|
||||||
|
@ -1600,15 +1643,14 @@ public abstract class CommonTest {
|
||||||
db.toUpdate("update dbtest set d2 = ?")
|
db.toUpdate("update dbtest set d2 = ?")
|
||||||
.argLocalDateTime(dbNow)
|
.argLocalDateTime(dbNow)
|
||||||
.update(1);
|
.update(1);
|
||||||
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d1=d2").queryLongOrNull());
|
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d1 = d2").queryLongOrNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dateRoundTripTimezones() {
|
public void dateRoundTripTimezones() {
|
||||||
new Schema()
|
new Schema()
|
||||||
.addTable("dbtest")
|
.addTable("dbtest")
|
||||||
.addColumn("d")
|
.addColumn("d").asLocalDateTime()
|
||||||
.asLocalDateTime()
|
|
||||||
.table()
|
.table()
|
||||||
.schema()
|
.schema()
|
||||||
.execute(db);
|
.execute(db);
|
||||||
|
@ -1617,7 +1659,6 @@ public abstract class CommonTest {
|
||||||
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, dateMinusZone);
|
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, dateMinusZone);
|
||||||
ZoneId datePlusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4));
|
ZoneId datePlusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4));
|
||||||
LocalDateTime datePlus = LocalDateTime.ofInstant(instant,datePlusZone);
|
LocalDateTime datePlus = LocalDateTime.ofInstant(instant,datePlusZone);
|
||||||
logger.log(Level.INFO, "dateMinus = " + dateMinus);
|
|
||||||
db.toInsert("insert into dbtest (d) values (?)")
|
db.toInsert("insert into dbtest (d) values (?)")
|
||||||
.argLocalDateTime(dateMinus)
|
.argLocalDateTime(dateMinus)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
|
@ -1631,7 +1672,7 @@ public abstract class CommonTest {
|
||||||
.argLocalDateTime(datePlus)
|
.argLocalDateTime(datePlus)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
LocalDateTime localDateTimePlus = db.toSelect("select d from dbtest")
|
LocalDateTime localDateTimePlus = db.toSelect("select d from dbtest")
|
||||||
.queryLocalDateTimeOrNull(datePlusZone);
|
.queryLocalDateTimeOrNull();
|
||||||
assertEquals(datePlus, localDateTimePlus);
|
assertEquals(datePlus, localDateTimePlus);
|
||||||
assertEquals("1970-01-03 02:17:36.789",
|
assertEquals("1970-01-03 02:17:36.789",
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimePlus));
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimePlus));
|
||||||
|
@ -1651,7 +1692,6 @@ public abstract class CommonTest {
|
||||||
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, dateMinusZone);
|
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, dateMinusZone);
|
||||||
ZoneId datePlusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4));
|
ZoneId datePlusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4));
|
||||||
LocalDateTime datePlus = LocalDateTime.ofInstant(instant, datePlusZone);
|
LocalDateTime datePlus = LocalDateTime.ofInstant(instant, datePlusZone);
|
||||||
logger.info("LocalDateTime: dateMinus=" + dateMinus + " datePlus=" + datePlus);
|
|
||||||
new Schema().addTable("dbtest").addColumn("d")
|
new Schema().addTable("dbtest").addColumn("d")
|
||||||
.asLocalDateTime()
|
.asLocalDateTime()
|
||||||
.schema()
|
.schema()
|
||||||
|
@ -1670,7 +1710,7 @@ public abstract class CommonTest {
|
||||||
.argLocalDateTime(datePlus)
|
.argLocalDateTime(datePlus)
|
||||||
.insert(1);
|
.insert(1);
|
||||||
localDateTime = db.toSelect("select d from dbtest")
|
localDateTime = db.toSelect("select d from dbtest")
|
||||||
.queryLocalDateTimeOrNull(datePlusZone);
|
.queryLocalDateTimeOrNull();
|
||||||
assertEquals("1970-01-03 02:17:36.789",
|
assertEquals("1970-01-03 02:17:36.789",
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTime.atZone(datePlusZone)));
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTime.atZone(datePlusZone)));
|
||||||
db.toDelete("delete from dbtest where d = ?")
|
db.toDelete("delete from dbtest where d = ?")
|
||||||
|
|
|
@ -2,18 +2,18 @@ dependencyResolutionManagement {
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
libs {
|
libs {
|
||||||
version('gradle', '8.7')
|
version('gradle', '8.7')
|
||||||
library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.4.1')
|
library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.5.2')
|
||||||
library('oracle', 'com.oracle.database.jdbc', 'ojdbc11').version('23.4.0.24.05')
|
library('oracle', 'com.oracle.database.jdbc', 'ojdbc11').version('23.7.0.25.01')
|
||||||
library('postgresql', 'org.postgresql', 'postgresql').version('42.7.3')
|
library('postgresql', 'org.postgresql', 'postgresql').version('42.7.5')
|
||||||
}
|
}
|
||||||
testLibs {
|
testLibs {
|
||||||
version('junit', '5.10.2')
|
version('junit', '5.12.0')
|
||||||
version('testcontainers', '1.20.0')
|
version('testcontainers', '1.20.0')
|
||||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
||||||
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
||||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
||||||
library('junit-jupiter-platform-launcher', 'org.junit.platform', 'junit-platform-launcher').version('1.10.1')
|
library('junit-jupiter-platform-launcher', 'org.junit.platform', 'junit-platform-launcher').version('1.12.0')
|
||||||
library('hamcrest', 'org.hamcrest', 'hamcrest-library').version('2.2')
|
library('hamcrest', 'org.hamcrest', 'hamcrest-library').version('3.0')
|
||||||
library('junit4', 'junit', 'junit').version('4.13.2')
|
library('junit4', 'junit', 'junit').version('4.13.2')
|
||||||
library('derby', 'org.apache.derby', 'derby').version('10.17.1.0')
|
library('derby', 'org.apache.derby', 'derby').version('10.17.1.0')
|
||||||
library('hsqldb', 'org.hsqldb', 'hsqldb').version('2.7.3')
|
library('hsqldb', 'org.hsqldb', 'hsqldb').version('2.7.3')
|
||||||
|
@ -35,4 +35,3 @@ include 'jdbc-test'
|
||||||
include 'jdbc-mariadb'
|
include 'jdbc-mariadb'
|
||||||
include 'jdbc-oracle'
|
include 'jdbc-oracle'
|
||||||
include 'jdbc-postgresql'
|
include 'jdbc-postgresql'
|
||||||
include 'jdbc-sqlserver'
|
|
||||||
|
|
Loading…
Reference in a new issue