Merge pull request #641 from xieyinglin/master
add support preparedstatement execute batch
This commit is contained in:
commit
4900dcdc4e
|
@ -23,3 +23,5 @@ tests/script/
|
||||||
tests/pytest/
|
tests/pytest/
|
||||||
tests/jenkins/
|
tests/jenkins/
|
||||||
tests/hdfs/
|
tests/hdfs/
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
|
|
@ -1,15 +1,77 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>com.taosdata.jdbc</groupId>
|
<groupId>com.taosdata.jdbc</groupId>
|
||||||
<artifactId>taos-jdbcdriver</artifactId>
|
<artifactId>taos-jdbcdriver</artifactId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>JDBCDriver</name>
|
<name>JDBCDriver</name>
|
||||||
|
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||||
<description>TDengine JDBC Driver</description>
|
<description>TDengine JDBC Driver</description>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>GNU AFFERO GENERAL PUBLIC LICENSE Version 3</name>
|
||||||
|
<url>https://github.com/taosdata/TDengine/blob/master/LICENSE</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:git://github.com/taosdata/TDengine.git</connection>
|
||||||
|
<developerConnection>scm:git:git@github.com:taosdata/TDengine.git</developerConnection>
|
||||||
|
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||||
|
<tag>HEAD</tag>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>taosdata</name>
|
||||||
|
<email>support@taosdata.com</email>
|
||||||
|
<organization>https://www.taosdata.com/</organization>
|
||||||
|
<organizationUrl>https://www.taosdata.com/</organizationUrl>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
|
||||||
|
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
|
||||||
|
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
|
||||||
|
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
|
||||||
|
<maven-javadoc-plugin.version>3.1.0</maven-javadoc-plugin.version>
|
||||||
|
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||||
|
<maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
|
||||||
|
<nexus-staging-maven-plugin.version>1.6.7</nexus-staging-maven-plugin.version>
|
||||||
|
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
|
||||||
|
<maven-scm-provider-gitexe.version>1.9.5</maven-scm-provider-gitexe.version>
|
||||||
|
|
||||||
|
<commons-logging.version>1.1.2</commons-logging.version>
|
||||||
|
<commons-lang3.version>3.5</commons-lang3.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<version>${commons-logging.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>*</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>${commons-lang3.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -35,18 +97,19 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>2.3.2</version>
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
<source>1.8</source>
|
<source>${java.version}</source>
|
||||||
<target>1.8</target>
|
<target>${java.version}</target>
|
||||||
<debug>true</debug>
|
<debug>true</debug>
|
||||||
|
<showDeprecation>true</showDeprecation>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
<version>2.1.2</version>
|
<version>${maven-source-plugin.version}</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>attach-sources</id>
|
<id>attach-sources</id>
|
||||||
|
@ -56,24 +119,101 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
<plugin>
|
||||||
</build>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>${maven-javadoc-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
<docencoding>UTF-8</docencoding>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<version>${maven-gpg-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>sign-artifacts</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>${maven-deploy-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-deploy</id>
|
||||||
|
<phase>deploy</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>deploy</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
|
<version>${nexus-staging-maven-plugin.version}</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<serverId>ossrh-td</serverId>
|
||||||
|
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||||
|
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<version>${maven-release-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<localCheckout>true</localCheckout>
|
||||||
|
<pushChanges>false</pushChanges>
|
||||||
|
<mavenExecutorId>forked-path</mavenExecutorId>
|
||||||
|
<arguments>-Dgpg.passphrase=${gpg.passphrase}</arguments>
|
||||||
|
</configuration>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-logging</groupId>
|
<groupId>org.apache.maven.scm</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>maven-scm-provider-gitexe</artifactId>
|
||||||
<version>1.1.2</version>
|
<version>${maven-scm-provider-gitexe.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
<version>3.5</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>ossrh-td</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
<repository>
|
||||||
|
<id>ossrh-td</id>
|
||||||
|
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,433 @@
|
||||||
|
package com.taosdata.jdbc;
|
||||||
|
|
||||||
|
import com.taosdata.jdbc.bean.TSDBPreparedParam;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this class is used to precompile the sql of tdengine insert or import ops
|
||||||
|
*/
|
||||||
|
public class SavedPreparedStatement {
|
||||||
|
|
||||||
|
private TSDBPreparedStatement tsdbPreparedStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql param List
|
||||||
|
*/
|
||||||
|
private List<TSDBPreparedParam> sqlParamList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init param according the sql
|
||||||
|
*/
|
||||||
|
private TSDBPreparedParam initPreparedParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is table name dynamic in the prepared sql
|
||||||
|
*/
|
||||||
|
private boolean isTableNameDynamic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert or import sql template pattern, the template are the following:
|
||||||
|
* <p>
|
||||||
|
* insert/import into tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ] values(?, ?, ...) (?, ?, ...)
|
||||||
|
* <p>
|
||||||
|
* we split it to three part:
|
||||||
|
* 1. prefix, insert/import
|
||||||
|
* 2. middle, tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ]
|
||||||
|
* 3. valueList, the content after values, for example (?, ?, ...) (?, ?, ...)
|
||||||
|
*/
|
||||||
|
private Pattern sqlPattern = Pattern.compile("(?s)(?i)^\\s*(INSERT|IMPORT)\\s+INTO\\s+((?<tablename>\\S+)\\s*(\\(.*\\))?\\s+(USING\\s+(?<stableName>\\S+)\\s+TAGS\\s*\\((?<tagValue>.+)\\))?)\\s*VALUES\\s*(?<valueList>\\(.*\\)).*");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the raw sql template
|
||||||
|
*/
|
||||||
|
private String sql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the prefix part of sql
|
||||||
|
*/
|
||||||
|
private String prefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the middle part of sql
|
||||||
|
*/
|
||||||
|
private String middle;
|
||||||
|
|
||||||
|
private int middleParamSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the valueList part of sql
|
||||||
|
*/
|
||||||
|
private String valueList;
|
||||||
|
|
||||||
|
private int valueListSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default param value
|
||||||
|
*/
|
||||||
|
private static final String DEFAULT_VALUE = "NULL";
|
||||||
|
|
||||||
|
private static final String PLACEHOLDER = "?";
|
||||||
|
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is the parameter add to batch list
|
||||||
|
*/
|
||||||
|
private boolean isAddBatch;
|
||||||
|
|
||||||
|
public SavedPreparedStatement(String sql, TSDBPreparedStatement tsdbPreparedStatement) throws SQLException {
|
||||||
|
this.sql = sql;
|
||||||
|
this.tsdbPreparedStatement = tsdbPreparedStatement;
|
||||||
|
this.sqlParamList = new ArrayList<>();
|
||||||
|
|
||||||
|
parsePreparedParam(this.sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse the init param according the sql param
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
*/
|
||||||
|
private void parsePreparedParam(String sql) throws SQLException {
|
||||||
|
|
||||||
|
Matcher matcher = sqlPattern.matcher(sql);
|
||||||
|
|
||||||
|
if (matcher.find()) {
|
||||||
|
|
||||||
|
tableName = matcher.group("tablename");
|
||||||
|
|
||||||
|
if (tableName != null && PLACEHOLDER.equals(tableName)) {
|
||||||
|
// the table name is dynamic
|
||||||
|
this.isTableNameDynamic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = matcher.group(1);
|
||||||
|
middle = matcher.group(2);
|
||||||
|
valueList = matcher.group("valueList");
|
||||||
|
|
||||||
|
if (middle != null && !"".equals(middle)) {
|
||||||
|
middleParamSize = parsePlaceholder(middle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueList != null && !"".equals(valueList)) {
|
||||||
|
valueListSize = parsePlaceholder(valueList);
|
||||||
|
}
|
||||||
|
|
||||||
|
initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// not match
|
||||||
|
throw new SQLException(TSDBConstants.WrapErrMsg("the sql is not complete!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TSDBPreparedParam initDefaultParam(String tableName, int middleParamSize, int valueListSize) {
|
||||||
|
|
||||||
|
TSDBPreparedParam tsdbPreparedParam = new TSDBPreparedParam(tableName);
|
||||||
|
|
||||||
|
tsdbPreparedParam.setMiddleParamList(getDefaultParamList(middleParamSize));
|
||||||
|
|
||||||
|
tsdbPreparedParam.setValueList(getDefaultParamList(valueListSize));
|
||||||
|
|
||||||
|
return tsdbPreparedParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate the default param value list
|
||||||
|
*
|
||||||
|
* @param paramSize
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<Object> getDefaultParamList(int paramSize) {
|
||||||
|
|
||||||
|
List<Object> paramList = new ArrayList<>(paramSize);
|
||||||
|
if (paramSize > 0) {
|
||||||
|
for (int i = 0; i < paramSize; i++) {
|
||||||
|
paramList.add(i, DEFAULT_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paramList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculate the placeholder num
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int parsePlaceholder(String value) {
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("[?]");
|
||||||
|
|
||||||
|
Matcher matcher = pattern.matcher(value);
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
while (matcher.find()) {
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set current row params
|
||||||
|
*
|
||||||
|
* @param parameterIndex the first parameter is 1, the second is 2, ...
|
||||||
|
* @param x the parameter value
|
||||||
|
*/
|
||||||
|
public void setParam(int parameterIndex, Object x) throws SQLException {
|
||||||
|
|
||||||
|
int paramSize = this.middleParamSize + this.valueListSize;
|
||||||
|
|
||||||
|
String errorMsg = String.format("the parameterIndex %s out of the range [1, %s]", parameterIndex, this.middleParamSize + this.valueListSize);
|
||||||
|
|
||||||
|
if (parameterIndex < 1 || parameterIndex > paramSize) {
|
||||||
|
throw new SQLException(TSDBConstants.WrapErrMsg(errorMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isAddBatch = false; //set isAddBatch to false
|
||||||
|
|
||||||
|
if (x == null) {
|
||||||
|
x = DEFAULT_VALUE; // set default null string
|
||||||
|
}
|
||||||
|
|
||||||
|
parameterIndex = parameterIndex - 1; // start from 0 in param list
|
||||||
|
|
||||||
|
if (this.middleParamSize != 0 && parameterIndex >= 0 && parameterIndex < this.middleParamSize) {
|
||||||
|
|
||||||
|
this.initPreparedParam.setMiddleParam(parameterIndex, x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.valueListSize != 0 && parameterIndex >= this.middleParamSize && parameterIndex < paramSize) {
|
||||||
|
|
||||||
|
this.initPreparedParam.setValueParam(parameterIndex - this.middleParamSize, x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new SQLException(TSDBConstants.WrapErrMsg(errorMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBatch() {
|
||||||
|
|
||||||
|
addCurrentRowParamToList();
|
||||||
|
this.initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add current param to batch list
|
||||||
|
*/
|
||||||
|
private void addCurrentRowParamToList() {
|
||||||
|
|
||||||
|
if (initPreparedParam != null && (this.middleParamSize > 0 || this.valueListSize > 0)) {
|
||||||
|
this.sqlParamList.add(initPreparedParam); // add current param to batch list
|
||||||
|
}
|
||||||
|
this.isAddBatch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute the sql with batch sql
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public int[] executeBatch() throws SQLException {
|
||||||
|
|
||||||
|
int result = executeBatchInternal();
|
||||||
|
|
||||||
|
return new int[]{result};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int executeBatchInternal() throws SQLException {
|
||||||
|
|
||||||
|
if (!isAddBatch) {
|
||||||
|
addCurrentRowParamToList(); // add current param to batch list
|
||||||
|
}
|
||||||
|
|
||||||
|
//1. generate batch sql
|
||||||
|
String sql = generateExecuteSql();
|
||||||
|
|
||||||
|
//2. execute batch sql
|
||||||
|
int result = executeSql(sql);
|
||||||
|
|
||||||
|
//3. clear batch param list
|
||||||
|
this.sqlParamList.clear();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate the batch sql
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String generateExecuteSql() {
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
stringBuilder.append(prefix);
|
||||||
|
stringBuilder.append(" into ");
|
||||||
|
|
||||||
|
if (!isTableNameDynamic) {
|
||||||
|
// tablename will not need to be replaced
|
||||||
|
stringBuilder.append(middle);
|
||||||
|
stringBuilder.append(" values");
|
||||||
|
|
||||||
|
stringBuilder.append(replaceValueListParam(valueList, sqlParamList));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// need to replace tablename
|
||||||
|
|
||||||
|
if (sqlParamList.size() > 0) {
|
||||||
|
|
||||||
|
TSDBPreparedParam firstPreparedParam = sqlParamList.get(0);
|
||||||
|
|
||||||
|
//replace middle part and value part of first row
|
||||||
|
String firstRow = replaceMiddleAndValuePart(firstPreparedParam);
|
||||||
|
stringBuilder.append(firstRow);
|
||||||
|
|
||||||
|
//the first param in the middleParamList is the tableName
|
||||||
|
String lastTableName = firstPreparedParam.getMiddleParamList().get(0).toString();
|
||||||
|
|
||||||
|
if (sqlParamList.size() > 1) {
|
||||||
|
|
||||||
|
for (int i = 1; i < sqlParamList.size(); i++) {
|
||||||
|
TSDBPreparedParam currentParam = sqlParamList.get(i);
|
||||||
|
String currentTableName = currentParam.getMiddleParamList().get(0).toString();
|
||||||
|
if (lastTableName.equalsIgnoreCase(currentTableName)) {
|
||||||
|
// tablename is same with the last row ,so only need to append the part of value
|
||||||
|
|
||||||
|
String values = replaceTemplateParam(valueList, currentParam.getValueList());
|
||||||
|
stringBuilder.append(values);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// tablename difference with the last row
|
||||||
|
//need to replace middle part and value part
|
||||||
|
String row = replaceMiddleAndValuePart(currentParam);
|
||||||
|
stringBuilder.append(row);
|
||||||
|
lastTableName = currentTableName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
stringBuilder.append(middle);
|
||||||
|
stringBuilder.append(" values");
|
||||||
|
stringBuilder.append(valueList);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace the middle and value part
|
||||||
|
*
|
||||||
|
* @param tsdbPreparedParam
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String replaceMiddleAndValuePart(TSDBPreparedParam tsdbPreparedParam) {
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(" ");
|
||||||
|
|
||||||
|
String middlePart = replaceTemplateParam(middle, tsdbPreparedParam.getMiddleParamList());
|
||||||
|
|
||||||
|
stringBuilder.append(middlePart);
|
||||||
|
stringBuilder.append(" values ");
|
||||||
|
|
||||||
|
String valuePart = replaceTemplateParam(valueList, tsdbPreparedParam.getValueList());
|
||||||
|
stringBuilder.append(valuePart);
|
||||||
|
stringBuilder.append(" ");
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace the placeholder of the template with TSDBPreparedParam list
|
||||||
|
*
|
||||||
|
* @param template
|
||||||
|
* @param sqlParamList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String replaceValueListParam(String template, List<TSDBPreparedParam> sqlParamList) {
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
if (sqlParamList.size() > 0) {
|
||||||
|
|
||||||
|
for (TSDBPreparedParam tsdbPreparedParam : sqlParamList) {
|
||||||
|
|
||||||
|
String tmp = replaceTemplateParam(template, tsdbPreparedParam.getValueList());
|
||||||
|
|
||||||
|
stringBuilder.append(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
stringBuilder.append(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace the placeholder of the template with paramList
|
||||||
|
*
|
||||||
|
* @param template
|
||||||
|
* @param paramList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String replaceTemplateParam(String template, List<Object> paramList) {
|
||||||
|
|
||||||
|
if (paramList.size() > 0) {
|
||||||
|
|
||||||
|
String tmp = template;
|
||||||
|
|
||||||
|
for (int i = 0; i < paramList.size(); ++i) {
|
||||||
|
|
||||||
|
String paraStr = getParamString(paramList.get(i));
|
||||||
|
|
||||||
|
tmp = tmp.replaceFirst("[" + PLACEHOLDER + "]", paraStr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the string of param object
|
||||||
|
*
|
||||||
|
* @param paramObj
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getParamString(Object paramObj) {
|
||||||
|
|
||||||
|
String paraStr = paramObj.toString();
|
||||||
|
if (paramObj instanceof Timestamp || (paramObj instanceof String && !DEFAULT_VALUE.equalsIgnoreCase(paraStr))) {
|
||||||
|
paraStr = "'" + paraStr + "'";
|
||||||
|
}
|
||||||
|
return paraStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int executeSql(String sql) throws SQLException {
|
||||||
|
|
||||||
|
return tsdbPreparedStatement.executeUpdate(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,10 +34,52 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
||||||
protected String sql;
|
protected String sql;
|
||||||
protected ArrayList<Object> parameters = new ArrayList<Object>();
|
protected ArrayList<Object> parameters = new ArrayList<Object>();
|
||||||
|
|
||||||
|
//start with insert or import and is case-insensitive
|
||||||
|
private static Pattern savePattern = Pattern.compile("(?i)^\\s*(insert|import)");
|
||||||
|
|
||||||
|
// is insert or import
|
||||||
|
private boolean isSaved;
|
||||||
|
|
||||||
|
private SavedPreparedStatement savedPreparedStatement;
|
||||||
|
|
||||||
TSDBPreparedStatement(TSDBJNIConnector connecter, String sql) {
|
TSDBPreparedStatement(TSDBJNIConnector connecter, String sql) {
|
||||||
super(connecter);
|
super(connecter);
|
||||||
|
init(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(String sql) {
|
||||||
this.rawSql = sql;
|
this.rawSql = sql;
|
||||||
preprocessSql();
|
preprocessSql();
|
||||||
|
|
||||||
|
this.isSaved = isSavedSql(this.rawSql);
|
||||||
|
if (this.isSaved) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.savedPreparedStatement = new SavedPreparedStatement(this.rawSql, this);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if the precompiled sql is insert or import
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isSavedSql(String sql) {
|
||||||
|
Matcher matcher = savePattern.matcher(sql);
|
||||||
|
return matcher.find();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] executeBatch() throws SQLException {
|
||||||
|
if (isSaved) {
|
||||||
|
return this.savedPreparedStatement.executeBatch();
|
||||||
|
} else {
|
||||||
|
return super.executeBatch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Object> getParameters() {
|
public ArrayList<Object> getParameters() {
|
||||||
|
@ -112,6 +154,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate parameters into prepared sql statements
|
* Populate parameters into prepared sql statements
|
||||||
|
*
|
||||||
* @return a string of the native sql statement for TSDB
|
* @return a string of the native sql statement for TSDB
|
||||||
*/
|
*/
|
||||||
private String getNativeSql() {
|
private String getNativeSql() {
|
||||||
|
@ -134,13 +177,22 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet executeQuery() throws SQLException {
|
public ResultSet executeQuery() throws SQLException {
|
||||||
|
if (isSaved) {
|
||||||
|
this.savedPreparedStatement.executeBatchInternal();
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
return super.executeQuery(getNativeSql());
|
return super.executeQuery(getNativeSql());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int executeUpdate() throws SQLException {
|
public int executeUpdate() throws SQLException {
|
||||||
|
if (isSaved) {
|
||||||
|
return this.savedPreparedStatement.executeBatchInternal();
|
||||||
|
} else {
|
||||||
return super.executeUpdate(getNativeSql());
|
return super.executeUpdate(getNativeSql());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNull(int parameterIndex, int sqlType) throws SQLException {
|
public void setNull(int parameterIndex, int sqlType) throws SQLException {
|
||||||
|
@ -239,21 +291,35 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setObject(int parameterIndex, Object x) throws SQLException {
|
public void setObject(int parameterIndex, Object x) throws SQLException {
|
||||||
|
if (isSaved) {
|
||||||
|
this.savedPreparedStatement.setParam(parameterIndex, x);
|
||||||
|
} else {
|
||||||
parameters.add(x);
|
parameters.add(x);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute() throws SQLException {
|
public boolean execute() throws SQLException {
|
||||||
|
if (isSaved) {
|
||||||
|
int result = this.savedPreparedStatement.executeBatchInternal();
|
||||||
|
return result > 0;
|
||||||
|
} else {
|
||||||
return super.execute(getNativeSql());
|
return super.execute(getNativeSql());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addBatch() throws SQLException {
|
public void addBatch() throws SQLException {
|
||||||
|
if (isSaved) {
|
||||||
|
this.savedPreparedStatement.addBatch();
|
||||||
|
} else {
|
||||||
|
|
||||||
if (this.batchedArgs == null) {
|
if (this.batchedArgs == null) {
|
||||||
batchedArgs = new ArrayList<String>();
|
batchedArgs = new ArrayList<String>();
|
||||||
}
|
}
|
||||||
super.addBatch(getNativeSql());
|
super.addBatch(getNativeSql());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
|
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.taosdata.jdbc.bean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tdengine batch insert or import param object
|
||||||
|
*/
|
||||||
|
public class TSDBPreparedParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tableName, if sTable Name is not null, and this is sub table name.
|
||||||
|
*/
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sub middle param list
|
||||||
|
*/
|
||||||
|
private List<Object> middleParamList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value list
|
||||||
|
*/
|
||||||
|
private List<Object> valueList;
|
||||||
|
|
||||||
|
public TSDBPreparedParam(String tableName) {
|
||||||
|
this.tableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTableName() {
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTableName(String tableName) {
|
||||||
|
this.tableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Object> getMiddleParamList() {
|
||||||
|
return middleParamList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMiddleParamList(List<Object> middleParamList) {
|
||||||
|
this.middleParamList = middleParamList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMiddleParam(int parameterIndex, Object x) {
|
||||||
|
this.middleParamList.set(parameterIndex, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Object> getValueList() {
|
||||||
|
return valueList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueList(List<Object> valueList) {
|
||||||
|
this.valueList = valueList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setValueParam(int parameterIndex, Object x) {
|
||||||
|
this.valueList.set(parameterIndex, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue