Skip to content
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

jdbc: metadata: support prepared statements #249

Closed

Conversation

nicktorwald
Copy link

@nicktorwald nicktorwald commented Dec 1, 2019

Affects: #213
Closes: #106
Closes: #198
Follows on: #173

@coveralls
Copy link

coveralls commented Dec 1, 2019

Coverage Status

Coverage decreased (-1.7%) to 75.92% when pulling a404c8d on nicktorwald/gh-198-server-prepared-statement into 4ba88fb on master.

@nicktorwald nicktorwald force-pushed the nicktorwald/gh-198-server-prepared-statement branch from c42ebdc to db21a6a Compare December 4, 2019 08:32
@nicktorwald
Copy link
Author

At this moment the driver can obtain parameter info (params) after PREPARE where there are only ANY parameter types.
I'm not sure, should it be solved as a part of prepared statement cache issue but it will be useful for ParameterMetaData class support.

box.prepare("SELECT * from s1 WHERE id > ? and val = ?")
---
- execute: 'function: 0x01071caa98'
  sql_str: SELECT * from s1 WHERE id > ? and val = ?
  params:
  - name: '?'
    type: ANY
  - name: '?'
    type: ANY
  metadata:
  - name: ID
    type: integer
  - name: VAL
    type: string
  param_count: 2
...

The driver can connect to different Tarantool instances within a range
of server versions. Sometimes, it's required to set a driver behaviour
depending on those versions (i.e. in scope of #213 the driver needs to
generate the functions for JDBC C4 LTRIM/RTRIM that are recognizable by
a particular Tarantool version).

This commit also includes implementation of two public DatabaseMetaData
methods getDatabaseMajorVersion and getDatabaseMinorVersion.

Affects: #213
Closes: #106
Tarantool introduced a new PREPARE protocol operation to be able to
create a prepared statement on the server side. This can be used by
JDBC SQLPreparedStatement implementation that will prepare its
query in advance to get meta data as well as reuse it multiple times.
These JDBC features will be introduced in future commits.

This commit add all the required protocol constants and allow
TarantoolClient to abstract from concrete operation codes related to
SQL. Because the native client does not provide API to perform PREPARE
it does not handle it in completeSql() as a completely unexpected
operation here.

Follows on: #198
@nicktorwald nicktorwald force-pushed the nicktorwald/gh-198-server-prepared-statement branch from db21a6a to 86b3c43 Compare January 20, 2020 02:16
@nicktorwald nicktorwald changed the title WIP: prepared statement metadata jdbc: metadata: support prepared statements Jan 20, 2020
Tarantool supports prepared statements since 2.3.1 that can be used
by java.sql.PreparedStatement to prepare the underlying query in
advance. If the driver connects to Tarantool which supports the prepared
statements then each PreparedStatement object acts as a corresponding
server prepared statement in terms of its behaviour (including
expiration or invalidation of statements - i.e. after DDL operations).
It also makes possible to obtain statement meta data via getMetaData
and getParameterMetaData without having to execute the query.

This commit extends TarantoolConnection API by new `prepare` and
`deallocate` methods that allow to deal with server prepared statements.
It caused a small reworking of a query execution process in
SQLConnection where QueryCommand abstraction was introduced. Another
extension is support of PreparedStatement that works in two different
modes now: legacy mode when server prepared statements are not available
(driver will send sql text + parameters as a separate queries when each
execution is performed) and new mode when they are supported (each
PreparedStatement covers the server prepared statement and sends
statement id + parameters).

There are a few issues on using the prepared statement now.
The first, it is required to deallocate prepared statements explicitly,
(no an eviction strategy on the server side) so PreparedStatement tries
to perform it when close() method is called. It causes the second issue.
The second, Tarantool does not distinguish query duplicates within one
session that can cause unexpected user experience. Let's say there are
two PreparedStatements that were prepared using the same query string.
If one of them closes it makes another statement broken because of they
reused the same session prepared statement. To overcome this issue the
driver connection tracks its own statements references. When the
particular statement reference count reaches zero it will safely
unprepared it on the server side.
The third, the prepared statement is invalidated by DDL queries or
the disconnection. Tarantool does not support auto re-preparing after
DDL operation at this moment, so it requires to be re-prepared for all
cached statements. Here, the PreparedStatement repeats behaviour of
Lua implementation for `box` module - returns an error when it
expired or deleted.

Closes: #198
In addition to result set metadata it's possible to examine parameters
of PreparedStatement using getParameterMetaData() method. Because
Tarantool returns extra info related to query parameters as a result of
PREPARE operation, we can fill ParameterMetaData by available info.

However, the server sends always 'ANY' as a target parameter type for
parameters and the driver treats all of them as UNKNOWN type. Once the
server starts to send proper types (such as integer, string and so on)
the driver should parse it automatically (required to be tested in
future).

Follows on: #173
@nicktorwald nicktorwald force-pushed the nicktorwald/gh-198-server-prepared-statement branch from 86b3c43 to a404c8d Compare January 20, 2020 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

jdbc: NPE when with libreoffice base tool jdbc: metadata: retrieve database version
3 participants