-
Notifications
You must be signed in to change notification settings - Fork 132
chore: add namespace for client side statements in PostgreSQL dialect #1737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0b6a66f
9652a25
f3ad43e
5d4668e
1362734
592c125
acef711
7e15741
3d25121
04127e2
7dbdf1c
ce0dda2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright 2022 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.google.cloud.spanner.connection; | ||
|
||
import com.google.cloud.spanner.ErrorCode; | ||
import com.google.cloud.spanner.SpannerExceptionFactory; | ||
import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException; | ||
import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.PgTransactionModeConverter; | ||
import java.lang.reflect.Method; | ||
import java.util.regex.Matcher; | ||
|
||
/** Specific executor for the BEGIN statement for PostgreSQL. */ | ||
class ClientSideStatementPgBeginExecutor implements ClientSideStatementExecutor { | ||
private final ClientSideStatementImpl statement; | ||
private final Method method; | ||
private final PgTransactionModeConverter converter; | ||
|
||
ClientSideStatementPgBeginExecutor(ClientSideStatementImpl statement) throws CompileException { | ||
try { | ||
this.statement = statement; | ||
this.converter = new PgTransactionModeConverter(); | ||
this.method = | ||
ConnectionStatementExecutor.class.getDeclaredMethod( | ||
statement.getMethodName(), converter.getParameterClass()); | ||
} catch (Exception e) { | ||
throw new CompileException(e, statement); | ||
} | ||
} | ||
|
||
@Override | ||
public StatementResult execute(ConnectionStatementExecutor connection, String sql) | ||
throws Exception { | ||
return (StatementResult) method.invoke(connection, getParameterValue(sql)); | ||
} | ||
|
||
PgTransactionMode getParameterValue(String sql) { | ||
Matcher matcher = statement.getPattern().matcher(sql); | ||
if (matcher.find() && matcher.groupCount() >= 1) { | ||
String value = matcher.group(1); | ||
if (value != null) { | ||
PgTransactionMode res = converter.convert(value.trim()); | ||
if (res != null) { | ||
return res; | ||
} | ||
throw SpannerExceptionFactory.newSpannerException( | ||
ErrorCode.INVALID_ARGUMENT, String.format("Unknown transaction mode: %s", value)); | ||
} | ||
} | ||
return null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,9 @@ | |
|
||
package com.google.cloud.spanner.connection; | ||
|
||
import com.google.cloud.spanner.Dialect; | ||
import com.google.cloud.spanner.ErrorCode; | ||
import com.google.cloud.spanner.SpannerExceptionFactory; | ||
import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException; | ||
import com.google.gson.Gson; | ||
import java.io.InputStreamReader; | ||
|
@@ -24,7 +27,21 @@ | |
/** This class reads and parses the {@link ClientSideStatement}s from the json file. */ | ||
class ClientSideStatements { | ||
private static final String STATEMENTS_DEFINITION_FILE = "ClientSideStatements.json"; | ||
static final ClientSideStatements INSTANCE = importStatements(); | ||
private static final String PG_STATEMENTS_DEFINITION_FILE = "PG_ClientSideStatements.json"; | ||
private static final ClientSideStatements INSTANCE = importStatements(); | ||
private static final ClientSideStatements PG_INSTANCE = pgImportStatements(); | ||
|
||
static ClientSideStatements getInstance(Dialect dialect) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we call this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I don't feel that is right. |
||
switch (dialect) { | ||
case GOOGLE_STANDARD_SQL: | ||
return INSTANCE; | ||
case POSTGRESQL: | ||
return PG_INSTANCE; | ||
default: | ||
throw SpannerExceptionFactory.newSpannerException( | ||
ErrorCode.INVALID_ARGUMENT, "Unknown or unsupported dialect: " + dialect); | ||
} | ||
} | ||
|
||
/** | ||
* Reads statement definitions from ClientSideStatements.json and parses these as Java objects. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, but I would propose making it more natural for reading, so |
||
|
@@ -37,6 +54,18 @@ private static ClientSideStatements importStatements() { | |
ClientSideStatements.class); | ||
} | ||
|
||
/** | ||
* Reads statement definitions from PG_ClientSideStatements.json and parses these as Java objects. | ||
*/ | ||
private static ClientSideStatements pgImportStatements() { | ||
Gson gson = new Gson(); | ||
return gson.fromJson( | ||
new InputStreamReader( | ||
ClientSideStatements.class.getResourceAsStream(PG_STATEMENTS_DEFINITION_FILE)), | ||
ClientSideStatements.class); | ||
} | ||
|
||
// This field is set automatically by the importStatements / pgImportStatements methods. | ||
private Set<ClientSideStatementImpl> statements; | ||
|
||
private ClientSideStatements() {} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call these
GSQL_INSTANCE_STATEMENTS
andPG_INSTANCE_STATEMENTS
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think that is better to separate them, but I think we can drop the
INSTANCE
part. SoGSQL_STATEMENTS
andPG_STATEMENTS
.