You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2022/08/21 18:36:25 UTC
[empire-db] branch master updated: EMPIREDB-394 cleanup DBMSHandler
This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/master by this push:
new 0a54b99a EMPIREDB-394 cleanup DBMSHandler
0a54b99a is described below
commit 0a54b99ab7dc660e172a412d26bba2a0d42359ec
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Sun Aug 21 20:36:23 2022 +0200
EMPIREDB-394 cleanup DBMSHandler
---
.../java/org/apache/empire/db/DBDDLGenerator.java | 2 +-
.../java/org/apache/empire/db/DBSQLBuilder.java | 337 +++++++++++++++++----
.../apache/empire/db/expr/column/DBValueExpr.java | 22 +-
.../java/org/apache/empire/dbms/DBMSHandler.java | 12 -
.../org/apache/empire/dbms/DBMSHandlerBase.java | 220 --------------
.../empire/dbms/derby/DerbyDDLGenerator.java | 2 +-
.../apache/empire/dbms/mysql/DBMSHandlerMySQL.java | 75 +++--
.../dbms/postgresql/PostgresDDLGenerator.java | 2 +-
.../empire/dbms/sqlserver/DBMSHandlerMSSQL.java | 65 ++--
9 files changed, 380 insertions(+), 357 deletions(-)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java b/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java
index 1c37980b..db607d41 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java
@@ -232,7 +232,7 @@ public abstract class DBDDLGenerator<T extends DBMSHandler>
// Default Value
if (isDDLColumnDefaults() && !c.isAutoGenerated() && c.getDefaultValue()!=null)
{ sql.append(" DEFAULT ");
- sql.append(dbms.getValueString(c.getDefaultValue(), c.getDataType()));
+ sql.appendValue(c.getDataType(), c.getDefaultValue());
}
// Nullable
if (c.isRequired() || c.isAutoGenerated())
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java b/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java
index 420be5df..5f7864ad 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java
@@ -18,14 +18,21 @@
*/
package org.apache.empire.db;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.util.Collection;
+import java.util.Date;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.OptionEntry;
+import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.DataType;
import org.apache.empire.dbms.DBMSHandler;
import org.apache.empire.dbms.DBSqlPhrase;
import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.NotSupportedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,13 +43,15 @@ import org.slf4j.LoggerFactory;
*/
public abstract class DBSQLBuilder implements Appendable
{
- private static final Logger log = LoggerFactory.getLogger(DBSQLBuilder.class);
-
- private final DBMSHandler dbms;
-
- private final StringBuilder sql = new StringBuilder(64);
-
- private DBCmdParamList cmdParamList;
+ private static final Logger log = LoggerFactory.getLogger(DBSQLBuilder.class);
+
+ protected static final char TEXT_DELIMITER = '\'';
+
+ protected final DBMSHandler dbms;
+
+ protected final StringBuilder sql = new StringBuilder(64);
+
+ protected DBCmdParamList cmdParamList;
/**
* Don't use this directly
@@ -58,6 +67,15 @@ public abstract class DBSQLBuilder implements Appendable
this.cmdParamList = cmdParamList;
}
+ /**
+ * returns the SQL as a String
+ */
+ @Override
+ public String toString()
+ {
+ return sql.toString();
+ }
+
/*
* getters
*/
@@ -104,6 +122,23 @@ public abstract class DBSQLBuilder implements Appendable
sql.append(sqlLiteral, start, end);
return this;
}
+
+ @Override
+ public DBSQLBuilder append(char c)
+ {
+ sql.append(c);
+ return this;
+ }
+
+ public DBSQLBuilder append(long l) {
+ sql.append(l);
+ return this;
+ }
+
+ public DBSQLBuilder append(double d) {
+ sql.append(d);
+ return this;
+ }
public DBSQLBuilder append(DBSqlPhrase phrase)
{
@@ -113,66 +148,35 @@ public abstract class DBSQLBuilder implements Appendable
public void append(DBCommandExpr subQueryCmd)
{
- // subQueryCmd.addSQL(this, DBExpr.CTX_DEFAULT);
+ // append select
sql.append(subQueryCmd.getSelect());
-
+ // check params
DBCmdParams params = subQueryCmd.getParams();
if (params.isEmpty())
return;
-
+ // cmdParamList
+ if (cmdParamList==null)
+ throw new NotSupportedException(this, "append command with params");
+ // merge
cmdParamList.mergeSubqueryParams(params);
-
- /*
- // Check CmdParams
- Object[] paramValues = subQueryCmd.getParamValues();
- if (paramValues!=null && paramValues.length>0)
- { // Params Available
- cmdParamList.mergeSubqueryParams(paramValues);
- }
- */
}
- @Override
- public DBSQLBuilder append(char c)
+ /**
+ * Appends the SQL representation of a value
+ * @param dataType the DataType
+ * @param value an DBExpr object, array or a basis data type(e.g. int, String)
+ */
+ public void appendValue(DataType type, Object value)
{
- sql.append(c);
- return this;
+ appendValue(type, value, DBExpr.CTX_DEFAULT, "+");
}
- public DBSQLBuilder append(boolean b) {
- sql.append(b);
- return this;
- }
-
- public DBSQLBuilder append(int i) {
- sql.append(i);
- return this;
- }
-
- public DBSQLBuilder append(long l) {
- sql.append(l);
- return this;
- }
-
- public DBSQLBuilder append(float f) {
- sql.append(f);
- return this;
- }
-
- public DBSQLBuilder append(double d) {
- sql.append(d);
- return this;
- }
-
/**
* Appends the SQL representation of a value
- *
- * @param StringBuilder but the SQL builder
* @param dataType the DataType
* @param value an DBExpr object, array or a basis data type(e.g. int, String)
* @param context the context of the DBColumnExpr object
* @param arraySep the separator value
- * @return the new SQL-Command
*/
public void appendValue(DataType dataType, Object value, long context, String arraySep)
{
@@ -211,7 +215,7 @@ public abstract class DBSQLBuilder implements Appendable
}
else
{ // Get Value Expression from dmbs
- sql.append(dbms.getValueString(value, dataType));
+ appendSimpleValue(dataType, value);
}
}
@@ -260,12 +264,233 @@ public abstract class DBSQLBuilder implements Appendable
}
}
+ /*
+ * internal
+ */
+
/**
- * returns the SQL as a String
+ * Returns a sql string for a given value.
+ * Text will be enclosed in single quotes and existing single quotes will be doubled.
+ * Empty strings are treated as null.
+ * The syntax of Date, Datetime and Boolean values are DBMS specific.
+ *
+ * @param value the value which is inserted to the new String
+ * @param type the sql data type of the supplied value
+ * @return the sql string representing this value
*/
- @Override
- public String toString()
+ protected void appendSimpleValue(DataType type, Object value)
+ {
+ if (value instanceof Enum<?>)
+ { // convert enum
+ log.warn("Enum of type {} supplied for getValueString. Converting value...", value.getClass().getName());
+ value = ObjectUtils.getEnumValue((Enum<?>)value, type.isNumeric());
+ }
+ if (ObjectUtils.isEmpty(value))
+ { // null
+ sql.append(DBSqlPhrase.SQL_NULL);
+ return;
+ }
+ // set string buffer
+ switch (type)
+ {
+ case DATE:
+ sql.append(getDateTimeString(value, DBSqlPhrase.SQL_DATE_TEMPLATE, DBSqlPhrase.SQL_DATE_PATTERN, DBSqlPhrase.SQL_CURRENT_DATE));
+ return;
+ case TIME:
+ sql.append(getDateTimeString(value, DBSqlPhrase.SQL_TIME_TEMPLATE, DBSqlPhrase.SQL_TIME_PATTERN, DBSqlPhrase.SQL_CURRENT_TIME));
+ return;
+ case DATETIME:
+ String text;
+ // Only date (without time) provided?
+ if (!DBDatabase.SYSDATE.equals(value) && !(value instanceof Date) && ObjectUtils.lengthOf(value)<=10)
+ text = getDateTimeString(value, DBSqlPhrase.SQL_DATE_TEMPLATE, DBSqlPhrase.SQL_DATE_PATTERN, DBSqlPhrase.SQL_CURRENT_TIMESTAMP);
+ else // Complete Date-Time Object with time
+ text = getDateTimeString(value, DBSqlPhrase.SQL_DATETIME_TEMPLATE, DBSqlPhrase.SQL_DATETIME_PATTERN, DBSqlPhrase.SQL_CURRENT_TIMESTAMP);
+ sql.append(text);
+ return;
+ case TIMESTAMP:
+ sql.append(getDateTimeString(value, DBSqlPhrase.SQL_TIMESTAMP_TEMPLATE, DBSqlPhrase.SQL_TIMESTAMP_PATTERN, DBSqlPhrase.SQL_CURRENT_TIMESTAMP));
+ return;
+ case VARCHAR:
+ case CHAR:
+ case CLOB:
+ case UNIQUEID:
+ appendStringLiteral(type, value);
+ return;
+ case BOOL:
+ // Get Boolean value
+ boolean boolVal = false;
+ if (value instanceof Boolean)
+ { boolVal = ((Boolean) value).booleanValue();
+ }
+ else
+ { // Boolean from String
+ boolVal = stringToBoolean(value.toString());
+ }
+ sql.append((boolVal) ? DBSqlPhrase.SQL_BOOLEAN_TRUE : DBSqlPhrase.SQL_BOOLEAN_FALSE);
+ return;
+ case INTEGER:
+ case DECIMAL:
+ case FLOAT:
+ sql.append(getNumberString(value, type));
+ return;
+ case BLOB:
+ throw new NotSupportedException(this, "appendSimpleValue(DataType.BLOB)");
+ case AUTOINC:
+ case UNKNOWN:
+ /* Allow expressions */
+ sql.append(value.toString());
+ return;
+ default:
+ log.warn("Unknown DataType {} for getValueString().", type);
+ sql.append(value.toString());
+ }
+ }
+
+ /**
+ * encodes a Date value for an SQL command string.
+ * @param value
+ * @param sqlTemplate
+ * @param sqlPattern
+ * @param sqlCurrentDate
+ * @return
+ */
+ protected String getDateTimeString(Object value, DBSqlPhrase sqlTemplate, DBSqlPhrase sqlPattern, DBSqlPhrase sqlCurrentDate)
{
- return sql.toString();
+ // is it a sysdate expression
+ if (DBDatabase.SYSDATE.equals(value))
+ return dbms.getSQLPhrase(sqlCurrentDate);
+ // Format the date (ymd)
+ Timestamp ts;
+ if ((value instanceof Timestamp))
+ { // We have a timestamp
+ ts = (Timestamp)value;
+ }
+ else if ((value instanceof Date))
+ { // Convert Date to Timestamp
+ ts = new Timestamp(((Date)value).getTime());
+ }
+ else if ((value instanceof LocalDate))
+ { // Convert LocalDate to Timestamp
+ ts = java.sql.Timestamp.valueOf(((LocalDate)value).atStartOfDay());
+ }
+ else if ((value instanceof LocalDateTime))
+ { // Convert LocalDateTime to Timestamp
+ ts = java.sql.Timestamp.valueOf((LocalDateTime)value);
+ }
+ else
+ { // "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]"
+ String dtValue = value.toString().trim();
+ try
+ { // parse timestamp
+ ts = Timestamp.valueOf(dtValue);
+ } catch (Throwable e) {
+ // Invalid date
+ log.error("Unable to parse date value "+dtValue, e);
+ throw new InvalidArgumentException("value", value);
+ }
+ }
+ // Convert to String
+ String pattern = dbms.getSQLPhrase(sqlPattern);
+ SimpleDateFormat sqlFormat = new SimpleDateFormat(dbms.getSQLPhrase(sqlPattern));
+ String datetime = sqlFormat.format(ts);
+ // Add micro / nanoseconds
+ int nanos = (ts.getNanos() % 1000000);
+ if (pattern.endsWith(".SSS") && nanos>0)
+ { // Add nanoseconds
+ if (((nanos) % 100)>0)
+ datetime += String.format("%06d", nanos);
+ else
+ datetime += String.format("%04d",(nanos/100));
+ }
+ // Now Build String
+ String template = dbms.getSQLPhrase(sqlTemplate);
+ return StringUtils.replace(template, "{0}", datetime);
+ }
+
+ /**
+ * encodes Text values for an SQL command string.
+ * @param type date type (can only be TEXT, CHAR, CLOB and UNIQUEID)
+ * @param text the text to be encoded
+ * @return the encoded sql value
+ */
+ protected void appendStringLiteral(DataType type, Object value)
+ { // text
+ if (value==null)
+ { append(DBSqlPhrase.SQL_NULL);
+ return;
+ }
+ String text = value.toString();
+ sql.append(TEXT_DELIMITER);
+ if (DBDatabase.EMPTY_STRING.equals(text)==false)
+ escapeAndAppendLiteral(text);
+ sql.append(TEXT_DELIMITER);
+ }
+
+ /**
+ * this helper function doubles up single quotes for SQL
+ */
+ protected void escapeAndAppendLiteral(String value)
+ {
+ int pos = 0;
+ int delim;
+ // find delimiter
+ while ((delim = value.indexOf(TEXT_DELIMITER, pos))>=0)
+ { // append
+ if (delim>pos)
+ sql.append(value.substring(pos, delim));
+ // double up
+ sql.append("''");
+ // next
+ pos = delim + 1;
+ }
+ if (pos==0)
+ sql.append(value); // add entire string
+ else if (pos < value.length())
+ sql.append(value.substring(pos)); // add the rest
}
+
+ /**
+ * encodes a numeric value for an SQL command string.
+ * @param value the numeric value
+ * @param type the number data type
+ * @return the string representation of the number
+ */
+ protected String getNumberString(Object value, DataType type)
+ {
+ // already a number
+ if (value instanceof Number)
+ return value.toString();
+
+ // check if it is a number
+ String s = value.toString();
+ boolean integerOnly = (type==DataType.INTEGER);
+ for (int i=0; i<s.length(); i++)
+ {
+ char c = s.charAt(i);
+ if (c>='0' && c<='9')
+ continue; // OK
+ if (c=='-' || c=='+')
+ continue; // OK
+ if (c==' ' && i>0)
+ return s.substring(0,i);
+ // check
+ if (integerOnly || (c!='.' && c!=','))
+ throw new NumberFormatException(s);
+ }
+ return s;
+ }
+
+ /**
+ * this function converts a string containing a boolean expression to a boolean.
+ * @param value the string containing a boolean expression
+ * @return true if the string contains either "true", "y" or "1" or false otherwise
+ */
+ protected boolean stringToBoolean(final String value)
+ {
+ return "1".equals(value) ||
+ "true".equalsIgnoreCase(value) ||
+ "y".equalsIgnoreCase(value);
+ }
+
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
index 18f60eb0..db7f71de 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
@@ -27,10 +27,10 @@ import org.apache.empire.data.DataType;
import org.apache.empire.db.DBColumn;
import org.apache.empire.db.DBColumnExpr;
import org.apache.empire.db.DBDatabase;
-import org.apache.empire.db.DBExpr;
import org.apache.empire.db.DBSQLBuilder;
-import org.apache.empire.dbms.DBMSHandler;
import org.apache.empire.xml.XMLUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
@@ -45,6 +45,7 @@ import org.w3c.dom.Element;
public class DBValueExpr extends DBColumnExpr
{
// *Deprecated* private static final long serialVersionUID = 1L;
+ private static final Logger log = LoggerFactory.getLogger(DBValueExpr.class);
public final DBDatabase db;
public final DataType type;
@@ -234,21 +235,10 @@ public class DBValueExpr extends DBColumnExpr
@Override
public void addSQL(DBSQLBuilder sql, long context)
{
- if (value instanceof DBExpr)
- { // its an expression
- ((DBExpr)value).addSQL(sql, context);
- }
+ if ((context & CTX_VALUE)!=0)
+ sql.appendValue(getDataType(), value);
else
- { // unpack
- DataType dataType = getDataType();
- Object dataValue = value;
- if (dataValue instanceof Enum<?>)
- dataValue = ObjectUtils.getEnumValue((Enum<?>)dataValue, dataType.isNumeric());
- // convert value to sql literal
- DBMSHandler dbms = db.getDbms();
- String text = (dbms!=null) ? dbms.getValueString(dataValue, dataType) : ObjectUtils.getString(dataValue);
- sql.append(text);
- }
+ log.warn("Cannot add SQL for DBValueExpr using context {}", context);
}
/**
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java
index 84f12491..3d6583c5 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java
@@ -116,18 +116,6 @@ public interface DBMSHandler
*/
String getConvertPhrase(DataType destType, DataType srcType, Object format);
- /**
- * Creates a sql string for a given value.
- * Text will be enclosed in single quotes and existing single quotes will be doubled.
- * Empty strings are treated as null.
- * Syntax of Date, Datetime and Boolean values are vendor specific.
- *
- * @param value the value which is inserted to the new String
- * @param type the sql data type of the supplied value
- * @return the sql string representing this value
- */
- String getValueString(Object value, DataType type);
-
/**
* Returns a DMBS-Timestamp that is used for record updates.
* @param conn the connection that might be used
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
index 0067880e..2f25cdb5 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
@@ -24,9 +24,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@@ -71,8 +68,6 @@ import org.slf4j.LoggerFactory;
public abstract class DBMSHandlerBase implements DBMSHandler
{
private static final Logger log = LoggerFactory.getLogger(DBMSHandler.class);
-
- protected static final char TEXT_DELIMITER = '\'';
// Illegal name chars and reserved SQL keywords
protected static final char[] ILLEGAL_NAME_CHARS = new char[] { '@', '?', '>', '=', '<', ';', ':',
@@ -529,75 +524,6 @@ public abstract class DBMSHandlerBase implements DBMSHandler
return rset.getObject(columnIndex);
}
}
-
- /**
- * Returns a sql string for a given value.
- * Text will be enclosed in single quotes and existing single quotes will be doubled.
- * Empty strings are treated as null.
- * The syntax of Date, Datetime and Boolean values are DBMS specific.
- *
- * @param value the value which is inserted to the new String
- * @param type the sql data type of the supplied value
- * @return the sql string representing this value
- */
- @Override
- public String getValueString(Object value, DataType type)
- {
- if (value instanceof Enum<?>)
- { // convert enum
- log.warn("Enum of type {} supplied for getValueString. Converting value...", value.getClass().getName());
- value = ObjectUtils.getEnumValue((Enum<?>)value, type.isNumeric());
- }
- if (ObjectUtils.isEmpty(value))
- { // null
- return getSQLPhrase(DBSqlPhrase.SQL_NULL);
- }
- // set string buffer
- switch (type)
- {
- case DATE:
- return getSQLDateTimeString(value, DBSqlPhrase.SQL_DATE_TEMPLATE, DBSqlPhrase.SQL_DATE_PATTERN, DBSqlPhrase.SQL_CURRENT_DATE);
- case TIME:
- return getSQLDateTimeString(value, DBSqlPhrase.SQL_TIME_TEMPLATE, DBSqlPhrase.SQL_TIME_PATTERN, DBSqlPhrase.SQL_CURRENT_TIME);
- case DATETIME:
- // Only date (without time) provided?
- if (!DBDatabase.SYSDATE.equals(value) && !(value instanceof Date) && ObjectUtils.lengthOf(value)<=10)
- return getSQLDateTimeString(value, DBSqlPhrase.SQL_DATE_TEMPLATE, DBSqlPhrase.SQL_DATE_PATTERN, DBSqlPhrase.SQL_CURRENT_TIMESTAMP);
- // Complete Date-Time Object with time
- return getSQLDateTimeString(value, DBSqlPhrase.SQL_DATETIME_TEMPLATE, DBSqlPhrase.SQL_DATETIME_PATTERN, DBSqlPhrase.SQL_CURRENT_TIMESTAMP);
- case TIMESTAMP:
- return getSQLDateTimeString(value, DBSqlPhrase.SQL_TIMESTAMP_TEMPLATE, DBSqlPhrase.SQL_TIMESTAMP_PATTERN, DBSqlPhrase.SQL_CURRENT_TIMESTAMP);
- case VARCHAR:
- case CHAR:
- case CLOB:
- case UNIQUEID:
- return getSQLStringLiteral(type, value);
- case BOOL:
- // Get Boolean value
- boolean boolVal = false;
- if (value instanceof Boolean)
- { boolVal = ((Boolean) value).booleanValue();
- }
- else
- { // Boolean from String
- boolVal = stringToBoolean(value.toString());
- }
- return getSQLPhrase((boolVal) ? DBSqlPhrase.SQL_BOOLEAN_TRUE : DBSqlPhrase.SQL_BOOLEAN_FALSE);
- case INTEGER:
- case DECIMAL:
- case FLOAT:
- return getSQLNumberString(value, type);
- case BLOB:
- throw new NotSupportedException(this, "getValueString(?, DataType.BLOB)");
- case AUTOINC:
- case UNKNOWN:
- /* Allow expressions */
- return value.toString();
- default:
- log.warn("Unknown DataType {} for getValueString().", type);
- return value.toString();
- }
- }
/**
* Executes the select, update or delete SQL-Command with a Statement object.
@@ -981,151 +907,5 @@ public abstract class DBMSHandlerBase implements DBMSHandler
log.trace("Statement param {} set to '{}'", paramIndex, value);
}
}
-
- /**
- * encodes a numeric value for an SQL command string.
- * @param value the numeric value
- * @param type the number data type
- * @return the string reprentation of the number
- */
- protected String getSQLNumberString(Object value, DataType type)
- {
- // already a number
- if (value instanceof Number)
- return value.toString();
-
- // check if it is a number
- String s = value.toString();
- boolean integerOnly = (type==DataType.INTEGER);
- for (int i=0; i<s.length(); i++)
- {
- char c = s.charAt(i);
- if (c>='0' && c<='9')
- continue; // OK
- if (c=='-' || c=='+')
- continue; // OK
- if (c==' ' && i>0)
- return s.substring(0,i);
- // check
- if (integerOnly || (c!='.' && c!=','))
- throw new NumberFormatException(s);
- }
- return s;
- }
-
- /**
- * encodes a Date value for an SQL command string.
- * @param value
- * @param sqlTemplate
- * @param sqlPattern
- * @param sqlCurrentDate
- * @return
- */
- protected String getSQLDateTimeString(Object value, DBSqlPhrase sqlTemplate, DBSqlPhrase sqlPattern, DBSqlPhrase sqlCurrentDate)
- {
- // is it a sysdate expression
- if (DBDatabase.SYSDATE.equals(value))
- return getSQLPhrase(sqlCurrentDate);
- // Format the date (ymd)
- Timestamp ts;
- if ((value instanceof Timestamp))
- { // We have a timestamp
- ts = (Timestamp)value;
- }
- else if ((value instanceof Date))
- { // Convert Date to Timestamp
- ts = new Timestamp(((Date)value).getTime());
- }
- else if ((value instanceof LocalDate))
- { // Convert LocalDate to Timestamp
- ts = java.sql.Timestamp.valueOf(((LocalDate)value).atStartOfDay());
- }
- else if ((value instanceof LocalDateTime))
- { // Convert LocalDateTime to Timestamp
- ts = java.sql.Timestamp.valueOf((LocalDateTime)value);
- }
- else
- { // "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]"
- String dtValue = value.toString().trim();
- try
- { // parse timestamp
- ts = Timestamp.valueOf(dtValue);
- } catch (Throwable e) {
- // Invalid date
- log.error("Unable to parse date value "+dtValue, e);
- throw new InvalidArgumentException("value", value);
- }
- }
- // Convert to String
- String pattern = getSQLPhrase(sqlPattern);
- SimpleDateFormat sqlFormat = new SimpleDateFormat(getSQLPhrase(sqlPattern));
- String datetime = sqlFormat.format(ts);
- // Add micro / nanoseconds
- int nanos = (ts.getNanos() % 1000000);
- if (pattern.endsWith(".SSS") && nanos>0)
- { // Add nanoseconds
- if (((nanos) % 100)>0)
- datetime += String.format("%06d", nanos);
- else
- datetime += String.format("%04d",(nanos/100));
- }
- // Now Build String
- String template = getSQLPhrase(sqlTemplate);
- return StringUtils.replace(template, "{0}", datetime);
- }
-
- /**
- * encodes Text values for an SQL command string.
- * @param type date type (can only be TEXT, CHAR, CLOB and UNIQUEID)
- * @param text the text to be encoded
- * @return the encoded sql value
- */
- protected String getSQLStringLiteral(DataType type, Object value)
- { // text
- if (value==null)
- return getSQLPhrase(DBSqlPhrase.SQL_NULL);
- String text = value.toString();
- StringBuilder sql = new StringBuilder(text.length()+2);
- sql.append(TEXT_DELIMITER);
- if (DBDatabase.EMPTY_STRING.equals(text)==false)
- appendSQLTextValue(sql, text);
- sql.append(TEXT_DELIMITER);
- return sql.toString();
- }
-
- /**
- * this helper function doubles up single quotes for SQL
- */
- protected void appendSQLTextValue(StringBuilder sql, String value)
- {
- int pos = 0;
- int delim;
- // find delimiter
- while ((delim = value.indexOf(TEXT_DELIMITER, pos))>=0)
- { // append
- if (delim>pos)
- sql.append(value.substring(pos, delim));
- // double up
- sql.append("''");
- // next
- pos = delim + 1;
- }
- if (pos==0)
- sql.append(value); // add entire string
- else if (pos < value.length())
- sql.append(value.substring(pos)); // add the rest
- }
-
- /**
- * this function converts a string containing a boolean expression to a boolean.
- * @param value the string containing a boolean expression
- * @return true if the string contains either "true", "y" or "1" or false otherwise
- */
- protected boolean stringToBoolean(final String value)
- {
- return "1".equals(value) ||
- "true".equalsIgnoreCase(value) ||
- "y".equalsIgnoreCase(value);
- }
}
\ No newline at end of file
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/derby/DerbyDDLGenerator.java b/empire-db/src/main/java/org/apache/empire/dbms/derby/DerbyDDLGenerator.java
index 352c37e8..5dd0cd4a 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/derby/DerbyDDLGenerator.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/derby/DerbyDDLGenerator.java
@@ -76,7 +76,7 @@ public class DerbyDDLGenerator extends DBDDLGenerator<DBMSHandlerDerby>
// Default Value
if (isDDLColumnDefaults() && !c.isAutoGenerated() && c.getDefaultValue()!=null)
{ sql.append(" DEFAULT ");
- sql.append(dbms.getValueString(c.getDefaultValue(), c.getDataType()));
+ sql.appendValue(c.getDataType(), c.getDefaultValue());
}
// Nullable
if (c.isRequired() || c.isAutoGenerated())
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java b/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java
index eb07418d..ad1ddd03 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java
@@ -124,6 +124,43 @@ public class DBMSHandlerMySQL extends DBMSHandlerBase
}
}
+ /**
+ * Provides a DBSQLBuilder implementation for MySQL
+ */
+ public static class DBSQLBuilderMySQL extends DBSQLBuilder
+ {
+ public DBSQLBuilderMySQL(DBMSHandlerMySQL dbms)
+ {
+ super(dbms);
+ }
+
+ @Override
+ protected void escapeAndAppendLiteral(String value)
+ {
+ if (value.indexOf('\'') >= 0 || value.indexOf('\\') >= 0)
+ {
+ int len = value.length();
+ for (int i = 0; i < len; i++)
+ {
+ if (value.charAt(i) == '\'')
+ { // a routine to double up single quotes for SQL
+ sql.append("''");
+ }
+ else if (value.charAt(i) == '\\')
+ { // a routine to double up backslashes for MySQL
+ sql.append("\\\\");
+ }
+ else
+ { // normal
+ sql.append(value.charAt(i));
+ }
+ }
+ } else {
+ sql.append(value);
+ }
+ }
+ }
+
// Properties
private String databaseName = null;
private String characterSet = "utf8";
@@ -904,6 +941,16 @@ public class DBMSHandlerMySQL extends DBMSHandlerBase
return new DBCommandMySQL(autoPrepareStmt);
}
+ /**
+ * Creates a new MySQL SQL-Builder.
+ * @return the new DBSQLBuilder object
+ */
+ @Override
+ public DBSQLBuilder createSQLBuilder()
+ {
+ return new DBSQLBuilderMySQL(this);
+ }
+
@Override
/**
* Creates a combined command that supports limit() and skip()
@@ -1138,33 +1185,5 @@ public class DBMSHandlerMySQL extends DBMSHandlerBase
ddlGenerator.getDDLScript(type, dbo, script);
}
- /**
- * this helper function doubles up single quotes for SQL
- */
- @Override
- protected void appendSQLTextValue(StringBuilder buf, String value)
- {
- if (value.indexOf('\'') >= 0 || value.indexOf('\\') >= 0)
- {
- int len = value.length();
- for (int i = 0; i < len; i++)
- {
- if (value.charAt(i) == '\'')
- { // a routine to double up single quotes for SQL
- buf.append("''");
- }
- else if (value.charAt(i) == '\\')
- { // a routine to double up backslashes for MySQL
- buf.append("\\\\");
- } else
- {
- buf.append(value.charAt(i));
- }
- }
- } else
- {
- buf.append(value);
- }
- }
}
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresDDLGenerator.java b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresDDLGenerator.java
index 5a575318..a318b42c 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresDDLGenerator.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresDDLGenerator.java
@@ -181,7 +181,7 @@ public class PostgresDDLGenerator extends DBDDLGenerator<DBMSHandlerPostgreSQL>
// Default Value
if (isDDLColumnDefaults() && !c.isAutoGenerated() && c.getDefaultValue()!=null)
{ sql.append(" DEFAULT ");
- sql.append(dbms.getValueString(c.getDefaultValue(), c.getDataType()));
+ sql.appendValue(c.getDataType(), c.getDefaultValue());
}
// Nullable
if (c.isRequired() || c.isAutoGenerated())
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
index 6bd8f12d..70f7adab 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
@@ -59,8 +59,8 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
private static final Logger log = LoggerFactory.getLogger(DBMSHandlerMSSQL.class);
/**
- * Defines the Microsoft SQL-Server command type.
- */
+ * Provides a DBCommand implementation for Microsoft SQL-Server
+ */
public static class DBCommandMSSQL extends DBCommand
{
// *Deprecated* private static final long serialVersionUID = 1L;
@@ -103,6 +103,36 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
}
}
+ /**
+ * Provides a DBSQLBuilder implementation for Microsoft SQL-Server
+ */
+ public static class DBSQLBuilderMSSQL extends DBSQLBuilder
+ {
+ private final boolean useUnicodePrefix;
+
+ public DBSQLBuilderMSSQL(DBMSHandlerMSSQL dbms)
+ {
+ super(dbms);
+ // init
+ this.useUnicodePrefix = dbms.useUnicodePrefix;
+ }
+
+ @Override
+ protected void appendStringLiteral(DataType type, Object value)
+ { // text
+ if (value==null)
+ { append(DBSqlPhrase.SQL_NULL);
+ return;
+ }
+ String text = value.toString();
+ // for SQLSERVER utf8 support, see EMPIREDB-122
+ sql.append((useUnicodePrefix) ? "N'" : "'");
+ if (DBDatabase.EMPTY_STRING.equals(text)==false)
+ escapeAndAppendLiteral(text);
+ sql.append(TEXT_DELIMITER);
+ }
+ }
+
// Properties
private String databaseName = null;
private String objectOwner = "dbo";
@@ -275,8 +305,7 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
/**
* Creates a new Microsoft SQL-Server command object.
- *
- * @return the new DBCommandMSSQL object
+ * @return the new DBCommand object
*/
@Override
public DBCommand createCommand(boolean autoPrepareStmt)
@@ -284,6 +313,16 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
// create command object
return new DBCommandMSSQL(autoPrepareStmt);
}
+
+ /**
+ * Creates a new Microsoft SQL-Server SQL-Builder.
+ * @return the new DBSQLBuilder object
+ */
+ @Override
+ public DBSQLBuilder createSQLBuilder()
+ {
+ return new DBSQLBuilderMSSQL(this);
+ }
/**
* Returns whether or not a particular feature is supported by this dbms
@@ -452,24 +491,6 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
// automatic identity management
return null;
}
-
- /**
- * @see DBMSHandler#getSQLTextString(DataType type, Object value)
- */
- @Override
- protected String getSQLStringLiteral(DataType type, Object value)
- { // text
- if (value==null)
- return getSQLPhrase(DBSqlPhrase.SQL_NULL);
- String text = value.toString();
- StringBuilder sql = new StringBuilder(text.length()+2);
- // for SQLSERVER utf8 support, see EMPIREDB-122
- sql.append((useUnicodePrefix) ? "N'" : "'");
- if (DBDatabase.EMPTY_STRING.equals(text)==false)
- appendSQLTextValue(sql, text);
- sql.append(TEXT_DELIMITER);
- return sql.toString();
- }
/**
* Overridden. Returns a timestamp that is used for record updates created by the database server.