Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SQLLINE-440] Support legacy date/time format #478

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 61 additions & 19 deletions src/main/java/sqlline/Rows.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ abstract class Rows implements Iterator<Rows.Row> {
final DateFormat timeFormat;
final DateFormat timestampFormat;
final String nullValue;
final boolean useGetStringForDate;
final boolean useGetStringForTime;
final boolean useGetStringForTimestamp;
final boolean useGetStringForNumber;
final boolean escapeOutput;

Rows(SqlLine sqlLine, ResultSet rs) throws SQLException {
Expand All @@ -56,29 +60,61 @@ abstract class Rows implements Iterator<Rows.Row> {
primaryKeys = new Boolean[count];
if (sqlLine.getOpts().isDefault(BuiltInProperty.NUMBER_FORMAT)) {
numberFormat = null;
useGetStringForNumber = false;
} else {
final String pattern =
sqlLine.getOpts().get(BuiltInProperty.NUMBER_FORMAT);
numberFormat = new DecimalFormat(pattern,
DecimalFormatSymbols.getInstance(Locale.ROOT));
if ("".equals(pattern)) {
numberFormat = null;
useGetStringForNumber = true;
} else {
numberFormat =
new DecimalFormat(pattern,
DecimalFormatSymbols.getInstance(Locale.ROOT));
useGetStringForNumber = false;
}
}
if (sqlLine.getOpts().isDefault(BuiltInProperty.DATE_FORMAT)) {
dateFormat = null;
useGetStringForDate = false;
} else {
String pattern = sqlLine.getOpts().get(BuiltInProperty.DATE_FORMAT);
dateFormat = new SimpleDateFormat(pattern, Locale.ROOT);
String pattern =
sqlLine.getOpts().get(BuiltInProperty.DATE_FORMAT);
if ("".equals(pattern)) {
dateFormat = null;
useGetStringForDate = true;
} else {
dateFormat = new SimpleDateFormat(pattern, Locale.ROOT);
useGetStringForDate = false;
}
}
if (sqlLine.getOpts().isDefault(BuiltInProperty.TIME_FORMAT)) {
timeFormat = null;
useGetStringForTime = false;
} else {
String pattern = sqlLine.getOpts().get(BuiltInProperty.TIME_FORMAT);
timeFormat = new SimpleDateFormat(pattern, Locale.ROOT);
String pattern =
sqlLine.getOpts().get(BuiltInProperty.TIME_FORMAT);
if ("".equals(pattern)) {
timeFormat = null;
useGetStringForTime = true;
} else {
timeFormat = new SimpleDateFormat(pattern, Locale.ROOT);
useGetStringForTime = false;
}
}
if (sqlLine.getOpts().isDefault(BuiltInProperty.TIMESTAMP_FORMAT)) {
timestampFormat = null;
useGetStringForTimestamp = false;
} else {
String pattern = sqlLine.getOpts().get(BuiltInProperty.TIMESTAMP_FORMAT);
timestampFormat = new SimpleDateFormat(pattern, Locale.ROOT);
String pattern =
sqlLine.getOpts().get(BuiltInProperty.TIMESTAMP_FORMAT);
if ("".equals(pattern)) {
timestampFormat = null;
useGetStringForTimestamp = true;
} else {
timestampFormat = new SimpleDateFormat(pattern, Locale.ROOT);
useGetStringForTimestamp = false;
}
}
if (sqlLine.getOpts().isDefault(BuiltInProperty.NULL_VALUE)) {
nullValue = null;
Expand Down Expand Up @@ -268,7 +304,7 @@ class Row {
case Types.DOUBLE:
case Types.DECIMAL:
case Types.NUMERIC:
setFormat(rs.getObject(i + 1), numberFormat, i);
setFormat(rs, numberFormat, useGetStringForNumber, i);
break;
case Types.BIT:
case Types.CLOB:
Expand All @@ -279,16 +315,16 @@ class Row {
case Types.ROWID:
case Types.NCLOB:
case Types.SQLXML:
setFormat(rs.getObject(i + 1), null, i);
setFormat(rs, null, false, i);
break;
case Types.TIME:
setFormat(rs.getObject(i + 1), timeFormat, i);
setFormat(rs, timeFormat, useGetStringForTime, i);
break;
case Types.DATE:
setFormat(rs.getObject(i + 1), dateFormat, i);
setFormat(rs, dateFormat, useGetStringForDate, i);
break;
case Types.TIMESTAMP:
setFormat(rs.getObject(i + 1), timestampFormat, i);
setFormat(rs, timestampFormat, useGetStringForTimestamp, i);
break;
default:
values[i] = rs.getString(i + 1);
Expand All @@ -304,13 +340,19 @@ class Row {
}
}

private void setFormat(Object o, Format format, int i) {
if (o == null) {
values[i] = String.valueOf(nullValue);
} else if (format != null) {
values[i] = format.format(o);
private void setFormat(ResultSet rs, Format format, boolean useGetString,
int i) throws SQLException {
if (useGetString) {
values[i] = rs.getString(i + 1);
} else {
values[i] = o.toString();
Object o = rs.getObject(i + 1);
if (o == null) {
values[i] = String.valueOf(nullValue);
} else if (format != null) {
values[i] = format.format(o);
} else {
values[i] = o.toString();
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/sqlline/SqlLineOpts.java
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,10 @@ public void setNumberFormat(String numberFormat) {
propertiesMap.put(NUMBER_FORMAT, NUMBER_FORMAT.defaultValue());
return;
}
if ("".equals(numberFormat)) {
propertiesMap.put(NUMBER_FORMAT, numberFormat);
return;
}
try {
NumberFormat nf = new DecimalFormat(numberFormat,
DecimalFormatSymbols.getInstance(Locale.ROOT));
Expand Down Expand Up @@ -1052,6 +1056,9 @@ private String getValidDateTimePatternOrThrow(String dateTimePattern) {
if (DEFAULT.equalsIgnoreCase(dateTimePattern)) {
return dateTimePattern;
}
if ("".equals(dateTimePattern)) {
return dateTimePattern;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat(dateTimePattern, Locale.ROOT);
sdf.format(TEST_DATE);
Expand Down
8 changes: 4 additions & 4 deletions src/main/resources/sqlline/manual.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2322,7 +2322,7 @@ Sets the quote character in csv outputFormat. Setting to default causes usage of

dateformat

The format for how date values are displayed. Setting to default causes date values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.SimpleDateFormat. For example, the setting "YYYY_MM_dd" yields values like "1970_01_01".
The format for how date values are displayed. Setting to default causes date values to be fetched and rendered via ResultSet.getObject.toString. Setting to empty string causes date values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.SimpleDateFormat. For example, the setting "YYYY_MM_dd" yields values like "1970_01_01".

escapeOutput

Expand Down Expand Up @@ -2390,7 +2390,7 @@ The value which will be used instead of null values. Setting to default causes '

numberformat

The format for how numeric values are displayed. Setting to default causes numeric values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.DecimalFormat. For example, the setting "0.###E0" yields scientific notation with up to three fractional digits, values like "6.022E23".
The format for how numeric values are displayed. Setting to default causes numeric values to be fetched and rendered via ResultSet.getObject.toString. Setting to empty string causes numeric values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.DecimalFormat. For example, the setting "0.###E0" yields scientific notation with up to three fractional digits, values like "6.022E23".

outputformat

Expand Down Expand Up @@ -2456,11 +2456,11 @@ The style of tables used to output data for table output format.

timeformat

The format for how time values are displayed. Setting to default causes time values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.SimpleDateFormat. For example, the setting "HH:mm:ss" yields values like "14:12:11".
The format for how time values are displayed. Setting to default causes time values to be fetched and rendered via ResultSet.getObject.toString. Setting to empty string causes time values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.SimpleDateFormat. For example, the setting "HH:mm:ss" yields values like "14:12:11".

timestampformat

The format for how timestamp values are displayed. Setting to default causes timestamp values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.SimpleDateFormat. For example, the setting "dd/MM/YYYY'T'HH:mm:ss" yields values like "01/01/1970T12:32:12".
The format for how timestamp values are displayed. Setting to default causes timestamp values to be fetched and rendered via ResultSet.getObject.toString. Setting to empty string causes timestamp values to be fetched and rendered via ResultSet.getString. Any other setting results in fetch via ResultSet.getObject and rendering via java.text.SimpleDateFormat. For example, the setting "dd/MM/YYYY'T'HH:mm:ss" yields values like "01/01/1970T12:32:12".

trimscripts

Expand Down
17 changes: 16 additions & 1 deletion src/test/java/sqlline/SqlLineArgsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1473,10 +1473,13 @@ public void testTimeFormat() {
// successful patterns
final String okTimeFormat = "!set timeFormat HH:mm:ss\n";
final String defaultTimeFormat = "!set timeFormat default\n";
final String legacyTimeFormat = "!set timeFormat ''\n";
final String okDateFormat = "!set dateFormat YYYY-MM-dd\n";
final String defaultDateFormat = "!set dateFormat default\n";
final String defaultDateFormat = "!set dateFormat ''\n";
final String legacyDateFormat = "!set dateFormat default\n";
final String okTimestampFormat = "!set timestampFormat default\n";
final String defaultTimestampFormat = "!set timestampFormat default\n";
final String legacyTimestampFormat = "!set timestampFormat ''\n";

// successful cases
sqlLine.getOpts().setPropertiesFile(DEV_NULL);
Expand All @@ -1489,6 +1492,10 @@ public void testTimeFormat() {
not(
anyOf(containsString("Error setting configuration"),
containsString("Exception"))));
checkScriptFile(legacyTimeFormat, false, equalTo(SqlLine.Status.OK),
not(
anyOf(containsString("Error setting configuration"),
containsString("Exception"))));
checkScriptFile(okDateFormat, false, equalTo(SqlLine.Status.OK),
not(
anyOf(containsString("Error setting configuration"),
Expand All @@ -1497,6 +1504,10 @@ public void testTimeFormat() {
not(
anyOf(containsString("Error setting configuration"),
containsString("Exception"))));
checkScriptFile(legacyDateFormat, false, equalTo(SqlLine.Status.OK),
not(
anyOf(containsString("Error setting configuration"),
containsString("Exception"))));
checkScriptFile(okTimestampFormat, false, equalTo(SqlLine.Status.OK),
not(
anyOf(containsString("Error setting configuration"),
Expand All @@ -1505,6 +1516,10 @@ public void testTimeFormat() {
not(
anyOf(containsString("Error setting configuration"),
containsString("Exception"))));
checkScriptFile(legacyTimestampFormat, false, equalTo(SqlLine.Status.OK),
not(
anyOf(containsString("Error setting configuration"),
containsString("Exception"))));

// failed patterns
final String wrongTimeFormat = "!set timeFormat qwerty\n";
Expand Down