-
Notifications
You must be signed in to change notification settings - Fork 199
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
Prepared query execution flow redesign #675
Comments
@aguibert @BillyYccc can you fill the corresponding sections in this document ? |
I would like to get a clear understanding of what is currently happening and what should ideally happen for all databases. We might have currently some bugs related to this. |
I also find having |
I think it is fine to allow control over |
@BillyYccc we need to determine how it works for one-shot queries when caching is disabled (other than the execution sequence) for MySQL does it mean that we should have the sequence
for un-cached one shot queries ? |
yes that's how it works |
can you update the doc with that ? |
which part of doc do you mean? |
for MySQL you wrote "There is no one-shot prepared-query protocol specific command in MySQL. so we can't change the command flow." We need to add the actual flow that I described I guess |
We need also consider if we need to autoimatically close the statement after executing one-shot prepared-queries. But for MySQL we have to send a close command otherwise the statements never get deallocated. Currently there's no such mechanism to clean the uncached one-shot statements so these are leaked, enabling the cache would let us send a close command when the statement gets evicted from the cache. |
@BillyYccc yes which is why I am asking for a flow definition of what happens for one-shot statement so we can implement it cleanly without leaking :-) |
I will likely start working on this for PostgreSQL soon and push a branch where you can push for MySQL and MSSQL. |
We should do what JDBC did here and raise an exception if a user attempts to use a prepared statement from a closed connection |
If we let users hold references to the prepared statement and cache it themselves, how would a user know which connection the cached prepared statement is running? In that way it's impossible to chain a cached prepared statement execution and other operations in the same stateful connection. I believe we need to cache the |
I don't expect users will keep a cache of multiple prepared statements (e.g. a map/set of PS), rather, I expect users will want to cache individual prepared statements and throwing an exception would just be a way to guard against application programming errors where the user caches the PS beyond the scope of the connection. |
I updated the document @BillyYccc @aguibert I will share a branch so you can look at the changes in practice |
@vietj can you elaborate a bit on the goal of this issue? Is it for correctness in order to resolve bugs with certain usage patterns? Or is this more of a performance improvement? |
it is for correctness (with pipelining there are some out of order command execution happening), we are currently also having a regression for PostgreSQL under high load but this is a side effect. |
the fact that a cached one-shot query implicitly creates a |
this also improves a few things I was not comfortable with such as the |
I added a link to the draft PR |
@BillyYccc we can discuss the caching of API |
Updated the proposal |
Some implementations need to close the prepared statement after the execution of the |
Currently one shot prepared query is a composite execution of a
PrepareStatementCommand
andExtendedQueryCommand
. The first command will prepare the statement and the later will execute it.When prepare statement are cached, the
PrepareStatementCommand
is only executed once (assuming the statement is not evicted from the cache).When prepare statement are not cached then it is unclear what should happen and likely this depends on the database.
What we have now
PostgreSQL
What is happening
Todo (study)
What should happen
A two steps executions issues the following commands
PrepareCommand
ExtendedPreparedQuery
One shot prepared query should be executed using un-named prepared statement, so the sequence above is replaced by:
MySQL
What is happening
two-step executions(i.e. prepare->execute) & one-shot preparedQuery
PrepareCommand
send
COM_STMT_PREPARE
to serverExtendedQueryCommand
locally bind the parameters and set the metadata
send
COM_STMT_EXECUTE
to serverCloseStatementCommand
send
COM_STMT_CLOSE
to serverWhat should happen
There is no one-shot prepared-query protocol specific command in MySQL. so we can't change the command flow.
MSSQL
What is happening
two-step executions(i.e. prepare->execute) & one-shot preparedQuery
PrepareCommand
do nothing but store the SQL string in the client
ExtendedQueryCommand
locally bind the parameters and set the metadata
send
sp_executesql
request to the serverCloseStatementCommand
do nothing because we use
sp_executesql
What should happen
two-step executions(i.e. prepare->execute)
PrepareCommand
send
sp_prepare
request to the serverExtendedQueryCommand
send
sp_execute
request to the serverCloseStatementCommand
send
sp_unprepare
request to the serverone-shot preparedQuery
send
sp_executesql
request to the server (using T-SQL)DB2
What is happening
PrepareCommand
Send
PREPARE
andDESCRIBE
commandsExtendedQueryCommand
Send
OPEN_QUERY
passing statement params in bound according to column metadata retrieved fromPREPARE
andDESCRIBE
CloseStatementCommand
No-op
What should happen
TBD: I can tell from tracing JDBC on Wireshark that it's possible to flow
PREPARE
,DESCRIBE
, andOPEN_QUERY
all at once (i.e. 1 db round-trip instead of 2), but I will need to investigate this more. It's not immediately obvious how this is possible because I need to read the response from the PREP+DESC in order to bind params properly for the OPNQRYProposal
Here is the proposal for changes.
The current commands
PrepareStatement
andExtendedQueryCommand
will remain but they will be used differently.The main difference with the current scheme is that executing a one-shot query is achieved with an
ExtendedQueryCommand
with a null internalPreparedStatement
.In the current flow, a
PrepareStatement
command is issued and then and thenExtendedQueryCommand
is executed. Which can lead to out of order command execution.Two steps prepared query
SqlConnection.prepare(sql)
method triggers the execution of aPrepareStatement
command and gets back an internalPreparedStatement
that is cached in the APIPreparedStatement
objectPreparedStatement.query().execute(tuple)
method triggers the execution of aExtendedQueryCommand
with the internalPreparedStatement
for executionThis is more or less like before.
One step cached prepared query
SqlClient#preparedQuery(sql).execute(tuple)
triggers the execution of anExtendedQueryCommand
without an internalPreparedStatement
and with thecached
boolean set totrue
.PreparedStatement
thenPrepareStatementCommand
PreparedStatement
will be cachedExtendedQueryCommand
executes using thisPreparedStatement
PreparedStatement
then the codec executes a single step query as we fall back in the usual caseOne step prepared query (no caching)
SqlClient#preparedQuery(sql).execute(tuple)
triggers the execution of anExtendedQueryCommand
without an internalPreparedStatement
and with thecached
boolean set tofalse
PrepareStatementCommand
ExtendedQueryCommand
executes with thePreparedStatement
Note for PostgreSQL, preparing a non cached one-shot prepared query uses the unnamed statement and does not require a close after the statement it used.
PRs
NOTE: this PR unifies also
ExtendedQueryCommand
andExtendedBatchQueryCommand
in a single command but it was a non initial goalThe text was updated successfully, but these errors were encountered: