move java.util.Date to java.time
This commit is contained in:
parent
1047be8456
commit
625c8999a3
36 changed files with 796 additions and 922 deletions
|
@ -2,7 +2,6 @@ package org.xbib.jdbc.query;
|
|||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -90,11 +89,6 @@ public interface Database extends Supplier<Database> {
|
|||
*/
|
||||
Long nextSequenceValue( String sequenceName);
|
||||
|
||||
/**
|
||||
* Get the value that would be used if you specify an argNowPerApp() parameter.
|
||||
*/
|
||||
LocalDateTime nowPerApp();
|
||||
|
||||
/**
|
||||
* Cause the underlying connection to commit its transaction immediately. This
|
||||
* must be explicitly enabled (see {@link Options},
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.sql.Statement;
|
|||
import java.sql.Timestamp;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -95,11 +94,6 @@ public class DatabaseImpl implements Database {
|
|||
return toSelect(flavor().sequenceSelectNextVal(sequenceName)).queryLongOrNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime nowPerApp() {
|
||||
return options.currentDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitNow() {
|
||||
if (options.ignoreTransactionControl()) {
|
||||
|
@ -250,8 +244,9 @@ public class DatabaseImpl implements Database {
|
|||
@Override
|
||||
public void assertTimeSynchronized(long millisToWarn, long millisToError) {
|
||||
toSelect("select ?" + flavor().fromAny())
|
||||
.argDateNowPerDb().queryFirstOrNull(r -> {
|
||||
LocalDateTime appDate = nowPerApp();
|
||||
.argLocalDateTimeNowPerDb()
|
||||
.queryFirstOrNull(r -> {
|
||||
LocalDateTime appDate = LocalDateTime.now();
|
||||
LocalDateTime dbDate = r.getLocalDateTimeOrNull();
|
||||
if (dbDate == null) {
|
||||
throw new DatabaseException("Expecting a date in the result");
|
||||
|
|
|
@ -1106,7 +1106,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
public Builder withDatePerAppOnly() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean useDatePerAppOnly() {
|
||||
public boolean useLocalDateTimeOnly() {
|
||||
return true;
|
||||
}
|
||||
}.withParent(this.options));
|
||||
|
|
|
@ -30,13 +30,11 @@ public class DdlImpl implements Ddl {
|
|||
private void updateInternal(boolean quiet) {
|
||||
CallableStatement ps = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
Exception logEx = null;
|
||||
try {
|
||||
ps = connection.prepareCall(sql);
|
||||
|
||||
metric.checkpoint("prep");
|
||||
ps.execute();
|
||||
metric.checkpoint("exec");
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public interface Flavor {
|
||||
|
@ -39,7 +36,7 @@ public interface Flavor {
|
|||
|
||||
String typeBlob();
|
||||
|
||||
String typeDate();
|
||||
String typeLocalDateTime();
|
||||
|
||||
String typeLocalDate();
|
||||
|
||||
|
@ -72,17 +69,6 @@ public interface Flavor {
|
|||
*/
|
||||
String fromAny();
|
||||
|
||||
/**
|
||||
* Return a SQL function representing the specified date. For example, in PostgreSQL this
|
||||
* looks like "'1970-01-02 02:17:36.789000 GMT'::timestamp".
|
||||
*/
|
||||
String dateAsSqlFunction(Timestamp timestamp, Calendar calendar);
|
||||
|
||||
/**
|
||||
* Return a SQL function representing the specified date without time.
|
||||
*/
|
||||
String localDateAsSqlFunction(Date date);
|
||||
|
||||
String sequenceOptions();
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Control various optional behavior for the database interactions.
|
||||
*/
|
||||
|
@ -95,27 +92,10 @@ public interface Options {
|
|||
Flavor flavor();
|
||||
|
||||
/**
|
||||
* The value returned by this method will be used for argDateNowPerApp() calls. It
|
||||
* may also be used for argDateNowPerDb() calls if you have enabled that.
|
||||
* This is useful for testing purposes as you can use OptionsOverride to provide your
|
||||
* own clock that will be used.
|
||||
*/
|
||||
LocalDateTime currentDate();
|
||||
|
||||
/**
|
||||
* Wherever argDateNowPerDb() is specified, use argDateNowPerApp() instead. This is
|
||||
* useful for testing purposes as you can use OptionsOverride to provide your
|
||||
* own system clock that will be used for time travel.
|
||||
*/
|
||||
boolean useDatePerAppOnly();
|
||||
|
||||
/**
|
||||
* This calendar will be used for conversions when storing and retrieving timestamps
|
||||
* from the database. By default this is the JVM default with TimeZone explicitly set
|
||||
* to GMT (so timestamps will be stored in the database as GMT).
|
||||
*
|
||||
* <p>It is strongly recommended to always run your database in GMT timezone, and
|
||||
* leave this set to the default.</p>
|
||||
*/
|
||||
Calendar calendarForTimestamps();
|
||||
boolean useLocalDateTimeOnly();
|
||||
|
||||
/**
|
||||
* The maximum number of characters to print in debug SQL for a given String type
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Control various optional behavior for the database interactions.
|
||||
|
@ -44,8 +40,7 @@ public class OptionsDefault implements Options {
|
|||
|
||||
@Override
|
||||
public String generateErrorCode() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:H:m:s");
|
||||
return sdf.format(new Date()) + "-" + Math.round(Math.random() * 1000000);
|
||||
return LocalDateTime.now() + "-" + Math.round(Math.random() * 1000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,20 +59,10 @@ public class OptionsDefault implements Options {
|
|||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime currentDate() {
|
||||
return LocalDateTime.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useDatePerAppOnly() {
|
||||
public boolean useLocalDateTimeOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar calendarForTimestamps() {
|
||||
return Calendar.getInstance(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxStringLengthParam() {
|
||||
return 4000;
|
||||
|
|
|
@ -2,9 +2,6 @@ package org.xbib.jdbc.query;
|
|||
|
||||
import org.xbib.jdbc.query.flavor.Postgresql;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Base class for selectively overriding another Options object.
|
||||
|
@ -90,18 +87,8 @@ public class OptionsOverride implements Options {
|
|||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime currentDate() {
|
||||
return parent.currentDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useDatePerAppOnly() {
|
||||
return parent.useDatePerAppOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar calendarForTimestamps() {
|
||||
return parent.calendarForTimestamps();
|
||||
public boolean useLocalDateTimeOnly() {
|
||||
return parent.useLocalDateTimeOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.math.BigDecimal;
|
|||
import java.sql.ResultSetMetaData;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
/**
|
||||
* Interface for reading results from a database query.
|
||||
|
@ -228,163 +229,128 @@ public interface Row {
|
|||
* representation. Some databases will pad the number out to "full precision". This
|
||||
* method tries to reduce scale if there is zero padding to the right of the decimal.
|
||||
*/
|
||||
|
||||
BigDecimal getBigDecimalOrNull();
|
||||
|
||||
|
||||
BigDecimal getBigDecimalOrNull(int columnOneBased);
|
||||
|
||||
|
||||
BigDecimal getBigDecimalOrNull(String columnName);
|
||||
|
||||
|
||||
BigDecimal getBigDecimalOrZero();
|
||||
|
||||
|
||||
BigDecimal getBigDecimalOrZero(int columnOneBased);
|
||||
|
||||
|
||||
BigDecimal getBigDecimalOrZero(String columnName);
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null; never returns the empty string
|
||||
*/
|
||||
|
||||
String getStringOrNull();
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null; never returns the empty string
|
||||
*/
|
||||
|
||||
String getStringOrNull(int columnOneBased);
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null; never returns the empty string
|
||||
*/
|
||||
|
||||
String getStringOrNull(String columnName);
|
||||
|
||||
/**
|
||||
* @return the value, or the empty string if it is SQL null; never returns null
|
||||
*/
|
||||
|
||||
String getStringOrEmpty();
|
||||
|
||||
/**
|
||||
* @return the value, or the empty string if it is SQL null; never returns null
|
||||
*/
|
||||
|
||||
String getStringOrEmpty(int columnOneBased);
|
||||
|
||||
/**
|
||||
* @return the value, or the empty string if it is SQL null; never returns null
|
||||
*/
|
||||
|
||||
String getStringOrEmpty(String columnName);
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null; never returns the empty string
|
||||
*/
|
||||
|
||||
String getClobStringOrNull();
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null; never returns the empty string
|
||||
*/
|
||||
|
||||
String getClobStringOrNull(int columnOneBased);
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null; never returns the empty string
|
||||
*/
|
||||
|
||||
String getClobStringOrNull(String columnName);
|
||||
|
||||
/**
|
||||
* @return the value, or the empty string if it is SQL null; never returns null
|
||||
*/
|
||||
|
||||
String getClobStringOrEmpty();
|
||||
|
||||
/**
|
||||
* @return the value, or the empty string if it is SQL null; never returns null
|
||||
*/
|
||||
|
||||
String getClobStringOrEmpty(int columnOneBased);
|
||||
|
||||
/**
|
||||
* @return the value, or the empty string if it is SQL null; never returns null
|
||||
*/
|
||||
|
||||
String getClobStringOrEmpty(String columnName);
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null
|
||||
*/
|
||||
|
||||
Reader getClobReaderOrNull();
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null
|
||||
*/
|
||||
|
||||
Reader getClobReaderOrNull(int columnOneBased);
|
||||
|
||||
/**
|
||||
* @return the value, or null if it is SQL null
|
||||
*/
|
||||
|
||||
Reader getClobReaderOrNull(String columnName);
|
||||
|
||||
/**
|
||||
* @return the value, or a StringReader containing the empty string if it is SQL null
|
||||
*/
|
||||
|
||||
Reader getClobReaderOrEmpty();
|
||||
|
||||
/**
|
||||
* @return the value, or a StringReader containing the empty string if it is SQL null
|
||||
*/
|
||||
|
||||
Reader getClobReaderOrEmpty(int columnOneBased);
|
||||
|
||||
/**
|
||||
* @return the value, or a StringReader containing the empty string if it is SQL null
|
||||
*/
|
||||
|
||||
Reader getClobReaderOrEmpty(String columnName);
|
||||
|
||||
|
||||
byte[] getBlobBytesOrNull();
|
||||
|
||||
|
||||
byte[] getBlobBytesOrNull(int columnOneBased);
|
||||
|
||||
|
||||
byte[] getBlobBytesOrNull(String columnName);
|
||||
|
||||
|
||||
byte[] getBlobBytesOrZeroLen();
|
||||
|
||||
|
||||
byte[] getBlobBytesOrZeroLen(int columnOneBased);
|
||||
|
||||
|
||||
byte[] getBlobBytesOrZeroLen(String columnName);
|
||||
|
||||
|
||||
InputStream getBlobInputStreamOrNull();
|
||||
|
||||
|
||||
InputStream getBlobInputStreamOrNull(int columnOneBased);
|
||||
|
||||
|
||||
InputStream getBlobInputStreamOrNull(String columnName);
|
||||
|
||||
|
||||
InputStream getBlobInputStreamOrEmpty();
|
||||
|
||||
|
||||
InputStream getBlobInputStreamOrEmpty(int columnOneBased);
|
||||
|
||||
InputStream getBlobInputStreamOrEmpty(String columnName);
|
||||
|
@ -393,8 +359,12 @@ public interface Row {
|
|||
|
||||
LocalDateTime getLocalDateTimeOrNull(int columnOneBased);
|
||||
|
||||
LocalDateTime getLocalDateTimeOrNull(int columnOneBased, ZoneId zoneId);
|
||||
|
||||
LocalDateTime getLocalDateTimeOrNull(String columnName);
|
||||
|
||||
LocalDateTime getLocalDateTimeOrNull(String columnName, ZoneId zoneId);
|
||||
|
||||
/**
|
||||
* Retrieve column as LocalDate, .i.e, date with no time.
|
||||
*
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.sql.SQLException;
|
|||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
/**
|
||||
* Safely wrap a ResultSet and provide access to the data it contains.
|
||||
|
@ -38,7 +39,6 @@ class RowsAdaptor implements Rows {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getColumnLabels() {
|
||||
try {
|
||||
|
@ -666,7 +666,23 @@ class RowsAdaptor implements Rows {
|
|||
public LocalDateTime getLocalDateTimeOrNull(int columnOneBased) {
|
||||
try {
|
||||
column = columnOneBased + 1;
|
||||
return toLocalDateTime(rs, columnOneBased);
|
||||
return rs.getObject(columnOneBased, LocalDateTime.class);
|
||||
} catch (SQLException e) {
|
||||
throw new DatabaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
@ -676,7 +692,18 @@ class RowsAdaptor implements Rows {
|
|||
public LocalDateTime getLocalDateTimeOrNull(String columnName) {
|
||||
try {
|
||||
column = rs.findColumn(columnName) + 1;
|
||||
return toLocalDateTime(rs, columnName);
|
||||
return rs.getObject(columnName, LocalDateTime.class);
|
||||
} catch (SQLException e) {
|
||||
throw new DatabaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
@ -687,7 +714,6 @@ class RowsAdaptor implements Rows {
|
|||
return getLocalDateOrNull(column++);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LocalDate getLocalDateOrNull(int columnOneBased) {
|
||||
try {
|
||||
|
@ -698,7 +724,6 @@ class RowsAdaptor implements Rows {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LocalDate getLocalDateOrNull(String columnName) {
|
||||
try {
|
||||
|
@ -719,16 +744,6 @@ class RowsAdaptor implements Rows {
|
|||
}
|
||||
}
|
||||
|
||||
private LocalDateTime toLocalDateTime(ResultSet rs, int col) throws SQLException {
|
||||
Timestamp val = rs.getTimestamp(col, options.calendarForTimestamps());
|
||||
return val == null ? null : val.toLocalDateTime();
|
||||
}
|
||||
|
||||
private LocalDateTime toLocalDateTime(ResultSet rs, String col) throws SQLException {
|
||||
Timestamp val = rs.getTimestamp(col, options.calendarForTimestamps());
|
||||
return val == null ? null : val.toLocalDateTime();
|
||||
}
|
||||
|
||||
private LocalDate toLocalDate(ResultSet rs, int col) throws SQLException {
|
||||
java.sql.Date val = rs.getDate(col);
|
||||
return val == null ? null : val.toLocalDate();
|
||||
|
|
|
@ -5,5 +5,6 @@ package org.xbib.jdbc.query;
|
|||
*/
|
||||
@FunctionalInterface
|
||||
public interface RowsHandler<T> {
|
||||
|
||||
T process(Rows rs) throws Exception;
|
||||
}
|
||||
|
|
|
@ -76,17 +76,14 @@ public class Schema {
|
|||
Table table = addTable(tableName);
|
||||
try {
|
||||
ResultSetMetaData metadata = r.getMetadata();
|
||||
|
||||
int columnCount = metadata.getColumnCount();
|
||||
String[] names = new String[columnCount];
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
names[i] = metadata.getColumnName(i + 1);
|
||||
}
|
||||
names = SqlArgs.tidyColumnNames(names);
|
||||
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
int type = metadata.getColumnType(i + 1);
|
||||
|
||||
switch (type) {
|
||||
case Types.SMALLINT:
|
||||
case Types.INTEGER:
|
||||
|
@ -142,13 +139,14 @@ public class Schema {
|
|||
// This is the type dates and times with time and time zone associated.
|
||||
// Note that Oracle dates are always really Timestamps.
|
||||
case Types.TIMESTAMP:
|
||||
case Types.TIMESTAMP_WITH_TIMEZONE:
|
||||
// Check if we really have a LocalDate implemented by the DB as a timestamp
|
||||
if (metadata.getScale(i + 1) == 0) {
|
||||
// If the scale is 0, this is a LocalDate (no time/timezone).
|
||||
// Anything with a time/timezone will have a non-zero scale
|
||||
table.addColumn(names[i]).asLocalDate();
|
||||
} else {
|
||||
table.addColumn(names[i]).asDate();
|
||||
table.addColumn(names[i]).asLocalDateTime();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -229,8 +227,8 @@ public class Schema {
|
|||
case StringFixed:
|
||||
sql.append(flavor.typeStringFixed(column.scale));
|
||||
break;
|
||||
case Date:
|
||||
sql.append(flavor.typeDate()); // Append a date with time
|
||||
case LocalDateTime:
|
||||
sql.append(flavor.typeLocalDateTime()); // Append a date with time
|
||||
break;
|
||||
case LocalDate:
|
||||
sql.append(flavor.typeLocalDate()); // Append a true date - no time
|
||||
|
@ -400,7 +398,7 @@ public class Schema {
|
|||
}
|
||||
|
||||
public enum ColumnType {
|
||||
Integer, Long, Float, Double, BigDecimal, StringVar, StringFixed, Clob, Blob, Date, LocalDate, Boolean
|
||||
Integer, Long, Float, Double, BigDecimal, StringVar, StringFixed, Clob, Blob, LocalDateTime, LocalDate, Boolean
|
||||
}
|
||||
|
||||
public class Sequence {
|
||||
|
@ -525,13 +523,13 @@ public class Schema {
|
|||
|
||||
public Schema schema() {
|
||||
if (createTracking) {
|
||||
addColumn("create_time").asDate().table();
|
||||
addColumn("create_time").asLocalDateTime().table();
|
||||
}
|
||||
if (createTrackingFkName != null) {
|
||||
addColumn("create_user").foreignKey(createTrackingFkName).references(createTrackingFkTable).table();
|
||||
}
|
||||
if (updateTracking || updateSequence) {
|
||||
addColumn("update_time").asDate().table();
|
||||
addColumn("update_time").asLocalDateTime().table();
|
||||
}
|
||||
if (updateTrackingFkName != null) {
|
||||
addColumn("update_user").foreignKey(updateTrackingFkName).references(updateTrackingFkTable).table();
|
||||
|
@ -868,8 +866,8 @@ public class Schema {
|
|||
}
|
||||
|
||||
// This type is for dates that have time associated
|
||||
public Column asDate() {
|
||||
return asType(ColumnType.Date);
|
||||
public Column asLocalDateTime() {
|
||||
return asType(ColumnType.LocalDateTime);
|
||||
}
|
||||
|
||||
// This type is for true dates with no time associated
|
||||
|
|
|
@ -295,32 +295,22 @@ public class Sql implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Apply {
|
|||
}
|
||||
|
||||
public Sql argDate(LocalDateTime arg) {
|
||||
sqlArgs.argDate(arg);
|
||||
sqlArgs.argLocalDateTime(arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sql argDate(String argName, LocalDateTime arg) {
|
||||
sqlArgs.argDate(argName, arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sql argDateNowPerApp() {
|
||||
sqlArgs.argDateNowPerApp();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sql argDateNowPerApp(String argName) {
|
||||
sqlArgs.argDateNowPerApp(argName);
|
||||
sqlArgs.argLocalDateTime(argName, arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sql argDateNowPerDb() {
|
||||
sqlArgs.argDateNowPerDb();
|
||||
sqlArgs.argLocalDateTimeNowPerDb();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sql argDateNowPerDb(String argName) {
|
||||
sqlArgs.argDateNowPerDb(argName);
|
||||
sqlArgs.argLocalDateTimeNowPerDb(argName);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,61 +64,52 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
return uniqueNames.toArray(new String[uniqueNames.size()]);
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argBoolean(Boolean arg) {
|
||||
invocations.add(new Invocation(ColumnType.Boolean, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argBoolean( String argName, Boolean arg) {
|
||||
public SqlArgs argBoolean(String argName, Boolean arg) {
|
||||
invocations.add(new Invocation(ColumnType.Boolean, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argInteger(Integer arg) {
|
||||
invocations.add(new Invocation(ColumnType.Integer, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argInteger( String argName, Integer arg) {
|
||||
public SqlArgs argInteger(String argName, Integer arg) {
|
||||
invocations.add(new Invocation(ColumnType.Integer, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argLong(Long arg) {
|
||||
invocations.add(new Invocation(ColumnType.Long, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argLong( String argName, Long arg) {
|
||||
public SqlArgs argLong(String argName, Long arg) {
|
||||
invocations.add(new Invocation(ColumnType.Long, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argFloat(Float arg) {
|
||||
invocations.add(new Invocation(ColumnType.Float, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argFloat( String argName, Float arg) {
|
||||
public SqlArgs argFloat(String argName, Float arg) {
|
||||
invocations.add(new Invocation(ColumnType.Float, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argDouble(Double arg) {
|
||||
invocations.add(new Invocation(ColumnType.Double, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SqlArgs argDouble( String argName, Double arg) {
|
||||
public SqlArgs argDouble(String argName, Double arg) {
|
||||
invocations.add(new Invocation(ColumnType.Double, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
@ -128,7 +119,7 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
return this;
|
||||
}
|
||||
|
||||
public SqlArgs argBigDecimal( String argName, BigDecimal arg) {
|
||||
public SqlArgs argBigDecimal(String argName, BigDecimal arg) {
|
||||
invocations.add(new Invocation(ColumnType.BigDecimal, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
@ -138,110 +129,81 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
return this;
|
||||
}
|
||||
|
||||
public SqlArgs argString( String argName, String arg) {
|
||||
public SqlArgs argString(String argName, String arg) {
|
||||
invocations.add(new Invocation(ColumnType.String, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SqlArgs argDate(LocalDateTime arg) {
|
||||
// date argument with a time on it
|
||||
invocations.add(new Invocation(ColumnType.Date, null, arg));
|
||||
public SqlArgs argLocalDateTime(LocalDateTime arg) {
|
||||
invocations.add(new Invocation(ColumnType.LocalDateTime, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SqlArgs argDate( String argName, LocalDateTime arg) {
|
||||
// date argument with a time on it
|
||||
invocations.add(new Invocation(ColumnType.Date, argName, arg));
|
||||
public SqlArgs argLocalDateTime(String argName, LocalDateTime arg) {
|
||||
invocations.add(new Invocation(ColumnType.LocalDateTime, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argLocalDate(LocalDate arg) {
|
||||
// date argument with no time on it
|
||||
invocations.add(new Invocation(ColumnType.LocalDate, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argLocalDate( String argName, LocalDate arg) {
|
||||
// date argument with no time on it
|
||||
public SqlArgs argLocalDate(String argName, LocalDate arg) {
|
||||
invocations.add(new Invocation(ColumnType.LocalDate, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argDateNowPerApp() {
|
||||
invocations.add(new Invocation(ColumnType.DateNowPerApp, null, null));
|
||||
public SqlArgs argLocalDateTimeNowPerDb() {
|
||||
invocations.add(new Invocation(ColumnType.LocalDateTimeNowPerDb, null, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argDateNowPerApp( String argName) {
|
||||
invocations.add(new Invocation(ColumnType.DateNowPerApp, argName, null));
|
||||
public SqlArgs argLocalDateTimeNowPerDb(String argName) {
|
||||
invocations.add(new Invocation(ColumnType.LocalDateTimeNowPerDb, argName, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argDateNowPerDb() {
|
||||
invocations.add(new Invocation(ColumnType.DateNowPerDb, null, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argDateNowPerDb( String argName) {
|
||||
invocations.add(new Invocation(ColumnType.DateNowPerDb, argName, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argBlobBytes(byte[] arg) {
|
||||
invocations.add(new Invocation(ColumnType.BlobBytes, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argBlobBytes( String argName, byte[] arg) {
|
||||
public SqlArgs argBlobBytes(String argName, byte[] arg) {
|
||||
invocations.add(new Invocation(ColumnType.BlobBytes, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argBlobInputStream(InputStream arg) {
|
||||
invocations.add(new Invocation(ColumnType.BlobStream, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argBlobInputStream( String argName, InputStream arg) {
|
||||
public SqlArgs argBlobInputStream(String argName, InputStream arg) {
|
||||
invocations.add(new Invocation(ColumnType.BlobStream, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argClobString(String arg) {
|
||||
invocations.add(new Invocation(ColumnType.ClobString, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argClobString( String argName, String arg) {
|
||||
public SqlArgs argClobString(String argName, String arg) {
|
||||
invocations.add(new Invocation(ColumnType.ClobString, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argClobReader(Reader arg) {
|
||||
invocations.add(new Invocation(ColumnType.ClobStream, null, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs argClobReader( String argName, Reader arg) {
|
||||
public SqlArgs argClobReader(String argName, Reader arg) {
|
||||
invocations.add(new Invocation(ColumnType.ClobStream, argName, arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SqlArgs makePositional() {
|
||||
for (Invocation invocation : invocations) {
|
||||
invocation.argName = null;
|
||||
|
@ -249,7 +211,6 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
public List<String> names() {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (Invocation invocation : invocations) {
|
||||
|
@ -348,25 +309,18 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
select.argLocalDate(i.argName, (LocalDate) i.arg);
|
||||
}
|
||||
break;
|
||||
case Date:
|
||||
case LocalDateTime:
|
||||
if (i.argName == null) {
|
||||
select.argDate((LocalDateTime) i.arg);
|
||||
select.argLocalDateTime((LocalDateTime) i.arg);
|
||||
} else {
|
||||
select.argDate(i.argName, (LocalDateTime) i.arg);
|
||||
select.argLocalDateTime(i.argName, (LocalDateTime) i.arg);
|
||||
}
|
||||
break;
|
||||
case DateNowPerApp:
|
||||
case LocalDateTimeNowPerDb:
|
||||
if (i.argName == null) {
|
||||
select.argDateNowPerApp();
|
||||
select.argLocalDateTimeNowPerDb();
|
||||
} else {
|
||||
select.argDateNowPerApp(i.argName);
|
||||
}
|
||||
break;
|
||||
case DateNowPerDb:
|
||||
if (i.argName == null) {
|
||||
select.argDateNowPerDb();
|
||||
} else {
|
||||
select.argDateNowPerDb(i.argName);
|
||||
select.argLocalDateTimeNowPerDb(i.argName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -456,33 +410,24 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
}
|
||||
break;
|
||||
case LocalDate:
|
||||
// date argument with no time on it
|
||||
if (i.argName == null) {
|
||||
insert.argLocalDate((LocalDate) i.arg);
|
||||
} else {
|
||||
insert.argLocalDate(i.argName, (LocalDate) i.arg);
|
||||
}
|
||||
break;
|
||||
case Date:
|
||||
// date argument with a time on it
|
||||
case LocalDateTime:
|
||||
if (i.argName == null) {
|
||||
insert.argDate((LocalDateTime) i.arg);
|
||||
insert.argLocalDateTime((LocalDateTime) i.arg);
|
||||
} else {
|
||||
insert.argDate(i.argName, (LocalDateTime) i.arg);
|
||||
insert.argLocalDateTime(i.argName, (LocalDateTime) i.arg);
|
||||
}
|
||||
break;
|
||||
case DateNowPerApp:
|
||||
case LocalDateTimeNowPerDb:
|
||||
if (i.argName == null) {
|
||||
insert.argDateNowPerApp();
|
||||
insert.argLocalDateTimeNowPerDb();
|
||||
} else {
|
||||
insert.argDateNowPerApp(i.argName);
|
||||
}
|
||||
break;
|
||||
case DateNowPerDb:
|
||||
if (i.argName == null) {
|
||||
insert.argDateNowPerDb();
|
||||
} else {
|
||||
insert.argDateNowPerDb(i.argName);
|
||||
insert.argLocalDateTimeNowPerDb(i.argName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -578,25 +523,18 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
update.argLocalDate(i.argName, (LocalDate) i.arg);
|
||||
}
|
||||
break;
|
||||
case Date:
|
||||
case LocalDateTime:
|
||||
if (i.argName == null) {
|
||||
update.argDate((LocalDateTime) i.arg);
|
||||
update.argLocalDateTime((LocalDateTime) i.arg);
|
||||
} else {
|
||||
update.argDate(i.argName, (LocalDateTime) i.arg);
|
||||
update.argLocalDateTime(i.argName, (LocalDateTime) i.arg);
|
||||
}
|
||||
break;
|
||||
case DateNowPerApp:
|
||||
case LocalDateTimeNowPerDb:
|
||||
if (i.argName == null) {
|
||||
update.argDateNowPerApp();
|
||||
update.argLocalDateTimeNowPerDb();
|
||||
} else {
|
||||
update.argDateNowPerApp(i.argName);
|
||||
}
|
||||
break;
|
||||
case DateNowPerDb:
|
||||
if (i.argName == null) {
|
||||
update.argDateNowPerDb();
|
||||
} else {
|
||||
update.argDateNowPerDb(i.argName);
|
||||
update.argLocalDateTimeNowPerDb(i.argName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -622,14 +560,29 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
}
|
||||
|
||||
public enum ColumnType {
|
||||
Integer, Long, Float, Double, BigDecimal, String, ClobString, ClobStream,
|
||||
BlobBytes, BlobStream, Date, LocalDate, DateNowPerApp, DateNowPerDb, Boolean
|
||||
String,
|
||||
Boolean,
|
||||
Integer,
|
||||
Long,
|
||||
Float,
|
||||
Double,
|
||||
BigDecimal,
|
||||
ClobString,
|
||||
ClobStream,
|
||||
BlobBytes,
|
||||
BlobStream,
|
||||
LocalDate,
|
||||
LocalDateTime,
|
||||
LocalDateTimeNowPerDb
|
||||
}
|
||||
|
||||
private static class Invocation {
|
||||
ColumnType columnType;
|
||||
String argName;
|
||||
Object arg;
|
||||
|
||||
private final ColumnType columnType;
|
||||
|
||||
private String argName;
|
||||
|
||||
private final Object arg;
|
||||
|
||||
Invocation(ColumnType columnType, String argName, Object arg) {
|
||||
this.columnType = columnType;
|
||||
|
@ -639,8 +592,12 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Invocation that = (Invocation) o;
|
||||
return columnType == that.columnType &&
|
||||
Objects.equals(argName, that.argName) &&
|
||||
|
@ -659,9 +616,13 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final int[] types;
|
||||
|
||||
private final int[] precision;
|
||||
|
||||
private final int[] scale;
|
||||
|
||||
private String[] names;
|
||||
|
||||
public Builder(Row r) {
|
||||
|
@ -672,14 +633,12 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
types = new int[columnCount];
|
||||
precision = new int[columnCount];
|
||||
scale = new int[columnCount];
|
||||
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
names[i] = metadata.getColumnLabel(i + 1);
|
||||
types[i] = metadata.getColumnType(i + 1);
|
||||
precision[i] = metadata.getPrecision(i + 1);
|
||||
scale[i] = metadata.getScale(i + 1);
|
||||
}
|
||||
|
||||
names = tidyColumnNames(names);
|
||||
} catch (SQLException e) {
|
||||
throw new DatabaseException("Unable to retrieve metadata from ResultSet", e);
|
||||
|
@ -727,22 +686,19 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
case Types.NCLOB:
|
||||
args.argClobString(names[i], r.getClobStringOrNull());
|
||||
break;
|
||||
|
||||
// Check Date before TimeStamp because SQL dates are also timestamps
|
||||
case Types.DATE:
|
||||
args.argLocalDate(names[i], r.getLocalDateOrNull());
|
||||
break;
|
||||
|
||||
case Types.TIMESTAMP:
|
||||
case Types.TIMESTAMP_WITH_TIMEZONE:
|
||||
if (this.scale[i] == 0) {
|
||||
// If the scale is 0, this is a LocalDate (no time/timezone).
|
||||
// Anything with a time will have a non-zero scale
|
||||
args.argLocalDate(names[i], r.getLocalDateOrNull());
|
||||
} else {
|
||||
args.argDate(names[i], r.getLocalDateTimeOrNull());
|
||||
args.argLocalDateTime(names[i], r.getLocalDateTimeOrNull());
|
||||
}
|
||||
break;
|
||||
|
||||
case Types.NVARCHAR:
|
||||
case Types.VARCHAR:
|
||||
case Types.CHAR:
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.io.Reader;
|
|||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
/**
|
||||
* Interface for configuring (setting parameters) and executing a chunk of SQL.
|
||||
|
@ -39,21 +40,19 @@ public interface SqlInsert {
|
|||
|
||||
SqlInsert argString( String argName, String arg);
|
||||
|
||||
SqlInsert argDate(LocalDateTime arg); // date with time
|
||||
SqlInsert argLocalDateTime(LocalDateTime arg);
|
||||
|
||||
SqlInsert argDate(String argName, LocalDateTime arg); // date with time
|
||||
SqlInsert argLocalDateTime(LocalDateTime arg, ZoneId zoneId);
|
||||
|
||||
SqlInsert argLocalDate(LocalDate arg); // date only - no timestamp
|
||||
SqlInsert argLocalDateTime(String argName, LocalDateTime arg);
|
||||
|
||||
SqlInsert argLocalDate( String argName, LocalDate arg); // date only - no timestamp
|
||||
SqlInsert argLocalDate(LocalDate arg);
|
||||
|
||||
SqlInsert argDateNowPerApp();
|
||||
SqlInsert argLocalDate( String argName, LocalDate arg);
|
||||
|
||||
SqlInsert argDateNowPerApp(String argName);
|
||||
SqlInsert argLocalDateTimeNowPerDb();
|
||||
|
||||
SqlInsert argDateNowPerDb();
|
||||
|
||||
SqlInsert argDateNowPerDb(String argName);
|
||||
SqlInsert argLocalDateTimeNowPerDb(String argName);
|
||||
|
||||
SqlInsert argBlobBytes(byte[] arg);
|
||||
|
||||
|
@ -126,7 +125,6 @@ public interface SqlInsert {
|
|||
* <p>This version of insert expects exactly one row to be inserted, and will throw
|
||||
* a DatabaseException if that isn't the case.</p>
|
||||
*/
|
||||
|
||||
Long insertReturningPkSeq(String primaryKeyColumnName);
|
||||
|
||||
<T> T insertReturning(String tableName, String primaryKeyColumnName, RowsHandler<T> rowsHandler,
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.Statement;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -40,9 +41,9 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
|
||||
private List<Batch> batched;
|
||||
|
||||
private List<Object> parameterList; // !null ==> traditional ? args
|
||||
private List<Object> parameterList;
|
||||
|
||||
private Map<String, Object> parameterMap; // !null ==> named :abc args
|
||||
private Map<String, Object> parameterMap;
|
||||
|
||||
private String pkArgName;
|
||||
|
||||
|
@ -141,13 +142,18 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argDate(LocalDateTime arg) {
|
||||
return positionalArg(adaptor.nullDate(arg));
|
||||
public SqlInsert argLocalDateTime(LocalDateTime arg) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argDate( String argName, LocalDateTime arg) {
|
||||
return namedArg(argName, adaptor.nullDate(arg));
|
||||
public SqlInsert argLocalDateTime(LocalDateTime arg, ZoneId zoneId) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(arg, zoneId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argLocalDateTime(String argName, LocalDateTime arg) {
|
||||
return namedArg(argName, adaptor.nullLocalDateTime(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -161,27 +167,17 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argDateNowPerApp() {
|
||||
return positionalArg(adaptor.nullDate(options.currentDate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argDateNowPerApp( String argName) {
|
||||
return namedArg(argName, adaptor.nullDate(options.currentDate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argDateNowPerDb() {
|
||||
if (options.useDatePerAppOnly()) {
|
||||
return positionalArg(adaptor.nullDate(options.currentDate()));
|
||||
public SqlInsert argLocalDateTimeNowPerDb() {
|
||||
if (options.useLocalDateTimeOnly()) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||
}
|
||||
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlInsert argDateNowPerDb( String argName) {
|
||||
if (options.useDatePerAppOnly()) {
|
||||
return namedArg(argName, adaptor.nullDate(options.currentDate()));
|
||||
public SqlInsert argLocalDateTimeNowPerDb(String argName) {
|
||||
if (options.useLocalDateTimeOnly()) {
|
||||
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||
}
|
||||
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||
}
|
||||
|
@ -236,7 +232,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
return apply(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlInsert apply(Apply apply) {
|
||||
apply.apply(this);
|
||||
|
@ -312,7 +307,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
if (!hasPk()) {
|
||||
throw new DatabaseException("Identify a primary key with argPk*() before insertReturning()");
|
||||
}
|
||||
|
||||
if (options.flavor().supportsInsertReturning()) {
|
||||
return updateInternal(1, primaryKeyColumnName, handler, otherColumnNames);
|
||||
} else if (pkSeqName != null) {
|
||||
|
@ -367,7 +361,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlInsert argPkSeq( String argName, String sequenceName) {
|
||||
if (hasPk() && batched == null) {
|
||||
throw new DatabaseException("Only call one argPk*() method");
|
||||
|
@ -381,7 +374,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlInsert argPkLong(String argName, Long arg) {
|
||||
if (hasPk() && batched == null) {
|
||||
throw new DatabaseException("Only call one argPk*() method");
|
||||
|
@ -395,7 +387,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlInsert argPkLong(Long arg) {
|
||||
if (hasPk() && batched == null) {
|
||||
throw new DatabaseException("Only call one argPk*() method");
|
||||
|
@ -415,18 +406,14 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
|
||||
private int[] insertBatchInternal() {
|
||||
batch();
|
||||
|
||||
if (batched == null || batched.size() == 0) {
|
||||
throw new DatabaseException("Batch insert requires parameters");
|
||||
}
|
||||
|
||||
PreparedStatement ps = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
|
||||
String executeSql = sql;
|
||||
Object[] firstRowParameters = null;
|
||||
List<Object[]> parameters = new ArrayList<>();
|
||||
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
Exception logEx = null;
|
||||
|
@ -444,7 +431,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
parameters.add(mpSql.getArgs());
|
||||
}
|
||||
|
||||
if (connection != null) {
|
||||
ps = connection.prepareStatement(executeSql);
|
||||
|
||||
|
@ -452,7 +438,6 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
adaptor.addParameters(ps, params);
|
||||
ps.addBatch();
|
||||
}
|
||||
|
||||
metric.checkpoint("prep");
|
||||
int[] numAffectedRows = ps.executeBatch();
|
||||
metric.checkpoint("execBatch", parameters.size());
|
||||
|
@ -482,13 +467,10 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
if (batched != null) {
|
||||
throw new DatabaseException("Call insertBatch() if you are using the batch() feature");
|
||||
}
|
||||
|
||||
PreparedStatement ps = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
|
||||
String executeSql = sql;
|
||||
Object[] parameters = null;
|
||||
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
Exception logEx = null;
|
||||
|
@ -496,10 +478,8 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
MixedParameterSql mpSql = new MixedParameterSql(sql, parameterList, parameterMap);
|
||||
executeSql = mpSql.getSqlToExecute();
|
||||
parameters = mpSql.getArgs();
|
||||
|
||||
if (connection != null) {
|
||||
ps = connection.prepareStatement(executeSql);
|
||||
|
||||
adaptor.addParameters(ps, parameters);
|
||||
metric.checkpoint("prep");
|
||||
int numAffectedRows = ps.executeUpdate();
|
||||
|
@ -536,14 +516,11 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
if (batched != null) {
|
||||
throw new DatabaseException("Call insertBatch() if you are using the batch() feature");
|
||||
}
|
||||
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
|
||||
String executeSql = sql;
|
||||
Object[] parameters = null;
|
||||
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
Exception logEx = null;
|
||||
|
@ -551,10 +528,8 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
MixedParameterSql mpSql = new MixedParameterSql(sql, parameterList, parameterMap);
|
||||
executeSql = mpSql.getSqlToExecute();
|
||||
parameters = mpSql.getArgs();
|
||||
|
||||
if (connection != null) {
|
||||
ps = connection.prepareStatement(executeSql, new String[]{pkToReturn});
|
||||
|
||||
adaptor.addParameters(ps, parameters);
|
||||
metric.checkpoint("prep");
|
||||
int numAffectedRows = ps.executeUpdate();
|
||||
|
@ -598,14 +573,11 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
if (batched != null) {
|
||||
throw new DatabaseException("Call insertBatch() if you are using the batch() feature");
|
||||
}
|
||||
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
|
||||
String executeSql = sql;
|
||||
Object[] parameters = null;
|
||||
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
Exception logEx = null;
|
||||
|
@ -613,14 +585,11 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
MixedParameterSql mpSql = new MixedParameterSql(sql, parameterList, parameterMap);
|
||||
executeSql = mpSql.getSqlToExecute();
|
||||
parameters = mpSql.getArgs();
|
||||
|
||||
String[] returnCols = new String[otherCols.length + 1];
|
||||
returnCols[0] = pkToReturn;
|
||||
System.arraycopy(otherCols, 0, returnCols, 1, otherCols.length);
|
||||
|
||||
if (connection != null) {
|
||||
ps = connection.prepareStatement(executeSql, returnCols);
|
||||
|
||||
adaptor.addParameters(ps, parameters);
|
||||
metric.checkpoint("prep");
|
||||
int numAffectedRows = ps.executeUpdate();
|
||||
|
@ -682,8 +651,8 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
}
|
||||
|
||||
private static class Batch {
|
||||
private final List<Object> parameterList; // !null ==> traditional ? args
|
||||
private final Map<String, Object> parameterMap; // !null ==> named :abc args
|
||||
private final List<Object> parameterList;
|
||||
private final Map<String, Object> parameterMap;
|
||||
|
||||
public Batch(List<Object> parameterList, Map<String, Object> parameterMap) {
|
||||
this.parameterList = parameterList;
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.xbib.jdbc.query;
|
|||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -10,126 +11,64 @@ import java.util.List;
|
|||
*/
|
||||
public interface SqlSelect {
|
||||
|
||||
|
||||
SqlSelect argBoolean(Boolean arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argBoolean( String argName, Boolean arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argInteger(Integer arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argInteger( String argName, Integer arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argLong(Long arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argLong( String argName, Long arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argFloat(Float arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argFloat( String argName, Float arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argDouble(Double arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argDouble( String argName, Double arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argBigDecimal(BigDecimal arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argBigDecimal( String argName, BigDecimal arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argString(String arg);
|
||||
|
||||
|
||||
|
||||
SqlSelect argString( String argName, String arg);
|
||||
|
||||
SqlSelect argLocalDateTime(LocalDateTime arg);
|
||||
|
||||
SqlSelect argLocalDateTime(String argName, LocalDateTime arg);
|
||||
|
||||
SqlSelect argDate(LocalDateTime arg); // Date with time
|
||||
SqlSelect argLocalDate(LocalDate arg);
|
||||
|
||||
SqlSelect argDate(String argName, LocalDateTime arg); // Date with time
|
||||
|
||||
|
||||
|
||||
SqlSelect argLocalDate(LocalDate arg); // Date without time
|
||||
|
||||
|
||||
|
||||
SqlSelect argLocalDate( String argName, LocalDate arg); // Date without time
|
||||
|
||||
|
||||
|
||||
SqlSelect argDateNowPerApp();
|
||||
|
||||
|
||||
|
||||
SqlSelect argDateNowPerApp( String argName);
|
||||
|
||||
|
||||
|
||||
SqlSelect argDateNowPerDb();
|
||||
|
||||
|
||||
|
||||
SqlSelect argDateNowPerDb( String argName);
|
||||
SqlSelect argLocalDate( String argName, LocalDate arg);
|
||||
|
||||
SqlSelect argLocalDateTimeNowPerDb();
|
||||
|
||||
SqlSelect argLocalDateTimeNowPerDb(String argName);
|
||||
|
||||
SqlSelect withTimeoutSeconds(int seconds);
|
||||
|
||||
|
||||
|
||||
SqlSelect withMaxRows(int rows);
|
||||
|
||||
|
||||
|
||||
SqlSelect withArgs(SqlArgs args);
|
||||
|
||||
|
||||
|
||||
SqlSelect apply(Apply apply);
|
||||
|
||||
|
||||
|
||||
SqlSelect fetchSize(int fetchSize);
|
||||
|
||||
|
||||
|
||||
Boolean queryBooleanOrNull();
|
||||
|
||||
|
||||
boolean queryBooleanOrFalse();
|
||||
|
||||
|
||||
boolean queryBooleanOrTrue();
|
||||
|
||||
|
||||
|
||||
Long queryLongOrNull();
|
||||
|
||||
|
||||
long queryLongOrZero();
|
||||
|
||||
/**
|
||||
|
@ -137,61 +76,34 @@ public interface SqlSelect {
|
|||
*
|
||||
* @return the first column values, omitting any that were null
|
||||
*/
|
||||
|
||||
|
||||
List<Long> queryLongs();
|
||||
|
||||
|
||||
|
||||
Integer queryIntegerOrNull();
|
||||
|
||||
|
||||
int queryIntegerOrZero();
|
||||
|
||||
|
||||
|
||||
List<Integer> queryIntegers();
|
||||
|
||||
|
||||
|
||||
Float queryFloatOrNull();
|
||||
|
||||
|
||||
float queryFloatOrZero();
|
||||
|
||||
|
||||
|
||||
List<Float> queryFloats();
|
||||
|
||||
|
||||
|
||||
Double queryDoubleOrNull();
|
||||
|
||||
|
||||
double queryDoubleOrZero();
|
||||
|
||||
|
||||
|
||||
List<Double> queryDoubles();
|
||||
|
||||
|
||||
|
||||
BigDecimal queryBigDecimalOrNull();
|
||||
|
||||
|
||||
|
||||
BigDecimal queryBigDecimalOrZero();
|
||||
|
||||
|
||||
|
||||
List<BigDecimal> queryBigDecimals();
|
||||
|
||||
|
||||
|
||||
String queryStringOrNull();
|
||||
|
||||
|
||||
|
||||
String queryStringOrEmpty();
|
||||
|
||||
/**
|
||||
|
@ -199,25 +111,19 @@ public interface SqlSelect {
|
|||
*
|
||||
* @return the first column values, omitting any that were null
|
||||
*/
|
||||
|
||||
|
||||
List<String> queryStrings();
|
||||
|
||||
LocalDateTime queryLocalDateTimeOrNull();
|
||||
|
||||
LocalDateTime queryLocalDateTimeOrNull(ZoneId zoneId);
|
||||
|
||||
LocalDateTime queryDateOrNull(); // Date with time
|
||||
List<LocalDateTime> queryLocalDateTimes();
|
||||
|
||||
List<LocalDateTime> queryLocalDateTimes(ZoneId zoneId);
|
||||
|
||||
LocalDate queryLocalDateOrNull();
|
||||
|
||||
List<LocalDateTime> queryDates(); // Date with time
|
||||
|
||||
|
||||
|
||||
LocalDate queryLocalDateOrNull(); // Date without time
|
||||
|
||||
|
||||
|
||||
List<LocalDate> queryLocalDates(); // Date without time
|
||||
List<LocalDate> queryLocalDates();
|
||||
|
||||
/**
|
||||
* This is the most generic and low-level way to iterate the query results.
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -23,7 +24,7 @@ import java.util.logging.Logger;
|
|||
*/
|
||||
public class SqlSelectImpl implements SqlSelect {
|
||||
|
||||
private static final Logger log = Logger.getLogger(Database.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(Database.class.getName());
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
|
@ -114,116 +115,85 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argBigDecimal(BigDecimal arg) {
|
||||
return positionalArg(adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argBigDecimal( String argName, BigDecimal arg) {
|
||||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argString(String arg) {
|
||||
return positionalArg(adaptor.nullString(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argString( String argName, String arg) {
|
||||
public SqlSelect argString(String argName, String arg) {
|
||||
return namedArg(argName, adaptor.nullString(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argDate(LocalDateTime arg) {
|
||||
// Date with time
|
||||
return positionalArg(adaptor.nullDate(arg));
|
||||
public SqlSelect argLocalDateTime(LocalDateTime arg) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argDate( String argName, LocalDateTime arg) {
|
||||
// Date with time
|
||||
return namedArg(argName, adaptor.nullDate(arg));
|
||||
public SqlSelect argLocalDateTime(String argName, LocalDateTime arg) {
|
||||
return namedArg(argName, adaptor.nullLocalDateTime(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argLocalDate(LocalDate arg) {
|
||||
// Date with no time
|
||||
return positionalArg(adaptor.nullLocalDate(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argLocalDate( String argName, LocalDate arg) {
|
||||
// Date with no time
|
||||
return namedArg(argName, adaptor.nullLocalDate(arg));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argDateNowPerApp() {
|
||||
return positionalArg(adaptor.nullDate(options.currentDate()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argDateNowPerApp( String argName) {
|
||||
return namedArg(argName, adaptor.nullDate(options.currentDate()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argDateNowPerDb() {
|
||||
if (options.useDatePerAppOnly()) {
|
||||
return positionalArg(adaptor.nullDate(options.currentDate()));
|
||||
public SqlSelect argLocalDateTimeNowPerDb() {
|
||||
if (options.useLocalDateTimeOnly()) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||
}
|
||||
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect argDateNowPerDb( String argName) {
|
||||
if (options.useDatePerAppOnly()) {
|
||||
return namedArg(argName, adaptor.nullDate(options.currentDate()));
|
||||
public SqlSelect argLocalDateTimeNowPerDb(String argName) {
|
||||
if (options.useLocalDateTimeOnly()) {
|
||||
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||
}
|
||||
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect withTimeoutSeconds(int seconds) {
|
||||
timeoutSeconds = seconds;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect withMaxRows(int rows) {
|
||||
maxRows = rows;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect withArgs(SqlArgs args) {
|
||||
return apply(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect apply(Apply apply) {
|
||||
apply.apply(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlSelect fetchSize(int rows) {
|
||||
fetchSize = rows;
|
||||
|
@ -253,7 +223,6 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Long queryLongOrNull() {
|
||||
return queryWithTimeout(rs -> {
|
||||
if (rs.next()) {
|
||||
|
@ -288,7 +257,6 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Integer queryIntegerOrNull() {
|
||||
return queryWithTimeout(rs -> {
|
||||
|
@ -324,7 +292,6 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Float queryFloatOrNull() {
|
||||
return queryWithTimeout(rs -> {
|
||||
|
@ -405,7 +372,6 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BigDecimal queryBigDecimalOrZero() {
|
||||
return queryWithTimeout(rs -> {
|
||||
|
@ -416,7 +382,6 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<BigDecimal> queryBigDecimals() {
|
||||
return queryWithTimeout(rs -> {
|
||||
|
@ -441,7 +406,6 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String queryStringOrEmpty() {
|
||||
return queryWithTimeout(rs -> {
|
||||
|
@ -467,21 +431,31 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime queryDateOrNull() {
|
||||
public LocalDateTime queryLocalDateTimeOrNull() {
|
||||
return queryLocalDateTimeOrNull(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime queryLocalDateTimeOrNull(ZoneId zoneId) {
|
||||
return queryWithTimeout(rs -> {
|
||||
if (rs.next()) {
|
||||
return rs.getLocalDateTimeOrNull(1);
|
||||
return rs.getLocalDateTimeOrNull(1, zoneId);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LocalDateTime> queryDates() {
|
||||
public List<LocalDateTime> queryLocalDateTimes() {
|
||||
return queryLocalDateTimes(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LocalDateTime> queryLocalDateTimes(ZoneId zoneId) {
|
||||
return queryWithTimeout(rs -> {
|
||||
List<LocalDateTime> result = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
LocalDateTime value = rs.getLocalDateTimeOrNull(1);
|
||||
LocalDateTime value = rs.getLocalDateTimeOrNull(1, zoneId);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
|
@ -603,11 +577,9 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
private <T> T queryWithTimeout(RowsHandler<T> handler) {
|
||||
assert ps == null;
|
||||
ResultSet rs = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
|
||||
Metric metric = new Metric(logger.isLoggable(Level.FINE));
|
||||
String executeSql = sql;
|
||||
Object[] parameters = null;
|
||||
|
||||
boolean isWarn = false;
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
|
@ -616,26 +588,21 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
MixedParameterSql mpSql = new MixedParameterSql(sql, parameterList, parameterMap);
|
||||
executeSql = mpSql.getSqlToExecute();
|
||||
parameters = mpSql.getArgs();
|
||||
|
||||
if (connection != null) {
|
||||
synchronized (cancelLock) {
|
||||
ps = connection.prepareStatement(executeSql,
|
||||
ResultSet.TYPE_SCROLL_INSENSITIVE,
|
||||
ResultSet.CONCUR_READ_ONLY);
|
||||
}
|
||||
|
||||
if (timeoutSeconds >= 0) {
|
||||
ps.setQueryTimeout(timeoutSeconds);
|
||||
}
|
||||
|
||||
if (maxRows > 0) {
|
||||
ps.setMaxRows(maxRows);
|
||||
}
|
||||
|
||||
if (fetchSize >= 0) {
|
||||
ps.setFetchSize(fetchSize);
|
||||
}
|
||||
|
||||
adaptor.addParameters(ps, parameters);
|
||||
metric.checkpoint("prep");
|
||||
rs = ps.executeQuery();
|
||||
|
@ -662,18 +629,18 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
logEx = e;
|
||||
throw DatabaseException.wrap(DebugSql.exceptionMessage(executeSql, parameters, errorCode, options), e);
|
||||
} finally {
|
||||
adaptor.closeQuietly(rs, log);
|
||||
adaptor.closeQuietly(ps, log);
|
||||
adaptor.closeQuietly(rs, logger);
|
||||
adaptor.closeQuietly(ps, logger);
|
||||
synchronized (cancelLock) {
|
||||
ps = null;
|
||||
}
|
||||
metric.done("close");
|
||||
if (isSuccess) {
|
||||
DebugSql.logSuccess("Query", log, metric, executeSql, parameters, options);
|
||||
DebugSql.logSuccess("Query", logger, metric, executeSql, parameters, options);
|
||||
} else if (isWarn) {
|
||||
DebugSql.logWarning("Query", log, metric, "QueryTimedOutException", executeSql, parameters, options, null);
|
||||
DebugSql.logWarning("Query", logger, metric, "QueryTimedOutException", executeSql, parameters, options, null);
|
||||
} else {
|
||||
DebugSql.logError("Query", log, metric, errorCode, executeSql, parameters, options, logEx);
|
||||
DebugSql.logError("Query", logger, metric, errorCode, executeSql, parameters, options, logEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,21 +39,17 @@ public interface SqlUpdate {
|
|||
|
||||
SqlUpdate argString(String argName, String arg);
|
||||
|
||||
SqlUpdate argDate(LocalDateTime arg);
|
||||
SqlUpdate argLocalDateTime(LocalDateTime arg);
|
||||
|
||||
SqlUpdate argDate(String argName, LocalDateTime arg);
|
||||
SqlUpdate argLocalDateTime(String argName, LocalDateTime arg);
|
||||
|
||||
SqlUpdate argLocalDate(LocalDate arg);
|
||||
|
||||
SqlUpdate argLocalDate(String argName, LocalDate arg);
|
||||
|
||||
SqlUpdate argDateNowPerApp();
|
||||
SqlUpdate argLocalDateTimeNowPerDb();
|
||||
|
||||
SqlUpdate argDateNowPerApp(String argName);
|
||||
|
||||
SqlUpdate argDateNowPerDb();
|
||||
|
||||
SqlUpdate argDateNowPerDb(String argName);
|
||||
SqlUpdate argLocalDateTimeNowPerDb(String argName);
|
||||
|
||||
SqlUpdate argBlobBytes(byte[] arg);
|
||||
|
||||
|
|
|
@ -50,186 +50,148 @@ public class SqlUpdateImpl implements SqlUpdate {
|
|||
adaptor = new StatementAdaptor(options);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlUpdate argBoolean(Boolean arg) {
|
||||
return positionalArg(adaptor.nullString(booleanToString(arg)));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlUpdate argBoolean(String argName, Boolean arg) {
|
||||
return namedArg(argName, adaptor.nullString(booleanToString(arg)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argInteger(Integer arg) {
|
||||
return positionalArg(adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argInteger(String argName, Integer arg) {
|
||||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argLong(Long arg) {
|
||||
return positionalArg(adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argLong(String argName, Long arg) {
|
||||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argFloat(Float arg) {
|
||||
return positionalArg(adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argFloat(String argName, Float arg) {
|
||||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argDouble(Double arg) {
|
||||
return positionalArg(adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argDouble(String argName, Double arg) {
|
||||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argBigDecimal(BigDecimal arg) {
|
||||
return positionalArg(adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argBigDecimal(String argName, BigDecimal arg) {
|
||||
return namedArg(argName, adaptor.nullNumeric(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argString(String arg) {
|
||||
return positionalArg(adaptor.nullString(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argString(String argName, String arg) {
|
||||
return namedArg(argName, adaptor.nullString(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argDate(LocalDateTime arg) {
|
||||
return positionalArg(adaptor.nullDate(arg));
|
||||
public SqlUpdate argLocalDateTime(LocalDateTime arg) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argDate(String argName, LocalDateTime arg) {
|
||||
return namedArg(argName, adaptor.nullDate(arg));
|
||||
public SqlUpdate argLocalDateTime(String argName, LocalDateTime arg) {
|
||||
return namedArg(argName, adaptor.nullLocalDateTime(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argLocalDate(LocalDate arg) {
|
||||
return positionalArg(adaptor.nullLocalDate(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argLocalDate(String argName, LocalDate arg) {
|
||||
return namedArg(argName, adaptor.nullLocalDate(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate argDateNowPerApp() {
|
||||
return positionalArg(adaptor.nullDate(options.currentDate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argDateNowPerApp(String argName) {
|
||||
return namedArg(argName, adaptor.nullDate(options.currentDate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate argDateNowPerDb() {
|
||||
if (options.useDatePerAppOnly()) {
|
||||
return positionalArg(adaptor.nullDate(options.currentDate()));
|
||||
public SqlUpdate argLocalDateTimeNowPerDb() {
|
||||
if (options.useLocalDateTimeOnly()) {
|
||||
return positionalArg(adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||
}
|
||||
return positionalArg(new RewriteArg(options.flavor().dbTimeMillis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argDateNowPerDb(String argName) {
|
||||
if (options.useDatePerAppOnly()) {
|
||||
return namedArg(argName, adaptor.nullDate(options.currentDate()));
|
||||
public SqlUpdate argLocalDateTimeNowPerDb(String argName) {
|
||||
if (options.useLocalDateTimeOnly()) {
|
||||
return namedArg(argName, adaptor.nullLocalDateTime(LocalDateTime.now()));
|
||||
}
|
||||
return namedArg(argName, new RewriteArg(options.flavor().dbTimeMillis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argBlobBytes(byte[] arg) {
|
||||
return positionalArg(adaptor.nullBytes(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argBlobBytes(String argName, byte[] arg) {
|
||||
return namedArg(argName, adaptor.nullBytes(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argBlobStream(InputStream arg) {
|
||||
return positionalArg(adaptor.nullInputStream(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argBlobStream(String argName, InputStream arg) {
|
||||
return namedArg(argName, adaptor.nullInputStream(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argClobString(String arg) {
|
||||
return positionalArg(adaptor.nullClobReader(arg == null ? null : new InternalStringReader(arg)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argClobString(String argName, String arg) {
|
||||
return namedArg(argName, adaptor.nullClobReader(arg == null ? null : new InternalStringReader(arg)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argClobReader(Reader arg) {
|
||||
return positionalArg(adaptor.nullClobReader(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SqlUpdate argClobReader(String argName, Reader arg) {
|
||||
return namedArg(argName, adaptor.nullClobReader(arg));
|
||||
}
|
||||
|
@ -244,7 +206,6 @@ public class SqlUpdateImpl implements SqlUpdate {
|
|||
return apply(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqlUpdate apply(Apply apply) {
|
||||
apply.apply(this);
|
||||
|
@ -419,8 +380,8 @@ public class SqlUpdateImpl implements SqlUpdate {
|
|||
}
|
||||
|
||||
private static class Batch {
|
||||
private final List<Object> parameterList; // !null ==> traditional ? args
|
||||
private final Map<String, Object> parameterMap; // !null ==> named :abc args
|
||||
private final List<Object> parameterList;
|
||||
private final Map<String, Object> parameterMap;
|
||||
|
||||
public Batch(List<Object> parameterList, Map<String, Object> parameterMap) {
|
||||
this.parameterList = parameterList;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
@ -13,75 +13,32 @@ import java.sql.Timestamp;
|
|||
import java.sql.Types;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Date;
|
||||
import java.util.Scanner;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Deal with mapping parameters into prepared statements.
|
||||
*/
|
||||
public class StatementAdaptor {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(StatementAdaptor.class.getName());
|
||||
|
||||
private final Options options;
|
||||
|
||||
public StatementAdaptor(Options options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
private static String readerToString(Reader r) {
|
||||
Scanner s = new Scanner(r).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
private static byte[] streamToBytes(InputStream is) throws SQLException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
|
||||
try {
|
||||
while ((length = is.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, length);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new SQLException("Unable to convert InputStream parameter to bytes", e);
|
||||
}
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the java.util.Date into a java.sql.Timestamp, following the nanos/millis canonicalization
|
||||
* required by the spec. If a java.sql.Timestamp is passed in (since it extends java.util.Date),
|
||||
* it will be checked and canonicalized only if not already correct.
|
||||
*/
|
||||
private static Timestamp toSqlTimestamp(Date date) {
|
||||
long millis = date.getTime();
|
||||
int fractionalSecondMillis = (int) (millis % 1000); // guaranteed < 1000
|
||||
|
||||
if (fractionalSecondMillis == 0) { // this means it's already correct by the spec
|
||||
if (date instanceof Timestamp) {
|
||||
return (Timestamp) date;
|
||||
} else {
|
||||
return new Timestamp(millis);
|
||||
}
|
||||
} else { // the millis are invalid and need to be corrected
|
||||
int tsNanos = fractionalSecondMillis * 1000000;
|
||||
long tsMillis = millis - fractionalSecondMillis;
|
||||
Timestamp timestamp = new Timestamp(tsMillis);
|
||||
timestamp.setNanos(tsNanos);
|
||||
return timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
public void addParameters(PreparedStatement ps, Object[] parameters) throws SQLException {
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Object parameter = parameters[i];
|
||||
|
||||
// Unwrap secret args here so we can use them
|
||||
if (parameter instanceof SecretArg) {
|
||||
parameter = ((SecretArg) parameter).getArg();
|
||||
}
|
||||
|
||||
if (parameter == null) {
|
||||
ParameterMetaData metaData;
|
||||
int parameterType;
|
||||
|
@ -106,57 +63,52 @@ public class StatementAdaptor {
|
|||
} else if (parameter instanceof java.sql.Date) {
|
||||
ps.setDate(i + 1, (java.sql.Date) parameter);
|
||||
} else if (parameter instanceof Date) {
|
||||
Date date = (Date) parameter;
|
||||
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
||||
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());
|
||||
//ps.setTimestamp(i + 1, toSqlTimestamp((Date) parameter), options.calendarForTimestamps());
|
||||
} else if (parameter instanceof Reader) {
|
||||
if (options.useStringForClob()) {
|
||||
ps.setString(i + 1, readerToString((Reader) parameter));
|
||||
try (BufferedReader reader = new BufferedReader((Reader) parameter)) {
|
||||
ps.setString(i + 1, reader.lines().collect(Collectors.joining()));
|
||||
} catch (IOException e) {
|
||||
throw new SQLException(e);
|
||||
}
|
||||
} else {
|
||||
ps.setCharacterStream(i + 1, (Reader) parameter);
|
||||
}
|
||||
} else if (parameter instanceof InputStream) {
|
||||
if (options.useBytesForBlob()) {
|
||||
ps.setBytes(i + 1, streamToBytes((InputStream) parameter));
|
||||
try {
|
||||
ps.setBytes(i + 1, ((InputStream) parameter).readAllBytes());
|
||||
} catch (IOException e) {
|
||||
throw new SQLException(e);
|
||||
}
|
||||
} else {
|
||||
ps.setBinaryStream(i + 1, (InputStream) parameter);
|
||||
}
|
||||
} else if (parameter instanceof Float) {
|
||||
//if (options.flavor() == Flavor.oracle && ps.isWrapperFor(OraclePreparedStatement.class)) {
|
||||
// The Oracle 11 driver setDouble() first converts the double to NUMBER, causing underflow
|
||||
// for small values so we need to use the proprietary mechanism
|
||||
//ps.unwrap(OraclePreparedStatement.class).setBinaryFloat(i + 1, (Float) parameter);
|
||||
//} else {
|
||||
ps.setFloat(i + 1, (Float) parameter);
|
||||
//}
|
||||
} else if (parameter instanceof Double) {
|
||||
//if (options.flavor() == Flavor.oracle && ps.isWrapperFor(OraclePreparedStatement.class)) {
|
||||
// The Oracle 11 driver setDouble() first converts the double to NUMBER, causing underflow
|
||||
// for small values so we need to use the proprietary mechanism
|
||||
//ps.unwrap(OraclePreparedStatement.class).setBinaryDouble(i + 1, (Double) parameter);
|
||||
//} else {
|
||||
ps.setDouble(i + 1, (Double) parameter);
|
||||
//}
|
||||
} else {
|
||||
ps.setObject(i + 1, parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object nullDate(LocalDateTime arg) {
|
||||
if (arg == null) {
|
||||
return new SqlNull(Types.TIMESTAMP);
|
||||
}
|
||||
return Timestamp.valueOf(arg);
|
||||
public Object nullLocalDateTime(LocalDateTime arg) {
|
||||
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg);
|
||||
}
|
||||
|
||||
public Object nullLocalDateTime(LocalDateTime arg, ZoneId zoneId) {
|
||||
return arg == null ? new SqlNull(Types.TIMESTAMP) : Timestamp.valueOf(arg.atZone(zoneId).toLocalDateTime());
|
||||
}
|
||||
|
||||
// Processes a true date without time information.
|
||||
public Object nullLocalDate(LocalDate arg) {
|
||||
if (arg == null) {
|
||||
return new SqlNull(Types.DATE);
|
||||
}
|
||||
|
||||
return java.sql.Date.valueOf(arg);
|
||||
return arg == null ? new SqlNull(Types.DATE) : java.sql.Date.valueOf(arg);
|
||||
}
|
||||
|
||||
public Object nullNumeric(Number arg) {
|
||||
|
@ -217,5 +169,4 @@ public class StatementAdaptor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,11 +2,6 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class BigQuery implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -81,7 +76,7 @@ public class BigQuery implements Flavor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String typeDate() {
|
||||
public String typeLocalDateTime() {
|
||||
return "datetime";
|
||||
}
|
||||
|
||||
|
@ -150,20 +145,6 @@ public class BigQuery implements Flavor {
|
|||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dateAsSqlFunction(Timestamp date, Calendar calendar) {
|
||||
// Construct a datetime literal
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000");
|
||||
dateFormat.setCalendar(calendar);
|
||||
return String.format("datetime '%s'", dateFormat.format(date));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localDateAsSqlFunction(Date date) {
|
||||
// Construct a datetime literal
|
||||
return String.format("datetime '%s'", date.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -2,11 +2,6 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Derby implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +75,7 @@ public class Derby implements Flavor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String typeDate() {
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp";
|
||||
}
|
||||
|
||||
|
@ -149,18 +144,6 @@ public class Derby implements Flavor {
|
|||
return " from sysibm.sysdummy1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dateAsSqlFunction(Timestamp date, Calendar calendar) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
dateFormat.setCalendar(calendar);
|
||||
return "timestamp('" + dateFormat.format(date) + "')";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localDateAsSqlFunction(Date date) {
|
||||
return "'" + date.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return " as bigint";
|
||||
|
|
175
jdbc-query/src/main/java/org/xbib/jdbc/query/flavor/H2.java
Normal file
175
jdbc-query/src/main/java/org/xbib/jdbc/query/flavor/H2.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
package org.xbib.jdbc.query.flavor;
|
||||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
public class H2 implements Flavor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "h2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(String url) {
|
||||
return url.startsWith("jdbc:h2:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String driverClass() {
|
||||
return "org.h2.Driver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalizedUpperCase() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeInteger() {
|
||||
return "integer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBoolean() {
|
||||
return "char(1)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLong() {
|
||||
return "bigint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeFloat() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeStringVar(int length) {
|
||||
return "varchar(" + length + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeStringFixed(int length) {
|
||||
return "char(" + length + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeClob() {
|
||||
return "clob(2G)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBlob() {
|
||||
return "blob(2G)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp(3)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLocalDate() {
|
||||
return "date";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useStringForClob() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useBytesForBlob() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceNextVal(String sequenceName) {
|
||||
return "next value for " + sequenceName + "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceSelectNextVal(String sequenceName) {
|
||||
return "select " + sequenceNextVal(sequenceName) + fromAny();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceDrop(String dbtestSeq) {
|
||||
return "drop sequence if exists " + dbtestSeq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tableDrop(String table) {
|
||||
return "drop table if exists " + table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOrderClause(boolean order) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCycleClause(boolean cycle) {
|
||||
return cycle ? " cycle" : " no cycle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromAny() {
|
||||
return " from (values(0))";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInsertReturning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbTimeMillis() {
|
||||
return "localtimestamp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCacheClause(int nbrValuesToCache) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return " as bigint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoCommitOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -2,11 +2,6 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Hsql implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -80,8 +75,8 @@ public class Hsql implements Flavor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String typeDate() {
|
||||
return "timestamp(3)";
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp with time zone";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,18 +144,6 @@ public class Hsql implements Flavor {
|
|||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dateAsSqlFunction(Timestamp date, Calendar calendar) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000XXX");
|
||||
dateFormat.setCalendar(calendar);
|
||||
return "cast(timestamp '" + dateFormat.format(date) + "' as timestamp without time zone)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localDateAsSqlFunction(Date date) {
|
||||
return "'" + date.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return " as bigint";
|
||||
|
|
177
jdbc-query/src/main/java/org/xbib/jdbc/query/flavor/MySQL.java
Normal file
177
jdbc-query/src/main/java/org/xbib/jdbc/query/flavor/MySQL.java
Normal file
|
@ -0,0 +1,177 @@
|
|||
package org.xbib.jdbc.query.flavor;
|
||||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
public class MySQL implements Flavor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "mysql";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(String url) {
|
||||
return url.startsWith("jdbc:mysql:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String driverClass() {
|
||||
return "com.mysql.jdbc.Driver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalizedUpperCase() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeInteger() {
|
||||
return "integer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBoolean() {
|
||||
return "char(1)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLong() {
|
||||
return "bigint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeFloat() {
|
||||
return "real";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeStringVar(int length) {
|
||||
return "varchar(" + length + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeStringFixed(int length) {
|
||||
return "char(" + length + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeClob() {
|
||||
return "clob";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBlob() {
|
||||
return "blob";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp";
|
||||
}
|
||||
|
||||
@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 "values next value for " + sequenceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceDrop(String sequenceName) {
|
||||
return "drop sequence " + sequenceName + " restrict";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tableDrop(String table) {
|
||||
return "drop table " + table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInsertReturning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCacheClause(int nbrValuesToCache) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOrderClause(boolean order) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCycleClause(boolean cycle) {
|
||||
return cycle ? " cycle" : " no cycle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbTimeMillis() {
|
||||
return "current_timestamp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromAny() {
|
||||
return " from sysibm.sysdummy1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return " as bigint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoCommitOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,6 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Oracle implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +55,7 @@ public class Oracle implements Flavor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String typeDate() {
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp(3)";
|
||||
}
|
||||
|
||||
|
@ -152,18 +147,6 @@ public class Oracle implements Flavor {
|
|||
return " from dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dateAsSqlFunction(Timestamp date, Calendar calendar) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000");
|
||||
dateFormat.setCalendar(calendar);
|
||||
return "timestamp '" + dateFormat.format(date) + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localDateAsSqlFunction(Date date) {
|
||||
return "to_date('" + date.toString() + "', 'yyyy-mm-dd')";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return "";
|
||||
|
|
|
@ -2,11 +2,6 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Postgresql implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +75,7 @@ public class Postgresql implements Flavor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String typeDate() {
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp(3)";
|
||||
}
|
||||
|
||||
|
@ -149,18 +144,6 @@ public class Postgresql implements Flavor {
|
|||
return " cache " + nbrValuesToCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dateAsSqlFunction(Timestamp date, Calendar calendar) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000");
|
||||
dateFormat.setCalendar(calendar);
|
||||
return "'" + dateFormat.format(date) + " GMT'::timestamp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localDateAsSqlFunction(Date date) {
|
||||
return "'" + date.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return "";
|
||||
|
|
|
@ -2,11 +2,6 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class SqlServer implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +55,7 @@ public class SqlServer implements Flavor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String typeDate() {
|
||||
public String typeLocalDateTime() {
|
||||
return "datetime2(3)";
|
||||
}
|
||||
|
||||
|
@ -153,18 +148,6 @@ public class SqlServer implements Flavor {
|
|||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dateAsSqlFunction(Timestamp date, Calendar calendar) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000");
|
||||
dateFormat.setCalendar(calendar);
|
||||
return "cast('" + dateFormat.format(date) + "' as datetime2(3))";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localDateAsSqlFunction(Date date) {
|
||||
return "'" + date.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return "";
|
||||
|
|
|
@ -6,7 +6,8 @@ import org.xbib.jdbc.query.SqlNull;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -77,9 +78,15 @@ public class DebugSql {
|
|||
} else if (argToPrint instanceof SqlNull || argToPrint == null) {
|
||||
buf.append("null");
|
||||
} else if (argToPrint instanceof java.sql.Timestamp) {
|
||||
buf.append(options.flavor().dateAsSqlFunction((Timestamp) argToPrint, options.calendarForTimestamps()));
|
||||
java.sql.Timestamp timestamp = (java.sql.Timestamp) argToPrint;
|
||||
LocalDateTime localDateTime = timestamp.toLocalDateTime();
|
||||
buf.append(localDateTime.toString());
|
||||
//buf.append(options.flavor().dateAsSqlFunction((Timestamp) argToPrint, options.calendarForTimestamps()));
|
||||
} else if (argToPrint instanceof java.sql.Date) {
|
||||
buf.append(options.flavor().localDateAsSqlFunction((java.sql.Date) argToPrint));
|
||||
java.sql.Date date = (java.sql.Date) argToPrint;
|
||||
LocalDate localDate = date.toLocalDate();
|
||||
buf.append(localDate.toString());
|
||||
//buf.append(options.flavor().localDateAsSqlFunction((java.sql.Date) argToPrint));
|
||||
} else if (argToPrint instanceof Number) {
|
||||
buf.append(argToPrint);
|
||||
} else if (argToPrint instanceof Boolean) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
org.xbib.jdbc.query.flavor.BigQuery
|
||||
org.xbib.jdbc.query.flavor.Derby
|
||||
org.xbib.jdbc.query.flavor.Hsql
|
||||
org.xbib.jdbc.query.flavor.H2
|
||||
org.xbib.jdbc.query.flavor.MySQL
|
||||
org.xbib.jdbc.query.flavor.Oracle
|
||||
org.xbib.jdbc.query.flavor.Postgresql
|
||||
org.xbib.jdbc.query.flavor.SqlServer
|
|
@ -25,7 +25,6 @@ import java.io.Reader;
|
|||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -36,9 +35,9 @@ import java.time.format.DateTimeFormatter;
|
|||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -64,22 +63,15 @@ public abstract class CommonTest {
|
|||
|
||||
protected Database db;
|
||||
|
||||
protected LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
protected LocalDateTime now;
|
||||
|
||||
protected LocalDate localDateNow = LocalDate.now();
|
||||
protected LocalDate localDateNow;
|
||||
|
||||
@BeforeEach
|
||||
public void setupJdbc() throws Exception {
|
||||
now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
localDateNow = LocalDate.now();
|
||||
dbp = createDatabaseProvider(new OptionsOverride() {
|
||||
@Override
|
||||
public LocalDateTime currentDate() {
|
||||
return now;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar calendarForTimestamps() {
|
||||
return Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
|
||||
}
|
||||
});
|
||||
db = dbp.get();
|
||||
db.dropTableQuietly(TEST_TABLE_NAME);
|
||||
|
@ -153,13 +145,13 @@ public abstract class CommonTest {
|
|||
.addColumn("str_fixed").asStringFixed(1).table()
|
||||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().table().schema().execute(db);
|
||||
|
||||
BigDecimal bigDecimal = new BigDecimal("5.3");
|
||||
db.toInsert("insert into dbtest values (?,?,?,?,?,?,?,?,?,?,?)").argInteger(1).argLong(2L).argFloat(3.2f).argDouble(4.2)
|
||||
.argBigDecimal(bigDecimal).argString("Hello").argString("T").argClobString("World")
|
||||
.argBlobBytes("More".getBytes()).argDate(now).argLocalDate(localDateNow).insert(1);
|
||||
.argBlobBytes("More".getBytes()).argLocalDateTime(now).argLocalDate(localDateNow).insert(1);
|
||||
|
||||
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")
|
||||
|
@ -286,14 +278,14 @@ public abstract class CommonTest {
|
|||
.argBigDecimal("bd", bigDecimal)
|
||||
.argString("s", "Hello")
|
||||
.argString("sf", "T")
|
||||
.argDate("date", now)
|
||||
.argLocalDateTime("date", now)
|
||||
.argLocalDate("local_date", localDateNow)
|
||||
.queryLongOrNull());
|
||||
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 "
|
||||
+ "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")
|
||||
.argDate("date", now).argLocalDate("local_date", localDateNow).queryLongs();
|
||||
.argLocalDateTime("date", now).argLocalDate("local_date", localDateNow).queryLongs();
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(Long.valueOf(1), result.get(0));
|
||||
}
|
||||
|
@ -312,7 +304,7 @@ public abstract class CommonTest {
|
|||
.addColumn("str_fixed").asStringFixed(1).table()
|
||||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().table().schema().execute(db);
|
||||
|
||||
BigDecimal bigDecimal = new BigDecimal("5.3");
|
||||
|
@ -327,12 +319,12 @@ public abstract class CommonTest {
|
|||
.argString("T")
|
||||
.argClobString("World")
|
||||
.argBlobBytes("More".getBytes())
|
||||
.argDate(now)
|
||||
.argLocalDateTime(now)
|
||||
.argLocalDate(localDateNow).insert());
|
||||
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)
|
||||
.argFloat(null).argDouble(null).argBigDecimal(null).argString(null).argString(null).argClobString(null)
|
||||
.argBlobBytes(null).argDate(null).argLocalDate(null).update(1);
|
||||
.argBlobBytes(null).argLocalDateTime(null).argLocalDate(null).update(1);
|
||||
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 -> {
|
||||
assertTrue(rs.next());
|
||||
|
@ -363,7 +355,7 @@ public abstract class CommonTest {
|
|||
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)
|
||||
.argLong(2L).argFloat(3.2f).argDouble(4.2).argBigDecimal(bigDecimal).argString("Hello").argString("T")
|
||||
.argClobString("World").argBlobBytes("More".getBytes()).argDate(now).argLocalDate(localDateNow).update());
|
||||
.argClobString("World").argBlobBytes("More".getBytes()).argLocalDateTime(now).argLocalDate(localDateNow).update());
|
||||
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 -> {
|
||||
assertTrue(rs.next());
|
||||
|
@ -426,20 +418,20 @@ public abstract class CommonTest {
|
|||
.addColumn("str_fixed").asStringFixed(1).table()
|
||||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().table().schema().execute(db);
|
||||
BigDecimal bigDecimal = new BigDecimal("5.3");
|
||||
db.toInsert("insert into dbtest values (:pk,:a,:b,:c,:d,:e,:f,:sf,:g,:h,:i,:j)").argLong(":pk", 1L).argInteger(":a", 1)
|
||||
.argLong(":b", 2L).argFloat(":c", 3.2f).argDouble(":d", 4.2).argBigDecimal(":e", bigDecimal)
|
||||
.argString(":f", "Hello").argString(":sf", "T")
|
||||
.argClobString(":g", "World").argBlobBytes(":h", "More".getBytes())
|
||||
.argDate(":i", now).argLocalDate(":j", localDateNow).insert(1);
|
||||
.argLocalDateTime(":i", now).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, "
|
||||
+ "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)
|
||||
.argString(":f", null).argString(":sf", null)
|
||||
.argClobString(":g", null).argBlobBytes(":h", null)
|
||||
.argDate(":i", null).argLocalDate(":j", null).update(1);
|
||||
.argLocalDateTime(":i", null).argLocalDate(":j", null).update(1);
|
||||
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 -> {
|
||||
assertTrue(rs.next());
|
||||
|
@ -472,7 +464,7 @@ public abstract class CommonTest {
|
|||
.argLong(":b", 2L).argFloat(":c", 3.2f).argDouble(":d", 4.2).argBigDecimal(":e", bigDecimal)
|
||||
.argString(":f", "Hello").argString(":sf", "T")
|
||||
.argClobString(":g", "World").argBlobBytes(":h", "More".getBytes())
|
||||
.argDate(":i", now).argLocalDate(":j", localDateNow).update(1);
|
||||
.argLocalDateTime(":i", now).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, "
|
||||
+ "bin_blob, date_millis, local_date from dbtest")
|
||||
.query((RowsHandler<Void>) rs -> {
|
||||
|
@ -537,11 +529,11 @@ public abstract class CommonTest {
|
|||
.addColumn("str_fixed").asStringFixed(1).table()
|
||||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().table().schema().execute(db);
|
||||
db.toInsert("insert into dbtest values (?,?,?,?,?,?,?,?,?,?,?,?)").argLong(1L).argInteger(null).argLong(null)
|
||||
.argFloat(null).argDouble(null).argBigDecimal(null).argString(null).argString(null).argClobString(null)
|
||||
.argBlobBytes(null).argDate(null).argLocalDate(null).insert(1);
|
||||
.argBlobBytes(null).argLocalDateTime(null).argLocalDate(null).insert(1);
|
||||
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 -> {
|
||||
|
@ -604,7 +596,7 @@ public abstract class CommonTest {
|
|||
String dateColumnName = "local_date";
|
||||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn(timestampColumnName).asDate().table()
|
||||
.addColumn(timestampColumnName).asLocalDateTime().table()
|
||||
.addColumn(dateColumnName).asLocalDate().table().schema().execute(db);
|
||||
db.toSelect("select * from dbtest").query((RowsHandler<Void>) rs -> {
|
||||
ResultSetMetaData metadata = rs.getMetadata();
|
||||
|
@ -612,8 +604,10 @@ public abstract class CommonTest {
|
|||
String columnName = metadata.getColumnName(i);
|
||||
String columnType = metadata.getColumnTypeName(i);
|
||||
if (columnName.equalsIgnoreCase(timestampColumnName)) {
|
||||
if ("sqlserver".equals(db.flavor().toString())) {
|
||||
if ("sqlserver".equals(db.flavor().getName())) {
|
||||
assertEquals("DATETIME2", columnType.toUpperCase());
|
||||
} else if ("hsqldb".equals(db.flavor().getName())) {
|
||||
assertEquals("TIMESTAMP WITH TIME ZONE", columnType.toUpperCase());
|
||||
} else {
|
||||
assertEquals("TIMESTAMP", columnType.toUpperCase());
|
||||
}
|
||||
|
@ -629,11 +623,11 @@ public abstract class CommonTest {
|
|||
|
||||
@Test
|
||||
public void intervals() {
|
||||
new Schema().addTable("dbtest").addColumn("d").asDate().schema().execute(db);
|
||||
db.toInsert("insert into dbtest (d) values (?)").argDate(now).insert(1);
|
||||
new Schema().addTable("dbtest").addColumn("d").asLocalDateTime().schema().execute(db);
|
||||
db.toInsert("insert into dbtest (d) values (?)").argLocalDateTime(now).insert(1);
|
||||
assertEquals(1, db.toSelect("select count(1) from dbtest where d - interval '1' hour * ? < ?")
|
||||
.argInteger(2)
|
||||
.argDate(now)
|
||||
.argLocalDateTime(now)
|
||||
.queryIntegerOrZero());
|
||||
}
|
||||
|
||||
|
@ -650,7 +644,7 @@ public abstract class CommonTest {
|
|||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("boolean_flag").asBoolean().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().schema().execute(db);
|
||||
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 (?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
|
@ -658,14 +652,16 @@ public abstract class CommonTest {
|
|||
.argDouble(Double.MAX_VALUE).argBigDecimal(new BigDecimal("123.456"))
|
||||
.argString("hello").argString("Z").argClobString("hello again")
|
||||
.argBlobBytes(new byte[]{'1', '2'}).argBoolean(true)
|
||||
.argDateNowPerApp().argLocalDate(localDateNow).insert(1);
|
||||
.argLocalDateTime(now)
|
||||
.argLocalDate(localDateNow).insert(1);
|
||||
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 (?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
.argInteger(Integer.MIN_VALUE).argLong(Long.MIN_VALUE).argFloat(0.000001f)
|
||||
.argDouble(Double.MIN_VALUE).argBigDecimal(new BigDecimal("-123.456"))
|
||||
.argString("goodbye").argString("A").argClobString("bye again")
|
||||
.argBlobBytes(new byte[]{'3', '4'}).argBoolean(false)
|
||||
.argDateNowPerApp().argLocalDate(localDateNow).insert(1);
|
||||
.argLocalDateTime(now)
|
||||
.argLocalDate(localDateNow).insert(1);
|
||||
String expectedSchema = new Schema().addTable("dbtest2")
|
||||
.addColumn("nbr_integer").asInteger().table()
|
||||
.addColumn("nbr_long").asLong().table()
|
||||
|
@ -677,7 +673,7 @@ public abstract class CommonTest {
|
|||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("boolean_flag").asBoolean().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().schema().print(db.flavor());
|
||||
List<SqlArgs> args = 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 dbtest")
|
||||
|
@ -719,7 +715,7 @@ public abstract class CommonTest {
|
|||
.argClobString("str_lob", "bye again")
|
||||
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
||||
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
||||
.argDate("date_millis", now)
|
||||
.argLocalDateTime("date_millis", now)
|
||||
.argLocalDate("local_date", localDateNow),
|
||||
new SqlArgs().argInteger("nbr_integer", Integer.MAX_VALUE)
|
||||
.argLong("nbr_long", Long.MAX_VALUE)
|
||||
|
@ -731,7 +727,7 @@ public abstract class CommonTest {
|
|||
.argClobString("str_lob", "hello again")
|
||||
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
||||
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
||||
.argDate("date_millis", now)
|
||||
.argLocalDateTime("date_millis", now)
|
||||
.argLocalDate("local_date", localDateNow)),
|
||||
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")
|
||||
|
@ -1368,25 +1364,26 @@ public abstract class CommonTest {
|
|||
@Test
|
||||
public void insertReturningAppDate() {
|
||||
db.dropSequenceQuietly("dbtest_seq");
|
||||
|
||||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("pk").primaryKey().table()
|
||||
.addColumn("d").asDate().table().schema()
|
||||
.addColumn("d")
|
||||
.asLocalDateTime()
|
||||
.table()
|
||||
.schema()
|
||||
.addSequence("dbtest_seq").schema()
|
||||
.execute(db);
|
||||
|
||||
db.toInsert("insert into dbtest (pk, d) values (:seq, :d)")
|
||||
.argPkSeq(":seq", "dbtest_seq")
|
||||
.argDateNowPerApp(":d")
|
||||
.argLocalDateTime(":d", now)
|
||||
.insertReturning("dbtest", "pk", rs -> {
|
||||
assertTrue(rs.next());
|
||||
assertEquals(Long.valueOf(1L), rs.getLongOrNull(1));
|
||||
assertThat(rs.getLocalDateTimeOrNull(2), equalTo(now));
|
||||
assertThat(rs.getLocalDateTimeOrNull(2, ZoneId.systemDefault()), equalTo(now));
|
||||
assertFalse(rs.next());
|
||||
return null;
|
||||
}, "d");
|
||||
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d=?").argDate(now).queryLongOrNull());
|
||||
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d=?").argLocalDateTime(now).queryLongOrNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1394,18 +1391,20 @@ public abstract class CommonTest {
|
|||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("pk").primaryKey().table()
|
||||
.addColumn("d").asDate().table()
|
||||
.addColumn("d2").asDate().table()
|
||||
.addColumn("d").asLocalDateTime().table()
|
||||
.addColumn("d2").asLocalDateTime().table()
|
||||
.addColumn("d3").asLocalDate().table()
|
||||
.addColumn("d4").asLocalDate().table()
|
||||
.addColumn("s").asString(5).table()
|
||||
.addColumn("s2").asString(5).table()
|
||||
.addColumn("i").asInteger().table().schema()
|
||||
.execute(db);
|
||||
|
||||
db.toInsert("insert into dbtest (pk, d, d3, s) values (?,?,?,?)")
|
||||
.argLong(1L).argDateNowPerApp().argLocalDate(localDateNow).argString("foo").insert(1);
|
||||
|
||||
.argLong(1L)
|
||||
.argLocalDateTime(now)
|
||||
.argLocalDate(localDateNow)
|
||||
.argString("foo")
|
||||
.insert(1);
|
||||
assertEquals(Long.valueOf(1L), db.toSelect("select pk from dbtest").queryLongOrNull());
|
||||
assertNull(db.toSelect("select pk from dbtest where 1=0").queryLongOrNull());
|
||||
assertNull(db.toSelect("select i from dbtest").queryLongOrNull());
|
||||
|
@ -1415,7 +1414,6 @@ public abstract class CommonTest {
|
|||
assertEquals(1L, (long) db.toSelect("select pk from dbtest").queryLongs().get(0));
|
||||
assertTrue(db.toSelect("select pk from dbtest where 1=0").queryLongs().isEmpty());
|
||||
assertTrue(db.toSelect("select i from dbtest").queryLongs().isEmpty());
|
||||
|
||||
assertEquals(Integer.valueOf(1), db.toSelect("select pk from dbtest").queryIntegerOrNull());
|
||||
assertNull(db.toSelect("select pk from dbtest where 1=0").queryIntegerOrNull());
|
||||
assertNull(db.toSelect("select i from dbtest").queryIntegerOrNull());
|
||||
|
@ -1425,7 +1423,6 @@ public abstract class CommonTest {
|
|||
assertEquals(1L, (int) db.toSelect("select pk from dbtest").queryIntegers().get(0));
|
||||
assertTrue(db.toSelect("select pk from dbtest where 1=0").queryIntegers().isEmpty());
|
||||
assertTrue(db.toSelect("select i from dbtest").queryIntegers().isEmpty());
|
||||
|
||||
assertEquals("foo", db.toSelect("select s from dbtest").queryStringOrNull());
|
||||
assertNull(db.toSelect("select s from dbtest where 1=0").queryStringOrNull());
|
||||
assertNull(db.toSelect("select s2 from dbtest").queryStringOrNull());
|
||||
|
@ -1435,13 +1432,12 @@ public abstract class CommonTest {
|
|||
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 s2 from dbtest").queryStrings().isEmpty());
|
||||
|
||||
assertEquals(now, db.toSelect("select d from dbtest").queryDateOrNull());
|
||||
assertNull(db.toSelect("select d from dbtest where 1=0").queryDateOrNull());
|
||||
assertNull(db.toSelect("select d2 from dbtest").queryDateOrNull());
|
||||
assertEquals(db.toSelect("select d from dbtest").queryDates().get(0), now);
|
||||
assertTrue(db.toSelect("select d from dbtest where 1=0").queryDates().isEmpty());
|
||||
assertTrue(db.toSelect("select d2 from dbtest").queryDates().isEmpty());
|
||||
assertEquals(now, db.toSelect("select d from dbtest").queryLocalDateTimeOrNull());
|
||||
assertNull(db.toSelect("select d from dbtest where 1=0").queryLocalDateTimeOrNull());
|
||||
assertNull(db.toSelect("select d2 from dbtest").queryLocalDateTimeOrNull());
|
||||
assertEquals(db.toSelect("select d from dbtest").queryLocalDateTimes().get(0), now);
|
||||
assertTrue(db.toSelect("select d from dbtest where 1=0").queryLocalDateTimes().isEmpty());
|
||||
assertTrue(db.toSelect("select d2 from dbtest").queryLocalDateTimes().isEmpty());
|
||||
|
||||
assertEquals(localDateNow, db.toSelect("select d3 from dbtest").queryLocalDateOrNull());
|
||||
assertNull(db.toSelect("select d3 from dbtest where 1=0").queryLocalDateOrNull());
|
||||
|
@ -1511,12 +1507,12 @@ public abstract class CommonTest {
|
|||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("pk").primaryKey().table()
|
||||
.addColumn("d").asDate().table().schema()
|
||||
.addColumn("d").asLocalDateTime().table().schema()
|
||||
.addSequence("dbtest_seq").schema()
|
||||
.execute(db);
|
||||
LocalDateTime dbNow = db.toInsert("insert into dbtest (pk, d) values (:seq, :d)")
|
||||
.argPkSeq(":seq", "dbtest_seq")
|
||||
.argDateNowPerDb(":d")
|
||||
.argLocalDateTimeNowPerDb(":d")
|
||||
.insertReturning("dbtest", "pk", rs -> {
|
||||
assertTrue(rs.next());
|
||||
assertEquals(Long.valueOf(1L), rs.getLongOrNull(1));
|
||||
|
@ -1524,7 +1520,8 @@ public abstract class CommonTest {
|
|||
assertFalse(rs.next());
|
||||
return dbDate;
|
||||
}, "d");
|
||||
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d=?").argDate(dbNow).queryLongOrNull());
|
||||
assertEquals(Long.valueOf(1L),
|
||||
db.toSelect("select count(*) from dbtest where d = ?").argLocalDateTime(dbNow).queryLongOrNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1581,12 +1578,12 @@ public abstract class CommonTest {
|
|||
for (int attempts = 1; attempts <= 10; attempts++) {
|
||||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("d").asDate().table().schema()
|
||||
.addColumn("d").asLocalDateTime().table().schema()
|
||||
.execute(db);
|
||||
db.toInsert("insert into dbtest (d) values (?)")
|
||||
.argDateNowPerDb()
|
||||
.argLocalDateTimeNowPerDb()
|
||||
.insert(1);
|
||||
LocalDateTime dbNow = db.toSelect("select d from dbtest").queryDateOrNull();
|
||||
LocalDateTime dbNow = db.toSelect("select d from dbtest").queryLocalDateTimeOrNull();
|
||||
if (dbNow != null && dbNow.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() % 10 != 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1600,19 +1597,17 @@ public abstract class CommonTest {
|
|||
public void dateRoundTrip() {
|
||||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("d1").asDate().table()
|
||||
.addColumn("d2").asDate().table().schema()
|
||||
.addColumn("d1").asLocalDateTime().table()
|
||||
.addColumn("d2").asLocalDateTime().table()
|
||||
.schema()
|
||||
.execute(db);
|
||||
// Store current time as per the database
|
||||
db.toInsert("insert into dbtest (d1) values (?)")
|
||||
.argDateNowPerDb()
|
||||
.argLocalDateTimeNowPerDb()
|
||||
.insert(1);
|
||||
// Now pull it out, put it back in, and verify it matches in the database
|
||||
LocalDateTime dbNow = db.toSelect("select d1 from dbtest").queryDateOrNull();
|
||||
db.toUpdate("update dbtest set d2=?")
|
||||
.argDate(dbNow)
|
||||
LocalDateTime dbNow = db.toSelect("select d1 from dbtest").queryLocalDateTimeOrNull();
|
||||
db.toUpdate("update dbtest set d2 = ?")
|
||||
.argLocalDateTime(dbNow)
|
||||
.update(1);
|
||||
|
||||
assertEquals(Long.valueOf(1L), db.toSelect("select count(*) from dbtest where d1=d2").queryLongOrNull());
|
||||
}
|
||||
|
||||
|
@ -1620,66 +1615,75 @@ public abstract class CommonTest {
|
|||
public void dateRoundTripTimezones() {
|
||||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("d").asDate().table().schema()
|
||||
.addColumn("d")
|
||||
.asLocalDateTime()
|
||||
.table()
|
||||
.schema()
|
||||
.execute(db);
|
||||
Instant instant = Instant.ofEpochMilli(166656789L);
|
||||
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4)));
|
||||
LocalDateTime datePlus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4)));
|
||||
TimeZone defaultTZ = TimeZone.getDefault();
|
||||
try {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT-4:00"));
|
||||
db.toInsert("insert into dbtest (d) values (?)").argDate(dateMinus).insert(1);
|
||||
LocalDateTime localDateTimeMinus = db.toSelect("select d from dbtest").queryDateOrNull();
|
||||
ZoneId dateMinusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4));
|
||||
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, dateMinusZone);
|
||||
ZoneId datePlusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4));
|
||||
LocalDateTime datePlus = LocalDateTime.ofInstant(instant,datePlusZone);
|
||||
logger.log(Level.INFO, "dateMinus = " + dateMinus);
|
||||
db.toInsert("insert into dbtest (d) values (?)")
|
||||
.argLocalDateTime(dateMinus)
|
||||
.insert(1);
|
||||
LocalDateTime localDateTimeMinus = db.toSelect("select d from dbtest")
|
||||
.queryLocalDateTimeOrNull();
|
||||
assertEquals(dateMinus, localDateTimeMinus);
|
||||
assertEquals("1970-01-02 18:17:36.789", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimeMinus));
|
||||
db.toDelete("delete from dbtest where d=?").argDate(dateMinus).update(1);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+4:00"));
|
||||
db.toInsert("insert into dbtest (d) values (?)").argDate(datePlus).insert(1);
|
||||
LocalDateTime localDateTimePlus = db.toSelect("select d from dbtest").queryDateOrNull();
|
||||
assertEquals("1970-01-02 18:17:36.789",
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimeMinus));
|
||||
db.toDelete("delete from dbtest where d = ?").argLocalDateTime(dateMinus).update(1);
|
||||
db.toInsert("insert into dbtest (d) values (?)")
|
||||
.argLocalDateTime(datePlus)
|
||||
.insert(1);
|
||||
LocalDateTime localDateTimePlus = db.toSelect("select d from dbtest")
|
||||
.queryLocalDateTimeOrNull(datePlusZone);
|
||||
assertEquals(datePlus, localDateTimePlus);
|
||||
assertEquals("1970-01-03 02:17:36.789", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimePlus));
|
||||
db.toDelete("delete from dbtest where d=?").argDate(datePlus).update(1);
|
||||
} finally {
|
||||
TimeZone.setDefault(defaultTZ);
|
||||
}
|
||||
assertEquals("1970-01-03 02:17:36.789",
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimePlus));
|
||||
db.toDelete("delete from dbtest where d = ?").argLocalDateTime(datePlus).update(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the appropriate database flavor can correctly convert a {@code Date}
|
||||
* Verify the appropriate database flavor can correctly convert a {@code LocalDateTime}
|
||||
* into a SQL function representing a conversion from string to timestamp. This
|
||||
* function is used to write debug SQL to the log in a way that could be manually
|
||||
* executed if desired.
|
||||
*/
|
||||
@Test
|
||||
public void stringDateFunctions() {
|
||||
public void stringLocalDateTimeFunctions() {
|
||||
Instant instant = Instant.ofEpochMilli(166656789L);
|
||||
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4)));
|
||||
LocalDateTime datePlus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4)));
|
||||
logger.info("LocalDateTime: " + dateMinus + " " + datePlus);
|
||||
TimeZone defaultTZ = TimeZone.getDefault();
|
||||
try {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT-4:00"));
|
||||
new Schema().addTable("dbtest").addColumn("d").asDate().schema().execute(db);
|
||||
db.toInsert("insert into dbtest (d) values ("
|
||||
+ db.flavor().dateAsSqlFunction(Timestamp.valueOf(dateMinus), db.options().calendarForTimestamps()).replace(":", "::") + ")")
|
||||
ZoneId dateMinusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4));
|
||||
LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, dateMinusZone);
|
||||
ZoneId datePlusZone = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4));
|
||||
LocalDateTime datePlus = LocalDateTime.ofInstant(instant, datePlusZone);
|
||||
logger.info("LocalDateTime: dateMinus=" + dateMinus + " datePlus=" + datePlus);
|
||||
new Schema().addTable("dbtest").addColumn("d")
|
||||
.asLocalDateTime()
|
||||
.schema()
|
||||
.execute(db);
|
||||
db.toInsert("insert into dbtest (d) values (?)")
|
||||
.argLocalDateTime(dateMinus)
|
||||
.insert(1);
|
||||
LocalDateTime localDateTime = db.toSelect("select d from dbtest")
|
||||
.queryLocalDateTimeOrNull();
|
||||
assertEquals("1970-01-02 18:17:36.789",
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(db.toSelect("select d from dbtest").queryDateOrNull()));
|
||||
// Now do some client operations in a different time zone
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+4:00"));
|
||||
// Verify regular arg maps date the same way even though our TimeZone is now different
|
||||
db.toDelete("delete from dbtest where d=?").argDate(datePlus).update(1);
|
||||
db.toInsert("insert into dbtest (d) values ("
|
||||
+ db.flavor().dateAsSqlFunction(Timestamp.valueOf(datePlus), db.options().calendarForTimestamps()).replace(":", "::") + ")")
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTime.atZone(dateMinusZone)));
|
||||
db.toDelete("delete from dbtest where d = ?")
|
||||
.argLocalDateTime(dateMinus)
|
||||
.update(1);
|
||||
db.toInsert("insert into dbtest (d) values (?)")
|
||||
.argLocalDateTime(datePlus)
|
||||
.insert(1);
|
||||
localDateTime = db.toSelect("select d from dbtest")
|
||||
.queryLocalDateTimeOrNull(datePlusZone);
|
||||
assertEquals("1970-01-03 02:17:36.789",
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(db.toSelect("select d from dbtest").queryDateOrNull()));
|
||||
// Verify the function maps correctly for equals operations as well
|
||||
db.toDelete("delete from dbtest where d=" + db.flavor().dateAsSqlFunction(Timestamp.valueOf(datePlus),
|
||||
db.options().calendarForTimestamps()).replace(":", "::")).update(1);
|
||||
} finally {
|
||||
TimeZone.setDefault(defaultTZ);
|
||||
}
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTime.atZone(datePlusZone)));
|
||||
db.toDelete("delete from dbtest where d = ?")
|
||||
.argLocalDateTime(datePlus)
|
||||
.update(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1687,12 +1691,12 @@ public abstract class CommonTest {
|
|||
new Schema()
|
||||
.addTable("dbtest")
|
||||
.addColumn("pk").primaryKey().table()
|
||||
.addColumn("d").asDate().table()
|
||||
.addColumn("d").asLocalDateTime().table()
|
||||
.addColumn("a").asInteger().table().schema()
|
||||
.execute(db);
|
||||
|
||||
db.toSelect("select pk as \"time:: now??\" from dbtest where a=? and d=:now")
|
||||
.argInteger(1).argDateNowPerDb("now").query(rs -> {
|
||||
.argInteger(1).argLocalDateTimeNowPerDb("now").query(rs -> {
|
||||
assertFalse(rs.next());
|
||||
return null;
|
||||
});
|
||||
|
|
|
@ -57,12 +57,6 @@ public class HsqldbTest extends CommonTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Disabled("HSQLDB uses always static GMT timezone")
|
||||
@Test
|
||||
public void clockSync() {
|
||||
db.assertTimeSynchronized();
|
||||
}
|
||||
|
||||
@Disabled("LocalDate implementations should be TimeZone agnostic, but HSQLDB implementation has a bug.")
|
||||
@Test
|
||||
public void argLocalDateTimeZones() {
|
||||
|
@ -89,7 +83,7 @@ public class HsqldbTest extends CommonTest {
|
|||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("boolean_flag").asBoolean().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().schema().execute(db);
|
||||
|
||||
db.toInsert("insert into dbtest (nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal, str_varchar,"
|
||||
|
@ -104,7 +98,7 @@ public class HsqldbTest extends CommonTest {
|
|||
.argClobString("hello again")
|
||||
.argBlobBytes(new byte[]{'1', '2'})
|
||||
.argBoolean(true)
|
||||
.argDateNowPerApp()
|
||||
.argLocalDateTime(now)
|
||||
.argLocalDate(localDateNow)
|
||||
.insert(1);
|
||||
|
||||
|
@ -120,7 +114,7 @@ public class HsqldbTest extends CommonTest {
|
|||
.argClobString("bye again")
|
||||
.argBlobBytes(new byte[]{'3', '4'})
|
||||
.argBoolean(false)
|
||||
.argDateNowPerApp()
|
||||
.argLocalDateTime(now)
|
||||
.argLocalDate(localDateNow)
|
||||
.insert(1);
|
||||
|
||||
|
@ -135,7 +129,7 @@ public class HsqldbTest extends CommonTest {
|
|||
.addColumn("str_lob").asClob().table()
|
||||
.addColumn("bin_blob").asBlob().table()
|
||||
.addColumn("boolean_flag").asBoolean().table()
|
||||
.addColumn("date_millis").asDate().table()
|
||||
.addColumn("date_millis").asLocalDateTime().table()
|
||||
.addColumn("local_date").asLocalDate().schema().print(db.flavor());
|
||||
|
||||
List<SqlArgs> args = db.toSelect("select nbr_integer, nbr_long, nbr_float, nbr_double, nbr_big_decimal,"
|
||||
|
@ -175,7 +169,7 @@ public class HsqldbTest extends CommonTest {
|
|||
.argClobString("str_lob", "bye again")
|
||||
.argBlobBytes("bin_blob", new byte[]{'3', '4'})
|
||||
.argString("boolean_flag", "N")//.argBoolean("boolean_flag", false)
|
||||
.argDate("date_millis", now)
|
||||
.argLocalDateTime("date_millis", now)
|
||||
.argLocalDate("local_date", localDateNow),
|
||||
new SqlArgs()
|
||||
.argInteger("nbr_integer", Integer.MAX_VALUE)
|
||||
|
@ -188,7 +182,7 @@ public class HsqldbTest extends CommonTest {
|
|||
.argClobString("str_lob", "hello again")
|
||||
.argBlobBytes("bin_blob", new byte[]{'1', '2'})
|
||||
.argString("boolean_flag", "Y")//.argBoolean("boolean_flag", true)
|
||||
.argDate("date_millis", now)
|
||||
.argLocalDateTime("date_millis", now)
|
||||
.argLocalDate("local_date", localDateNow)),
|
||||
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")
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.ResultSetMetaData;
|
|||
import java.sql.Types;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -628,21 +629,32 @@ public class RowStub {
|
|||
|
||||
@Override
|
||||
public LocalDateTime getLocalDateTimeOrNull() {
|
||||
return toDate(rows.get(row)[++col]);
|
||||
return toLocalDateTime(rows.get(row)[++col]);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LocalDateTime getLocalDateTimeOrNull(int columnOneBased) {
|
||||
col = columnOneBased;
|
||||
return toDate(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
|
||||
public LocalDateTime getLocalDateTimeOrNull(String columnName) {
|
||||
col = columnIndexByName(columnName) + 1;
|
||||
return toDate(rows.get(row)[columnIndexByName(columnName)]);
|
||||
return toLocalDateTime(rows.get(row)[columnIndexByName(columnName)]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getLocalDateTimeOrNull(String columnName, ZoneId zoneId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -758,14 +770,20 @@ public class RowStub {
|
|||
return (String) o;
|
||||
}
|
||||
|
||||
private LocalDateTime toDate(Object o) {
|
||||
private LocalDateTime toLocalDateTime(Object o) {
|
||||
return toLocalDateTime(o, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
private LocalDateTime toLocalDateTime(Object o, ZoneId zoneId) {
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
throw new DatabaseException("Didn't understand date string: " + s);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public class InsertReturning extends DerbyExample {
|
|||
new Schema()
|
||||
.addTable("t")
|
||||
.addColumn("pk").primaryKey().table()
|
||||
.addColumn("d").asDate().table()
|
||||
.addColumn("d").asLocalDateTime().table()
|
||||
.addColumn("s").asString(80).schema()
|
||||
.addSequence("pk_seq").schema().execute(db);
|
||||
|
||||
|
@ -33,7 +33,7 @@ public class InsertReturning extends DerbyExample {
|
|||
Long pk = db.toInsert(
|
||||
"insert into t (pk,d,s) values (?,?,?)")
|
||||
.argPkSeq("pk_seq")
|
||||
.argDateNowPerDb()
|
||||
.argLocalDateTimeNowPerDb()
|
||||
.argString("Hi")
|
||||
.insertReturningPkSeq("pk");
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.xbib.jdbc.query.test.example;
|
|||
import org.xbib.jdbc.query.Database;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
|
@ -19,20 +18,19 @@ public class SampleDao {
|
|||
|
||||
public void createSample(final Sample sample, Long userIdMakingChange) {
|
||||
Database db = dbp.get();
|
||||
|
||||
LocalDateTime updateTime = db.nowPerApp();
|
||||
LocalDateTime updateTime = LocalDateTime.now();
|
||||
Long sampleId = db.toInsert(
|
||||
"insert into sample (sample_id, sample_name, update_sequence, update_time) values (?,?,0,?)")
|
||||
.argPkSeq("id_seq")
|
||||
.argString(sample.getName())
|
||||
.argDate(updateTime)
|
||||
.argLocalDateTime(updateTime)
|
||||
.insertReturningPkSeq("sample_id");
|
||||
|
||||
db.toInsert("insert into sample_history (sample_id, sample_name, update_sequence, update_time, update_user_id,"
|
||||
+ " is_deleted) values (?,?,0,?,?,'N')")
|
||||
.argLong(sampleId)
|
||||
.argString(sample.getName())
|
||||
.argDate(updateTime)
|
||||
.argLocalDateTime(updateTime)
|
||||
.argLong(userIdMakingChange)
|
||||
.insert(1);
|
||||
|
||||
|
@ -61,20 +59,20 @@ public class SampleDao {
|
|||
// Insert the history row first, so it will fail (non-unique sample_id + update_sequence)
|
||||
// if someone else modified the row. This is an optimistic locking strategy.
|
||||
int newUpdateSequence = sample.getUpdateSequence() + 1;
|
||||
LocalDateTime newUpdateTime = db.nowPerApp();
|
||||
LocalDateTime newUpdateTime = LocalDateTime.now();
|
||||
db.toInsert("insert into sample_history (sample_id, sample_name, update_sequence, update_time, update_user_id,"
|
||||
+ " is_deleted) values (?,?,?,?,?,'N')")
|
||||
.argLong(sample.getSampleId())
|
||||
.argString(sample.getName())
|
||||
.argInteger(newUpdateSequence)
|
||||
.argDate(newUpdateTime)
|
||||
.argLocalDateTime(newUpdateTime)
|
||||
.argLong(userIdMakingChange)
|
||||
.insert(1);
|
||||
|
||||
db.toUpdate("update sample set sample_name=?, update_sequence=?, update_time=? where sample_id=?")
|
||||
.argString(sample.getName())
|
||||
.argInteger(newUpdateSequence)
|
||||
.argDate(newUpdateTime)
|
||||
.argLocalDateTime(newUpdateTime)
|
||||
.argLong(sample.getSampleId())
|
||||
.update(1);
|
||||
|
||||
|
@ -89,13 +87,13 @@ public class SampleDao {
|
|||
// Insert the history row first, so it will fail (non-unique sample_id + update_sequence)
|
||||
// if someone else modified the row. This is an optimistic locking strategy.
|
||||
int newUpdateSequence = sample.getUpdateSequence() + 1;
|
||||
LocalDateTime newUpdateTime = db.nowPerApp();
|
||||
LocalDateTime newUpdateTime = LocalDateTime.now();
|
||||
db.toInsert("insert into sample_history (sample_id, sample_name, update_sequence, update_time, update_user_id,"
|
||||
+ " is_deleted) values (?,?,?,?,?,'Y')")
|
||||
.argLong(sample.getSampleId())
|
||||
.argString(sample.getName())
|
||||
.argInteger(newUpdateSequence)
|
||||
.argDate(newUpdateTime)
|
||||
.argLocalDateTime(newUpdateTime)
|
||||
.argLong(userIdMakingChange)
|
||||
.insert(1);
|
||||
|
||||
|
|
Loading…
Reference in a new issue