Skip to content

Commit

Permalink
fix: improve insert values(...) batch rewrite
Browse files Browse the repository at this point in the history
Now it supports VALUES (?,1), and splits very long batch into series of smaller ones
to keep overall number of bind variables <32768 (that is PG's limit in v3 protocol)

Trigger property: reWriteBatchedInserts=true. Default value is still "false".

closes #580
closes #584
  • Loading branch information
Chrriis authored and vlsi committed Jun 22, 2016
1 parent 1eb4085 commit 510e6e0
Show file tree
Hide file tree
Showing 27 changed files with 1,458 additions and 1,384 deletions.
33 changes: 23 additions & 10 deletions pgjdbc/src/main/java/org/postgresql/core/DMLCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,21 @@
* Data Modification Language inspection support.
*
* @author Jeremy Whiting jwhiting@redhat.com
* @author Christopher Deckers (chrriis@gmail.com)
*
*/
public class DMLCommand {

public boolean isBatchedReWriteCompatible() {
return batchedReWriteCompatible;
return valuesBraceOpenPosition >= 0;
}

public int getBatchRewriteValuesBraceOpenPosition() {
return valuesBraceOpenPosition;
}

public int getBatchRewriteValuesBraceClosePosition() {
return valuesBraceClosePosition;
}

public DMLCommandType getType() {
Expand All @@ -32,33 +41,37 @@ public boolean isReturningKeywordPresent() {

public static DMLCommand createStatementTypeInfo(DMLCommandType type,
boolean isBatchedReWritePropertyConfigured,
boolean isBatchedReWriteCompatible, boolean isRETURNINGkeywordPresent,
boolean autocommit, int priorQueryCount) {
int valuesBraceOpenPosition, int valuesBraceClosePosition, boolean isRETURNINGkeywordPresent,
int priorQueryCount) {
return new DMLCommand(type, isBatchedReWritePropertyConfigured,
isBatchedReWriteCompatible, isRETURNINGkeywordPresent, autocommit,
valuesBraceOpenPosition, valuesBraceClosePosition, isRETURNINGkeywordPresent,
priorQueryCount);
}

public static DMLCommand createStatementTypeInfo(DMLCommandType type) {
return new DMLCommand(type, false, false, false, false,0);
return new DMLCommand(type, false, -1, -1, false, 0);
}

public static DMLCommand createStatementTypeInfo(DMLCommandType type,
boolean isRETURNINGkeywordPresent) {
return new DMLCommand(type, false, false, isRETURNINGkeywordPresent, false,0);
return new DMLCommand(type, false, -1, -1, isRETURNINGkeywordPresent, 0);
}

private DMLCommand(DMLCommandType type, boolean isBatchedReWriteConfigured,
boolean isCompatible, boolean isPresent, boolean isautocommitConfigured,
int valuesBraceOpenPosition, int valuesBraceClosePosition, boolean isPresent,
int priorQueryCount) {
commandType = type;
parsedSQLhasRETURNINGKeyword = isPresent;
batchedReWriteCompatible = (type == INSERT) && isBatchedReWriteConfigured
&& isCompatible && !isautocommitConfigured
boolean batchedReWriteCompatible = (type == INSERT) && isBatchedReWriteConfigured
&& valuesBraceOpenPosition >= 0 && valuesBraceClosePosition > valuesBraceOpenPosition
&& !isPresent && priorQueryCount == 0;
this.valuesBraceOpenPosition = batchedReWriteCompatible ? valuesBraceOpenPosition : -1;
this.valuesBraceClosePosition = batchedReWriteCompatible ? valuesBraceClosePosition : -1;
}

private final DMLCommandType commandType;
private final boolean parsedSQLhasRETURNINGKeyword;
private final boolean batchedReWriteCompatible;
private final int valuesBraceOpenPosition;
private final int valuesBraceClosePosition;

}
34 changes: 31 additions & 3 deletions pgjdbc/src/main/java/org/postgresql/core/NativeQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* replaced with $1, $2, etc.
*/
public class NativeQuery {
private final static String[] BIND_NAMES = new String[128];
private final static String[] BIND_NAMES = new String[128 * 10];
private final static int[] NO_BINDS = new int[0];

public final String nativeSql;
Expand Down Expand Up @@ -79,8 +79,36 @@ public static String bindName(int index) {
return index < BIND_NAMES.length ? BIND_NAMES[index] : "$" + index;
}

public static int bindCount() {
return BIND_NAMES.length;
public static StringBuilder appendBindName(StringBuilder sb, int index) {
if (index < BIND_NAMES.length) {
return sb.append(bindName(index));
}
sb.append('$');
sb.append(index);
return sb;
}

/**
* Calculate the text length required for the given number of bind variables
* including dollars.
* Do this to avoid repeated calls to
* AbstractStringBuilder.expandCapacity(...) and Arrays.copyOf
*
* @param bindCount total number of parameters in a query
* @return int total character length for $xyz kind of binds
*/
public static int calculateBindLength(int bindCount) {
int res = 0;
int bindLen = 2; // $1
int maxBindsOfLen = 9; // $0 .. $9
while (bindCount > 0) {
int numBinds = Math.min(maxBindsOfLen, bindCount);
bindCount -= numBinds;
res += bindLen * numBinds;
bindLen++;
maxBindsOfLen *= 10; // $0..$9 (9 items) -> $10..$99 (90 items)
}
return res;
}

public DMLCommand getCommand() {
Expand Down
Loading

0 comments on commit 510e6e0

Please sign in to comment.