Skip to content

Commit ced08fc

Browse files
committed
Assign numbers to parameters in Tokenizer
1 parent 07aabef commit ced08fc

File tree

7 files changed

+76
-54
lines changed

7 files changed

+76
-54
lines changed

h2/src/docsrc/html/changelog.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ <h1>Change Log</h1>
2121

2222
<h2>Next Version (unreleased)</h2>
2323
<ul>
24+
<li>Issue #3334: Regression with CREATE ALIAS - Parameter "#2" is not set
25+
</li>
2426
<li>Issue #3321: Insert Primary Key after import CSV Data does not work
2527
</li>
2628
<li>PR #3323: Tokenize SQL before parsing and preserve tokens for recompilation

h2/src/main/org/h2/command/Parser.java

Lines changed: 21 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,7 @@ public class Parser {
447447
private Select currentSelect;
448448
private List<TableView> cteCleanups;
449449
private ArrayList<Parameter> parameters;
450-
private ArrayList<Parameter> indexedParameterList;
451450
private ArrayList<Parameter> suppliedParameters;
452-
private ArrayList<Parameter> suppliedParameterList;
453451
private String schemaName;
454452
private ArrayList<String> expectedList;
455453
private boolean rightsChecked;
@@ -589,7 +587,6 @@ private CommandList prepareCommandList(CommandContainer command, Prepared p, Str
589587
return new CommandList(session, sql, command, list, parameters, remainingSql);
590588
}
591589
suppliedParameters = parameters;
592-
suppliedParameterList = indexedParameterList;
593590
try {
594591
p = parse(remainingSql, remainingTokens);
595592
} catch (DbException ex) {
@@ -666,7 +663,6 @@ private Prepared parse(String sql, boolean withExpectedList) {
666663
expectedList = null;
667664
}
668665
parameters = suppliedParameters != null ? suppliedParameters : Utils.newSmallArrayList();
669-
indexedParameterList = suppliedParameterList;
670666
currentSelect = null;
671667
currentPrepared = null;
672668
createView = null;
@@ -852,14 +848,12 @@ private Prepared parsePrepared() {
852848
if (c == null) {
853849
throw getSyntaxError();
854850
}
855-
if (indexedParameterList != null) {
856-
for (int i = 0, size = indexedParameterList.size();
857-
i < size; i++) {
858-
if (indexedParameterList.get(i) == null) {
859-
indexedParameterList.set(i, new Parameter(i));
851+
if (parameters != null) {
852+
for (int i = 0, size = parameters.size(); i < size; i++) {
853+
if (parameters.get(i) == null) {
854+
parameters.set(i, new Parameter(i));
860855
}
861856
}
862-
parameters = indexedParameterList;
863857
}
864858
boolean withParamValues = readIf(OPEN_BRACE);
865859
if (withParamValues) {
@@ -4917,46 +4911,26 @@ private void checkDatabaseName(String databaseName) {
49174911
}
49184912

49194913
private Parameter readParameter() {
4920-
// there must be no space between ? and the number
49214914
int index = ((Token.ParameterToken) token).index();
49224915
read();
49234916
Parameter p;
4924-
if (index > 0) {
4925-
if (indexedParameterList == null) {
4926-
if (parameters == null) {
4927-
// this can occur when parsing expressions only (for
4928-
// example check constraints)
4929-
throw getSyntaxError();
4930-
} else if (!parameters.isEmpty()) {
4931-
throw DbException
4932-
.get(ErrorCode.CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS);
4933-
}
4934-
indexedParameterList = Utils.newSmallArrayList();
4935-
}
4936-
if (index > Constants.MAX_PARAMETER_INDEX) {
4937-
throw DbException.getInvalidValueException(
4938-
"parameter index", index);
4939-
}
4940-
index--;
4941-
if (indexedParameterList.size() <= index) {
4942-
indexedParameterList.ensureCapacity(index + 1);
4943-
while (indexedParameterList.size() <= index) {
4944-
indexedParameterList.add(null);
4945-
}
4946-
}
4947-
p = indexedParameterList.get(index);
4948-
if (p == null) {
4949-
p = new Parameter(index);
4950-
indexedParameterList.set(index, p);
4951-
parameters.add(p);
4952-
}
4953-
} else {
4954-
if (indexedParameterList != null) {
4955-
throw DbException
4956-
.get(ErrorCode.CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS);
4917+
if (parameters == null) {
4918+
parameters = Utils.newSmallArrayList();
4919+
}
4920+
if (index > Constants.MAX_PARAMETER_INDEX) {
4921+
throw DbException.getInvalidValueException("parameter index", index);
4922+
}
4923+
index--;
4924+
if (parameters.size() <= index) {
4925+
parameters.ensureCapacity(index + 1);
4926+
while (parameters.size() < index) {
4927+
parameters.add(null);
49574928
}
4958-
p = new Parameter(parameters.size());
4929+
p = new Parameter(index);
49594930
parameters.add(p);
4931+
} else if ((p = parameters.get(index)) == null) {
4932+
p = new Parameter(index);
4933+
parameters.set(index, p);
49604934
}
49614935
return p;
49624936
}
@@ -9660,8 +9634,8 @@ public void setRightsChecked(boolean rightsChecked) {
96609634
this.rightsChecked = rightsChecked;
96619635
}
96629636

9663-
public void setSuppliedParameterList(ArrayList<Parameter> suppliedParameterList) {
9664-
this.suppliedParameterList = suppliedParameterList;
9637+
public void setSuppliedParameters(ArrayList<Parameter> suppliedParameters) {
9638+
this.suppliedParameters = suppliedParameters;
96659639
}
96669640

96679641
/**

h2/src/main/org/h2/command/Token.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ Value value(CastDataProvider provider) {
664664

665665
static final class ParameterToken extends Token {
666666

667-
private final int index;
667+
int index;
668668

669669
ParameterToken(int start, int index) {
670670
super(start);

h2/src/main/org/h2/command/Tokenizer.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ ArrayList<Token> tokenize(String sql, boolean stopOnCloseParen) {
163163
ArrayList<Token> tokens = new ArrayList<>();
164164
int end = sql.length() - 1;
165165
boolean foundUnicode = false;
166+
int lastParameter = 0;
166167
loop: for (int i = 0; i <= end;) {
167168
int tokenStart = i;
168169
char c = sql.charAt(i);
@@ -204,6 +205,7 @@ ArrayList<Token> tokenize(String sql, boolean stopOnCloseParen) {
204205
i = stringEnd + 1;
205206
} else {
206207
i = parseParameterIndex(sql, end, i, tokens);
208+
lastParameter = assignParameterIndex(tokens, lastParameter);
207209
continue loop;
208210
}
209211
} else {
@@ -339,7 +341,7 @@ ArrayList<Token> tokenize(String sql, boolean stopOnCloseParen) {
339341
}
340342
token = new Token.KeywordToken(tokenStart, BIGGER);
341343
break;
342-
case '?':
344+
case '?': {
343345
if (i + 1 < end && sql.charAt(i + 1) == '?') {
344346
char c3 = sql.charAt(i + 2);
345347
if (c3 == '(') {
@@ -354,7 +356,9 @@ ArrayList<Token> tokenize(String sql, boolean stopOnCloseParen) {
354356
}
355357
}
356358
i = parseParameterIndex(sql, end, i, tokens);
359+
lastParameter = assignParameterIndex(tokens, lastParameter);
357360
continue loop;
361+
}
358362
case '@':
359363
token = new Token.KeywordToken(tokenStart, AT);
360364
break;
@@ -1339,6 +1343,21 @@ private static int parseParameterIndex(String sql, int end, int i, ArrayList<Tok
13391343
return i;
13401344
}
13411345

1346+
private static int assignParameterIndex(ArrayList<Token> tokens, int lastParameter) {
1347+
Token.ParameterToken parameter = (Token.ParameterToken) tokens.get(tokens.size() - 1);
1348+
if (parameter.index == 0) {
1349+
if (lastParameter < 0) {
1350+
throw DbException.get(ErrorCode.CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS);
1351+
}
1352+
parameter.index = ++lastParameter;
1353+
} else if (lastParameter > 0) {
1354+
throw DbException.get(ErrorCode.CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS);
1355+
} else {
1356+
lastParameter = -1;
1357+
}
1358+
return lastParameter;
1359+
}
1360+
13421361
private static void processUescape(String sql, ArrayList<Token> tokens) {
13431362
ListIterator<Token> i = tokens.listIterator();
13441363
while (i.hasNext()) {

h2/src/main/org/h2/index/ViewIndex.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ private Cursor findRecursive(SearchRow first, SearchRow last) {
168168
if (query == null) {
169169
Parser parser = new Parser(createSession);
170170
parser.setRightsChecked(true);
171-
parser.setSuppliedParameterList(originalParameters);
171+
parser.setSuppliedParameters(originalParameters);
172172
query = (Query) parser.prepare(querySQL);
173173
query.setNeverLazy(true);
174174
}
@@ -226,9 +226,11 @@ public void setupQueryParameters(SessionLocal session, SearchRow first, SearchRo
226226
ArrayList<Parameter> paramList = query.getParameters();
227227
if (originalParameters != null) {
228228
for (Parameter orig : originalParameters) {
229-
int idx = orig.getIndex();
230-
Value value = orig.getValue(session);
231-
setParameter(paramList, idx, value);
229+
if (orig != null) {
230+
int idx = orig.getIndex();
231+
Value value = orig.getValue(session);
232+
setParameter(paramList, idx, value);
233+
}
232234
}
233235
}
234236
int len;

h2/src/main/org/h2/table/TableView.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,9 @@ public int getParameterOffset(ArrayList<Parameter> additionalParameters) {
541541
private static int getMaxParameterIndex(ArrayList<Parameter> parameters) {
542542
int result = -1;
543543
for (Parameter p : parameters) {
544-
result = Math.max(result, p.getIndex());
544+
if (p != null) {
545+
result = Math.max(result, p.getIndex());
546+
}
545547
}
546548
return result;
547549
}

h2/src/test/org/h2/test/db/TestFunctions.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,16 @@ private void testFunctionTable() throws SQLException {
155155
Statement stat = conn.createStatement();
156156
stat.execute("create alias simple_function_table for '" +
157157
TestFunctions.class.getName() + ".simpleFunctionTable'");
158+
stat.execute("create alias function_table_with_parameter for '" +
159+
TestFunctions.class.getName() + ".functionTableWithParameter'");
158160
stat.execute("select * from simple_function_table() " +
159161
"where a>0 and b in ('x', 'y')");
162+
PreparedStatement prep = conn.prepareStatement("call function_table_with_parameter(?)");
163+
prep.setInt(1, 10);
164+
ResultSet rs = prep.executeQuery();
165+
assertTrue(rs.next());
166+
assertEquals(10, rs.getInt(1));
167+
assertEquals("X", rs.getString(2));
160168
conn.close();
161169
}
162170

@@ -188,6 +196,21 @@ public static ResultSet simpleFunctionTable(@SuppressWarnings("unused") Connecti
188196
return result;
189197
}
190198

199+
/**
200+
* This method is called via reflection from the database.
201+
*
202+
* @param conn the connection
203+
* @param p the parameter
204+
* @return a result set
205+
*/
206+
public static ResultSet functionTableWithParameter(@SuppressWarnings("unused") Connection conn, int p) {
207+
SimpleResultSet result = new SimpleResultSet();
208+
result.addColumn("A", Types.INTEGER, 0, 0);
209+
result.addColumn("B", Types.CHAR, 0, 0);
210+
result.addRow(p, 'X');
211+
return result;
212+
}
213+
191214
/**
192215
* This method is called via reflection from the database.
193216
*

0 commit comments

Comments
 (0)