Support quoted identifiers in SimpleJdbcInsert

See gh-24013
This commit is contained in:
Kita, Maksim
2019-11-18 10:20:15 +03:00
committed by Sam Brannen
parent 070590cb11
commit d39034754f
7 changed files with 110 additions and 1 deletions

View File

@@ -77,6 +77,8 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
/** Collection of TableParameterMetaData objects. */
private final List<TableParameterMetaData> tableParameterMetaData = new ArrayList<>();
/** the string used to quote SQL identifiers. */
private String identifierQuoteString = "";
/**
* Constructor used to initialize with provided database meta-data.
@@ -213,6 +215,15 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
logger.warn("Error retrieving 'DatabaseMetaData.storesLowerCaseIdentifiers': " + ex.getMessage());
}
}
try {
this.identifierQuoteString = databaseMetaData.getIdentifierQuoteString();
}
catch (SQLException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Error retrieving 'DatabaseMetaData.getIdentifierQuoteString': " + ex.getMessage());
}
}
}
@Override
@@ -293,6 +304,14 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
return this.databaseVersion;
}
/**
* Provide access to identifier quote string.
*/
@Override
public String getIdentifierQuoteString() {
return this.identifierQuoteString;
}
/**
* Method supporting the meta-data processing for a table.
*/

View File

@@ -79,6 +79,9 @@ public class TableMetaDataContext {
// Are we using generated key columns
private boolean generatedKeyColumnsUsed = false;
// Are we using escaping for SQL identifiers
private boolean usingEscaping = false;
/**
* Set the name of the table for this context.
@@ -276,13 +279,24 @@ public class TableMetaDataContext {
for (String key : generatedKeyNames) {
keys.add(key.toUpperCase());
}
String identifierQuoteString = "";
if (this.metaDataProvider != null && this.usingEscaping) {
identifierQuoteString = this.metaDataProvider.getIdentifierQuoteString();
}
StringBuilder insertStatement = new StringBuilder();
insertStatement.append("INSERT INTO ");
if (getSchemaName() != null) {
insertStatement.append(identifierQuoteString);
insertStatement.append(getSchemaName());
insertStatement.append('.');
insertStatement.append(getTableName());
insertStatement.append(identifierQuoteString);
}
else {
insertStatement.append(identifierQuoteString);
insertStatement.append(getTableName());
insertStatement.append(identifierQuoteString);
}
insertStatement.append(getTableName());
insertStatement.append(" (");
int columnCount = 0;
for (String columnName : getTableColumns()) {
@@ -291,7 +305,9 @@ public class TableMetaDataContext {
if (columnCount > 1) {
insertStatement.append(", ");
}
insertStatement.append(identifierQuoteString);
insertStatement.append(columnName);
insertStatement.append(identifierQuoteString);
}
}
insertStatement.append(") VALUES(");
@@ -381,4 +397,11 @@ public class TableMetaDataContext {
return obtainMetaDataProvider().isGeneratedKeysColumnNameArraySupported();
}
public boolean isUsingEscaping() {
return this.usingEscaping;
}
public void setUsingEscaping(boolean usingEscaping) {
this.usingEscaping = usingEscaping;
}
}

View File

@@ -139,4 +139,11 @@ public interface TableMetaDataProvider {
*/
List<TableParameterMetaData> getTableParameterMetaData();
/**
* Retrieves the string used to quote SQL identifiers. This method returns a space " " if identifier quoting is not supported.
* {@link DatabaseMetaData#getIdentifierQuoteString()}
* @return database identifier quote string.
*/
String getIdentifierQuoteString();
}

View File

@@ -236,6 +236,20 @@ public abstract class AbstractJdbcInsert {
return this.insertTypes;
}
/**
* Set using using escaping.
*/
public void setUsingEscaping(boolean usingEscaping) {
this.tableMetaDataContext.setUsingEscaping(usingEscaping);
}
/**
* Get using escaping.
*/
public boolean isUsingEscaping() {
return this.tableMetaDataContext.isUsingEscaping();
}
//-------------------------------------------------------------------------
// Methods handling compilation issues

View File

@@ -114,6 +114,12 @@ public class SimpleJdbcInsert extends AbstractJdbcInsert implements SimpleJdbcIn
return this;
}
@Override
public SimpleJdbcInsert usingEscaping(boolean usingEscaping) {
setUsingEscaping(usingEscaping);
return this;
}
@Override
public int execute(Map<String, ?> args) {
return doExecute(args);

View File

@@ -82,6 +82,13 @@ public interface SimpleJdbcInsertOperations {
*/
SimpleJdbcInsertOperations includeSynonymsForTableColumnMetaData();
/**
* Specify should sql identifiers be quoted.
* @param usingEscaping should sql identifiers be quoted
* @return the instance of this SimpleJdbcInsert
*/
SimpleJdbcInsertOperations usingEscaping(boolean usingEscaping);
/**
* Execute the insert using the values passed in.

View File

@@ -138,4 +138,37 @@ class SimpleJdbcInsertTests {
verify(tableResultSet).close();
}
@Test
public void testSimpleJdbcInsert() {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(dataSource).withTableName("T").usingColumns("F", "S");
jdbcInsert.compile();
String expected = "INSERT INTO T (F, S) VALUES(?, ?)";
String actual = jdbcInsert.getInsertString();
assertThat(actual).isEqualTo(expected);
}
@Test
public void testSimpleJdbcInsertWithEscapingWithSchemaName() throws Exception {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(dataSource).withSchemaName("S").withTableName("T").usingColumns("F", "S").usingEscaping(true);
given(databaseMetaData.getIdentifierQuoteString()).willReturn("`");
jdbcInsert.compile();
String expected = "INSERT INTO `S.T` (`F`, `S`) VALUES(?, ?)";
String actual = jdbcInsert.getInsertString();
assertThat(actual).isEqualTo(expected);
}
@Test
public void testSimpleJdbcInsertWithEscapingWithoutSchemaName() throws Exception {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(dataSource).withTableName("T").usingColumns("F", "S").usingEscaping(true);
given(databaseMetaData.getIdentifierQuoteString()).willReturn("`");
jdbcInsert.compile();
String expected = "INSERT INTO `T` (`F`, `S`) VALUES(?, ?)";
String actual = jdbcInsert.getInsertString();
assertThat(actual).isEqualTo(expected);
}
}