From 2f581c2b901a84cd03da91a7b8f0c9fed00d9b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E6=BA=90?= Date: Sun, 25 Aug 2019 20:10:15 +0800 Subject: [PATCH] =?UTF-8?q?fix=20#921=20spring=20boot=20mybatis=20?= =?UTF-8?q?=E4=BC=A0=E5=8F=82=E6=95=B0=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../druid/pool/ElasticSearchConnection.java | 18 +- ...ticSearchDruidPooledPreparedStatement.java | 9 +- .../pool/ElasticSearchPreparedStatement.java | 366 +++++++++++++++--- .../nlpcn/es4sql/query/ESActionFactory.java | 2 +- src/test/java/org/nlpcn/es4sql/JDBCTests.java | 30 +- 6 files changed, 366 insertions(+), 61 deletions(-) diff --git a/pom.xml b/pom.xml index 2971e6e3..b341514f 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.nlpcn elasticsearch-sql - 6.8.2.0 + 6.8.2.1 jar Query elasticsearch using SQL elasticsearch-sql diff --git a/src/main/java/com/alibaba/druid/pool/ElasticSearchConnection.java b/src/main/java/com/alibaba/druid/pool/ElasticSearchConnection.java index 36473886..e57fe481 100644 --- a/src/main/java/com/alibaba/druid/pool/ElasticSearchConnection.java +++ b/src/main/java/com/alibaba/druid/pool/ElasticSearchConnection.java @@ -2,7 +2,21 @@ import org.elasticsearch.client.Client; -import java.sql.*; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; @@ -33,7 +47,7 @@ public Statement createStatement() throws SQLException { @Override public PreparedStatement prepareStatement(String sql) throws SQLException { - return new ElasticSearchPreparedStatement(); + return new ElasticSearchPreparedStatement(sql); } @Override diff --git a/src/main/java/com/alibaba/druid/pool/ElasticSearchDruidPooledPreparedStatement.java b/src/main/java/com/alibaba/druid/pool/ElasticSearchDruidPooledPreparedStatement.java index c6514dcd..1104c392 100644 --- a/src/main/java/com/alibaba/druid/pool/ElasticSearchDruidPooledPreparedStatement.java +++ b/src/main/java/com/alibaba/druid/pool/ElasticSearchDruidPooledPreparedStatement.java @@ -37,7 +37,7 @@ public ResultSet executeQuery() throws SQLException { conn.beforeExecute(); try { - ObjectResult extractor = getObjectResult(true, getSql(), false, false, true); + ObjectResult extractor = getObjectResult(true, false, false, true); List headers = extractor.getHeaders(); List> lines = extractor.getLines(); @@ -67,7 +67,7 @@ public boolean execute() throws SQLException { conn.beforeExecute(); try { - ObjectResult extractor = getObjectResult(true, getSql(), false, false, true); + ObjectResult extractor = getObjectResult(true, false, false, true); List headers = extractor.getHeaders(); List> lines = extractor.getLines(); @@ -84,11 +84,10 @@ public boolean execute() throws SQLException { } } - private ObjectResult getObjectResult(boolean flat, String query, boolean includeScore, boolean includeType, boolean includeId) throws SqlParseException, SQLFeatureNotSupportedException, Exception, CsvExtractorException { + private ObjectResult getObjectResult(boolean flat, boolean includeScore, boolean includeType, boolean includeId) throws SqlParseException, SQLFeatureNotSupportedException, Exception, CsvExtractorException { SearchDao searchDao = new org.nlpcn.es4sql.SearchDao(client); - //String rewriteSQL = searchDao.explain(getSql()).explain().explain(); - + String query = ((ElasticSearchPreparedStatement) getRawPreparedStatement()).getExecutableSql(); QueryAction queryAction = searchDao.explain(query); Object execution = QueryActionElasticExecutor.executeAnyAction(searchDao.getClient(), queryAction); return new ObjectResultsExtractor(includeScore, includeType, includeId, false, queryAction).extractResults(execution, flat); diff --git a/src/main/java/com/alibaba/druid/pool/ElasticSearchPreparedStatement.java b/src/main/java/com/alibaba/druid/pool/ElasticSearchPreparedStatement.java index 6164aa15..c573b466 100644 --- a/src/main/java/com/alibaba/druid/pool/ElasticSearchPreparedStatement.java +++ b/src/main/java/com/alibaba/druid/pool/ElasticSearchPreparedStatement.java @@ -1,16 +1,92 @@ package com.alibaba.druid.pool; +import com.alibaba.druid.proxy.jdbc.JdbcParameter; +import com.alibaba.druid.proxy.jdbc.JdbcParameterDate; +import com.alibaba.druid.proxy.jdbc.JdbcParameterDecimal; +import com.alibaba.druid.proxy.jdbc.JdbcParameterImpl; +import com.alibaba.druid.proxy.jdbc.JdbcParameterInt; +import com.alibaba.druid.proxy.jdbc.JdbcParameterLong; +import com.alibaba.druid.proxy.jdbc.JdbcParameterNull; +import com.alibaba.druid.proxy.jdbc.JdbcParameterString; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.ParserException; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.support.logging.Log; +import com.alibaba.druid.support.logging.LogFactory; +import com.alibaba.druid.util.JdbcConstants; +import org.nlpcn.es4sql.query.ESActionFactory; + import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; -import java.sql.*; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; +import java.util.List; public class ElasticSearchPreparedStatement implements PreparedStatement { + private final static Log LOG = LogFactory.getLog(ElasticSearchPreparedStatement.class); + + private String sql; + private JdbcParameter[] parameters; + private int parametersSize; private ResultSet results = null; + private SQLUtils.FormatOption sqlFormatOption = new SQLUtils.FormatOption(false, false); + + public ElasticSearchPreparedStatement(String sql) { + this.sql = sql; + this.parameters = new JdbcParameter[16]; + this.parametersSize = 0; + } + + public String getSql() { + return sql; + } + + public String getExecutableSql() { + if (parametersSize < 1) { + return sql; + } + + List parameters = new ArrayList<>(parametersSize); + JdbcParameter jdbcParam; + for (int i = 0; i < parametersSize; ++i) { + jdbcParam = this.parameters[i]; + parameters.add(jdbcParam != null ? jdbcParam.getValue() : null); + } + + try { + SQLStatementParser parser = ESActionFactory.createSqlStatementParser(sql); + List statementList = parser.parseStatementList(); + return SQLUtils.toSQLString(statementList, JdbcConstants.MYSQL, parameters, sqlFormatOption); + } catch (ClassCastException | ParserException ex) { + LOG.warn("format error", ex); + return sql; + } + } + @Override public ResultSet executeQuery() throws SQLException { return null; @@ -23,87 +99,87 @@ public int executeUpdate() throws SQLException { @Override public void setNull(int parameterIndex, int sqlType) throws SQLException { - + setParameter(parameterIndex, createParameterNull(sqlType)); } @Override public void setBoolean(int parameterIndex, boolean x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.BOOLEAN, x)); } @Override public void setByte(int parameterIndex, byte x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.TINYINT, x)); } @Override public void setShort(int parameterIndex, short x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.SMALLINT, x)); } @Override public void setInt(int parameterIndex, int x) throws SQLException { - + setParameter(parameterIndex, createParameter(x)); } @Override public void setLong(int parameterIndex, long x) throws SQLException { - + setParameter(parameterIndex, createParameter(x)); } @Override public void setFloat(int parameterIndex, float x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.FLOAT, x)); } @Override public void setDouble(int parameterIndex, double x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.DOUBLE, x)); } @Override public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - + setParameter(parameterIndex, createParameter(x)); } @Override public void setString(int parameterIndex, String x) throws SQLException { - + setParameter(parameterIndex, createParameter(x)); } @Override public void setBytes(int parameterIndex, byte[] x) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BYTES, x)); } @Override public void setDate(int parameterIndex, Date x) throws SQLException { - + setParameter(parameterIndex, createParameter(x)); } @Override public void setTime(int parameterIndex, Time x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.TIME, x)); } @Override public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - + setParameter(parameterIndex, createParameter(x)); } @Override public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.AsciiInputStream, x, length)); } @Override public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.UnicodeStream, x, length)); } @Override public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BinaryInputStream, x, length)); } @Override @@ -113,12 +189,12 @@ public void clearParameters() throws SQLException { @Override public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - + setParameter(parameterIndex, createParameter(targetSqlType, x)); } @Override public void setObject(int parameterIndex, Object x) throws SQLException { - + setObjectParameter(parameterIndex, x); } @Override @@ -133,27 +209,27 @@ public void addBatch() throws SQLException { @Override public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.CharacterInputStream, reader, length)); } @Override public void setRef(int parameterIndex, Ref x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.REF, x)); } @Override public void setBlob(int parameterIndex, Blob x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.BLOB, x)); } @Override public void setClob(int parameterIndex, Clob x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.CLOB, x)); } @Override public void setArray(int parameterIndex, Array x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.ARRAY, x)); } @Override @@ -163,27 +239,27 @@ public ResultSetMetaData getMetaData() throws SQLException { @Override public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.DATE, x, cal)); } @Override public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.TIME, x, cal)); } @Override public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.TIMESTAMP, x, cal)); } @Override public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - + setParameter(parameterIndex, createParameterNull(sqlType)); } @Override public void setURL(int parameterIndex, URL x) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.URL, x)); } @Override @@ -193,97 +269,97 @@ public ParameterMetaData getParameterMetaData() throws SQLException { @Override public void setRowId(int parameterIndex, RowId x) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.ROWID, x)); } @Override public void setNString(int parameterIndex, String value) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.NVARCHAR, value)); } @Override public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.NCharacterInputStream, value, length)); } @Override public void setNClob(int parameterIndex, NClob value) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.NCLOB, value)); } @Override public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.CLOB, reader, length)); } @Override public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.BLOB, inputStream, length)); } @Override public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.NCLOB, reader, length)); } @Override public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.SQLXML, xmlObject)); } @Override public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - + setParameter(parameterIndex, createParameter(x, targetSqlType, scaleOrLength)); } @Override public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.AsciiInputStream, x, length)); } @Override public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BinaryInputStream, x, length)); } @Override public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.CharacterInputStream, reader, length)); } @Override public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.AsciiInputStream, x)); } @Override public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BinaryInputStream, x)); } @Override public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.CharacterInputStream, reader)); } @Override public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - + setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.NCharacterInputStream, value)); } @Override public void setClob(int parameterIndex, Reader reader) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.CLOB, reader)); } @Override public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.BLOB, inputStream)); } @Override public void setNClob(int parameterIndex, Reader reader) throws SQLException { - + setParameter(parameterIndex, createParameter(Types.NCLOB, reader)); } @Override @@ -303,6 +379,8 @@ public void close() throws SQLException { } this.results = null; + this.parameters = null; + this.parametersSize = 0; } @Override @@ -513,4 +591,194 @@ public boolean isWrapperFor(Class iface) throws SQLException { public void setResults(ResultSet results) { this.results = results; } + + private JdbcParameter createParameterNull(int sqlType) { + return JdbcParameterNull.valueOf(sqlType); + } + + private JdbcParameter createParameter(int sqlType, Object value) { + if (value == null) { + return JdbcParameterNull.valueOf(sqlType); + } + + return new JdbcParameterImpl(sqlType, value); + } + + private JdbcParameter createParameter(int x) { + return JdbcParameterInt.valueOf(x); + } + + private JdbcParameter createParameter(long x) { + return JdbcParameterLong.valueOf(x); + } + + private JdbcParameter createParameter(BigDecimal x) { + if (x == null) { + return JdbcParameterNull.DECIMAL; + } + + return JdbcParameterDecimal.valueOf(x); + } + + private JdbcParameter createParameter(String x) { + if (x == null) { + return JdbcParameterNull.VARCHAR; + } + + if (x.length() == 0) { + return JdbcParameterString.empty; + } + + return new JdbcParameterString(x); + } + + private JdbcParameter createParameter(java.util.Date x) { + if (x == null) { + return JdbcParameterNull.DATE; + } + + return new JdbcParameterDate(x); + } + + private JdbcParameter createParameter(int sqlType, Object value, long length) { + if (value == null) { + return JdbcParameterNull.valueOf(sqlType); + } + + return new JdbcParameterImpl(sqlType, value, length); + } + + private void setObjectParameter(int parameterIndex, Object x) { + if (x == null) { + setParameter(parameterIndex, createParameterNull(Types.OTHER)); + return; + } + + Class clazz = x.getClass(); + if (clazz == Byte.class) { + setParameter(parameterIndex, createParameter(Types.TINYINT, x)); + return; + } + + if (clazz == Short.class) { + setParameter(parameterIndex, createParameter(Types.SMALLINT, x)); + return; + } + + if (clazz == Integer.class) { + setParameter(parameterIndex, createParameter((Integer) x)); + return; + } + + if (clazz == Long.class) { + setParameter(parameterIndex, createParameter((Long) x)); + return; + } + + if (clazz == String.class) { + setParameter(parameterIndex, createParameter((String) x)); + return; + } + + if (clazz == BigDecimal.class) { + setParameter(parameterIndex, createParameter((BigDecimal) x)); + return; + } + + if (clazz == Float.class) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.FLOAT, x)); + return; + } + + if (clazz == Double.class) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.DOUBLE, x)); + return; + } + + if (clazz == java.sql.Date.class || clazz == java.util.Date.class) { + setParameter(parameterIndex, createParameter((java.util.Date) x)); + return; + } + + if (clazz == java.sql.Timestamp.class) { + setParameter(parameterIndex, createParameter((java.sql.Timestamp) x)); + return; + } + + if (clazz == java.sql.Time.class) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.TIME, x)); + return; + } + + if (clazz == Boolean.class) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.BOOLEAN, x)); + return; + } + + if (clazz == byte[].class) { + setParameter(parameterIndex, new JdbcParameterImpl(JdbcParameter.TYPE.BYTES, x)); + return; + } + + if (x instanceof InputStream) { + setParameter(parameterIndex, new JdbcParameterImpl(JdbcParameter.TYPE.BinaryInputStream, x)); + return; + } + + if (x instanceof Reader) { + setParameter(parameterIndex, new JdbcParameterImpl(JdbcParameter.TYPE.CharacterInputStream, x)); + return; + } + + if (x instanceof Clob) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.CLOB, x)); + return; + } + + if (x instanceof NClob) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.NCLOB, x)); + return; + } + + if (x instanceof Blob) { + setParameter(parameterIndex, new JdbcParameterImpl(Types.BLOB, x)); + return; + } + + setParameter(parameterIndex, createParameter(Types.OTHER, null)); + } + + private JdbcParameter createParameter(int sqlType, Object value, Calendar calendar) { + if (value == null) { + return JdbcParameterNull.valueOf(sqlType); + } + + return new JdbcParameterImpl(sqlType, value, calendar); + } + + private JdbcParameter createParameter(Object x, int sqlType, int scaleOrLength) { + if (x == null) { + return JdbcParameterNull.valueOf(sqlType); + } + + return new JdbcParameterImpl(sqlType, x, -1, null, scaleOrLength); + } + + private void setParameter(int jdbcIndex, JdbcParameter parameter) { + int index = jdbcIndex - 1; + + if (jdbcIndex > parametersSize) { + parametersSize = jdbcIndex; + } + if (parametersSize >= parameters.length) { + int oldCapacity = parameters.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); + if (newCapacity <= 4) { + newCapacity = 4; + } + + parameters = Arrays.copyOf(parameters, newCapacity); + } + parameters[index] = parameter; + } } diff --git a/src/main/java/org/nlpcn/es4sql/query/ESActionFactory.java b/src/main/java/org/nlpcn/es4sql/query/ESActionFactory.java index 79d7be17..04a4c23e 100644 --- a/src/main/java/org/nlpcn/es4sql/query/ESActionFactory.java +++ b/src/main/java/org/nlpcn/es4sql/query/ESActionFactory.java @@ -127,7 +127,7 @@ private static QueryAction handleSelect(Client client, Select select) { } } - private static SQLStatementParser createSqlStatementParser(String sql) { + public static SQLStatementParser createSqlStatementParser(String sql) { ElasticLexer lexer = new ElasticLexer(sql); lexer.nextToken(); return new MySqlStatementParser(lexer); diff --git a/src/test/java/org/nlpcn/es4sql/JDBCTests.java b/src/test/java/org/nlpcn/es4sql/JDBCTests.java index 6b6032a4..2ab67c2e 100644 --- a/src/test/java/org/nlpcn/es4sql/JDBCTests.java +++ b/src/test/java/org/nlpcn/es4sql/JDBCTests.java @@ -49,11 +49,35 @@ public void testJDBC() throws Exception { connection.close(); dds.close(); - Assert.assertTrue(result.size()==1); - Assert.assertTrue(result.get(0).equals("Heath,39,F")); + Assert.assertEquals(1, result.size()); + Assert.assertEquals("Heath,39,F", result.get(0)); Assert.assertFalse(Matchers.isEmptyOrNullString().matches(scrollId)); } -} + @Test + public void testJDBCWithParameter() throws Exception { + Properties properties = new Properties(); + properties.put(PROP_URL, "jdbc:elasticsearch://127.0.0.1:9300/" + TestsConstants.TEST_INDEX_ACCOUNT); + properties.put(PROP_CONNECTIONPROPERTIES, "client.transport.ignore_cluster_name=true"); + try (DruidDataSource dds = (DruidDataSource) ElasticSearchDruidDataSourceFactory.createDataSource(properties); + Connection connection = dds.getConnection(); + PreparedStatement ps = connection.prepareStatement("SELECT gender,lastname,age from " + TestsConstants.TEST_INDEX_ACCOUNT + " where lastname=?")) { + // set parameter + ps.setString(1, "Heath"); + ResultSet resultSet = ps.executeQuery(); + ResultSetMetaData metaData = resultSet.getMetaData(); + assertThat(metaData.getColumnName(1), equalTo("gender")); + assertThat(metaData.getColumnName(2), equalTo("lastname")); + assertThat(metaData.getColumnName(3), equalTo("age")); + List result = new ArrayList<>(); + while (resultSet.next()) { + result.add(resultSet.getString("lastname") + "," + resultSet.getInt("age") + "," + resultSet.getString("gender")); + } + + Assert.assertEquals(1, result.size()); + Assert.assertEquals("Heath,39,F", result.get(0)); + } + } +}