mapepire-python 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapepire_python/client/query.py +132 -0
- mapepire_python/client/sql_job.py +130 -0
- mapepire_python/pool.py +29 -0
- mapepire_python/py.typed +0 -0
- mapepire_python/ssl.py +19 -0
- mapepire_python/types.py +239 -0
- mapepire_python/version.py +11 -0
- mapepire_python-0.1.3.dist-info/LICENSE +201 -0
- mapepire_python-0.1.3.dist-info/METADATA +637 -0
- mapepire_python-0.1.3.dist-info/RECORD +12 -0
- mapepire_python-0.1.3.dist-info/WHEEL +5 -0
- mapepire_python-0.1.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, Dict, Generic, List, Optional, TypeVar, Union
|
|
4
|
+
|
|
5
|
+
from ..types import QueryOptions
|
|
6
|
+
from .sql_job import SQLJob
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class QueryState(Enum):
|
|
12
|
+
NOT_YET_RUN = (1,)
|
|
13
|
+
RUN_MORE_DATA_AVAIL = (2,)
|
|
14
|
+
RUN_DONE = (3,)
|
|
15
|
+
ERROR = 4
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_query_options(opts: Optional[Union[Dict[str, Any], QueryOptions]] = None) -> QueryOptions:
|
|
19
|
+
if isinstance(opts, QueryOptions):
|
|
20
|
+
return opts
|
|
21
|
+
elif opts:
|
|
22
|
+
return QueryOptions(**opts)
|
|
23
|
+
else:
|
|
24
|
+
return QueryOptions(isClCommand=False, parameters=None, autoClose=False)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Query(Generic[T]):
|
|
28
|
+
global_query_list: List["Query[Any]"] = []
|
|
29
|
+
|
|
30
|
+
def __init__(self, job: SQLJob, query: str, opts: QueryOptions) -> None:
|
|
31
|
+
self.job = job
|
|
32
|
+
self.is_prepared: bool = True if opts.parameters is not None else False
|
|
33
|
+
self.parameters: Optional[List[str]] = opts.parameters
|
|
34
|
+
self.sql: str = query
|
|
35
|
+
self.is_cl_command: Optional[bool] = opts.isClCommand
|
|
36
|
+
self.should_auto_close: Optional[bool] = opts.autoClose
|
|
37
|
+
self.is_terse_results: Optional[bool] = opts.isTerseResults
|
|
38
|
+
|
|
39
|
+
self._rows_to_fetch: int = 100
|
|
40
|
+
self.state: QueryState = QueryState.NOT_YET_RUN
|
|
41
|
+
|
|
42
|
+
Query.global_query_list.append(self)
|
|
43
|
+
|
|
44
|
+
def run(self, rows_to_fetch: Optional[int] = None) -> Dict[str, Any]:
|
|
45
|
+
if rows_to_fetch is None:
|
|
46
|
+
rows_to_fetch = self._rows_to_fetch
|
|
47
|
+
else:
|
|
48
|
+
self._rows_to_fetch = rows_to_fetch
|
|
49
|
+
|
|
50
|
+
# check Query state first
|
|
51
|
+
if self.state == QueryState.RUN_MORE_DATA_AVAIL:
|
|
52
|
+
raise Exception("Statement has already been run")
|
|
53
|
+
elif self.state == QueryState.RUN_DONE:
|
|
54
|
+
raise Exception("Statement has already been fully run")
|
|
55
|
+
|
|
56
|
+
query_object: Dict[str, Any] = {}
|
|
57
|
+
if self.is_cl_command:
|
|
58
|
+
query_object = {
|
|
59
|
+
"id": self.job._get_unique_id("clcommand"),
|
|
60
|
+
"type": "cl",
|
|
61
|
+
"terse": self.is_terse_results,
|
|
62
|
+
"cmd": self.sql,
|
|
63
|
+
}
|
|
64
|
+
else:
|
|
65
|
+
query_object = {
|
|
66
|
+
"id": self.job._get_unique_id("query"),
|
|
67
|
+
"type": "prepare_sql_execute" if self.is_prepared else "sql",
|
|
68
|
+
"sql": self.sql,
|
|
69
|
+
"terse": self.is_terse_results,
|
|
70
|
+
"rows": rows_to_fetch,
|
|
71
|
+
"parameters": self.parameters,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
self.job.send(json.dumps(query_object))
|
|
75
|
+
query_result: Dict[str, Any] = json.loads(self.job._socket.recv())
|
|
76
|
+
|
|
77
|
+
self.state = (
|
|
78
|
+
QueryState.RUN_DONE
|
|
79
|
+
if query_result.get("is_done", False)
|
|
80
|
+
else QueryState.RUN_MORE_DATA_AVAIL
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if not query_result.get("success", False) and not self.is_cl_command:
|
|
84
|
+
print(query_result)
|
|
85
|
+
self.state = QueryState.ERROR
|
|
86
|
+
error_keys = ["error", "sql_state", "sql_rc"]
|
|
87
|
+
error_list = {
|
|
88
|
+
key: query_result[key] for key in error_keys if key in query_result.keys()
|
|
89
|
+
}
|
|
90
|
+
if len(error_list) == 0:
|
|
91
|
+
error_list["error"] = "failed to run query for unknown reason"
|
|
92
|
+
|
|
93
|
+
raise Exception(error_list)
|
|
94
|
+
|
|
95
|
+
self._correlation_id = query_result["id"]
|
|
96
|
+
|
|
97
|
+
return query_result
|
|
98
|
+
|
|
99
|
+
def fetch_more(self, rows_to_fetch: Optional[int] = None) -> Dict[str, Any]:
|
|
100
|
+
if rows_to_fetch is None:
|
|
101
|
+
rows_to_fetch = self._rows_to_fetch
|
|
102
|
+
else:
|
|
103
|
+
self._rows_to_fetch = rows_to_fetch
|
|
104
|
+
|
|
105
|
+
if self.state == QueryState.NOT_YET_RUN:
|
|
106
|
+
raise Exception("Statement has not been run")
|
|
107
|
+
elif self.state == QueryState.RUN_DONE:
|
|
108
|
+
raise Exception("Statement has already been fully run")
|
|
109
|
+
|
|
110
|
+
query_object = {
|
|
111
|
+
"id": self.job._get_unique_id("fetchMore"),
|
|
112
|
+
"cont_id": self._correlation_id,
|
|
113
|
+
"type": "sqlmore",
|
|
114
|
+
"sql": self.sql,
|
|
115
|
+
"rows": rows_to_fetch,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
self._rows_to_fetch = rows_to_fetch
|
|
119
|
+
self.job.send(json.dumps(query_object))
|
|
120
|
+
query_result: Dict[str, Any] = json.loads(self.job._socket.recv())
|
|
121
|
+
|
|
122
|
+
self.state = (
|
|
123
|
+
QueryState.RUN_DONE
|
|
124
|
+
if query_result.get("is_done", False)
|
|
125
|
+
else QueryState.RUN_MORE_DATA_AVAIL
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if not query_result["success"]:
|
|
129
|
+
self.state = QueryState.ERROR
|
|
130
|
+
raise Exception(query_result["error"] or "Failed to run Query (unknown error)")
|
|
131
|
+
|
|
132
|
+
return query_result
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import json
|
|
3
|
+
import ssl
|
|
4
|
+
from typing import Any, Dict, Optional, Union
|
|
5
|
+
|
|
6
|
+
from websocket import WebSocket, create_connection
|
|
7
|
+
|
|
8
|
+
from ..types import DaemonServer, JobStatus, QueryOptions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SQLJob:
|
|
12
|
+
def __init__(self, options: Dict[Any, Any] = {}) -> None:
|
|
13
|
+
self.options = options
|
|
14
|
+
self._unique_id_counter: int = 0
|
|
15
|
+
self._reponse_emitter = None
|
|
16
|
+
self._status: JobStatus = JobStatus.NotStarted
|
|
17
|
+
self._trace_file = None
|
|
18
|
+
self._is_tracing_channeldata: bool = True
|
|
19
|
+
|
|
20
|
+
self.__unique_id = self._get_unique_id("sqljob")
|
|
21
|
+
self.id: Optional[str] = None
|
|
22
|
+
|
|
23
|
+
def _get_unique_id(self, prefix: str = "id") -> str:
|
|
24
|
+
self._unique_id_counter += 1
|
|
25
|
+
return f"{prefix}{self._unique_id_counter}"
|
|
26
|
+
|
|
27
|
+
def _get_channel(self, db2_server: DaemonServer) -> WebSocket:
|
|
28
|
+
uri = f"wss://{db2_server.host}:{db2_server.port}/db/"
|
|
29
|
+
headers = {
|
|
30
|
+
"Authorization": "Basic "
|
|
31
|
+
+ base64.b64encode(f"{db2_server.user}:{db2_server.password}".encode()).decode("ascii")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Prepare SSL context if necessary
|
|
35
|
+
ssl_opts: Dict[str, Any] = {}
|
|
36
|
+
if db2_server.ignoreUnauthorized:
|
|
37
|
+
ssl_opts["cert_reqs"] = ssl.CERT_NONE
|
|
38
|
+
if db2_server.ca:
|
|
39
|
+
ssl_context = ssl.create_default_context(cadata=db2_server.ca)
|
|
40
|
+
ssl_context.check_hostname = False
|
|
41
|
+
ssl_opts["ssl_context"] = ssl_context
|
|
42
|
+
ssl_opts["cert_reqs"] = ssl.CERT_NONE # ignore certs for now
|
|
43
|
+
|
|
44
|
+
# Create WebSocket connection
|
|
45
|
+
socket = create_connection(uri, header=headers, sslopt=ssl_opts)
|
|
46
|
+
|
|
47
|
+
return socket
|
|
48
|
+
|
|
49
|
+
def send(self, content):
|
|
50
|
+
self._socket.send(content)
|
|
51
|
+
|
|
52
|
+
def connect(self, db2_server: DaemonServer) -> Dict[Any, Any]:
|
|
53
|
+
self._socket: WebSocket = self._get_channel(db2_server)
|
|
54
|
+
|
|
55
|
+
props = ";".join(
|
|
56
|
+
[
|
|
57
|
+
f'{prop}={",".join(self.options[prop]) if isinstance(self.options[prop], list) else self.options[prop]}'
|
|
58
|
+
for prop in self.options
|
|
59
|
+
]
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
connection_props = {
|
|
63
|
+
"id": self._get_unique_id(),
|
|
64
|
+
"type": "connect",
|
|
65
|
+
"technique": "tcp",
|
|
66
|
+
"application": "Python Client",
|
|
67
|
+
"props": props if len(props) > 0 else "",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
self.send(json.dumps(connection_props))
|
|
71
|
+
result: Dict[str, Any] = {}
|
|
72
|
+
try:
|
|
73
|
+
result = json.loads(self._socket.recv())
|
|
74
|
+
except Exception as e:
|
|
75
|
+
print(f"an error occured while loading connect result: {e}")
|
|
76
|
+
|
|
77
|
+
if result.get("success", False):
|
|
78
|
+
self._status = JobStatus.Ready
|
|
79
|
+
else:
|
|
80
|
+
self._status = JobStatus.NotStarted
|
|
81
|
+
raise Exception(result.get("error", "Failed to connect to server"))
|
|
82
|
+
|
|
83
|
+
self.id = result["job"]
|
|
84
|
+
self._is_tracing_channeldata = False
|
|
85
|
+
|
|
86
|
+
return result
|
|
87
|
+
|
|
88
|
+
def query(
|
|
89
|
+
self,
|
|
90
|
+
sql: str,
|
|
91
|
+
opts: Optional[Union[Dict[str, Any], QueryOptions]] = None,
|
|
92
|
+
):
|
|
93
|
+
"""
|
|
94
|
+
Create a Query object using provided SQL and options. If opts is None,
|
|
95
|
+
the default options defined in Query constructor are used. opts can be a
|
|
96
|
+
dictionary to be converted to QueryOptions, or a QueryOptions object directly.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
sql (str): The SQL query string.
|
|
100
|
+
opts (Optional[Union[Dict[str, Any], QueryOptions]]): Additional options
|
|
101
|
+
for the query which can be a dictionary or a QueryOptions object.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Query: A configured Query object.
|
|
105
|
+
"""
|
|
106
|
+
from .query import Query
|
|
107
|
+
|
|
108
|
+
if opts is not None and not isinstance(opts, (dict, QueryOptions)):
|
|
109
|
+
raise ValueError("opts must be a dictionary, a QueryOptions object, or None")
|
|
110
|
+
|
|
111
|
+
query_options = (
|
|
112
|
+
opts
|
|
113
|
+
if isinstance(opts, QueryOptions)
|
|
114
|
+
else (
|
|
115
|
+
QueryOptions(**opts)
|
|
116
|
+
if opts
|
|
117
|
+
else QueryOptions(isClCommand=False, parameters=None, autoClose=False)
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return Query(job=self, query=sql, opts=query_options)
|
|
122
|
+
|
|
123
|
+
def query_and_run(
|
|
124
|
+
self, sql: str, opts: Optional[Dict[str, Any]] = None, **kwargs
|
|
125
|
+
) -> Dict[str, Any]:
|
|
126
|
+
query = self.query(sql, opts)
|
|
127
|
+
return query.run(**kwargs)
|
|
128
|
+
|
|
129
|
+
def close(self):
|
|
130
|
+
self._socket.close()
|
mapepire_python/pool.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# from dataclasses import dataclass
|
|
2
|
+
# from typing import List, Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# from mapepire_python.client.sql_job import SQLJob
|
|
6
|
+
# from mapepire_python.types import *
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# @dataclass
|
|
10
|
+
# class PoolOptions:
|
|
11
|
+
# creds: DaemonServer
|
|
12
|
+
# opts: Optional[JDBCOptions]
|
|
13
|
+
# max_size: int
|
|
14
|
+
# starting_size: int
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# class Pool:
|
|
18
|
+
# def __init__(self, options: PoolOptions) -> None:
|
|
19
|
+
# self.options = options
|
|
20
|
+
# self.jobs: List[SQLJob] = []
|
|
21
|
+
|
|
22
|
+
# def init(self):
|
|
23
|
+
# ...
|
|
24
|
+
|
|
25
|
+
# async def add_job(self):
|
|
26
|
+
# new_job = SQLJob(self.options.opts)
|
|
27
|
+
# self.jobs.append(new_job)
|
|
28
|
+
# new_job.connect(self.options.creds)
|
|
29
|
+
# return new_job
|
mapepire_python/py.typed
ADDED
|
File without changes
|
mapepire_python/ssl.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import socket
|
|
2
|
+
import ssl
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .types import DaemonServer
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_certificate(creds: DaemonServer) -> Optional[bytes]:
|
|
9
|
+
context = ssl.create_default_context()
|
|
10
|
+
context.check_hostname = False
|
|
11
|
+
context.verify_mode = ssl.CERT_NONE
|
|
12
|
+
|
|
13
|
+
if creds.ca:
|
|
14
|
+
context.load_verify_locations(
|
|
15
|
+
cadata=creds.ca if isinstance(creds.ca, str) else creds.ca.decode()
|
|
16
|
+
)
|
|
17
|
+
with socket.create_connection((creds.host, creds.port)) as sock:
|
|
18
|
+
with context.wrap_socket(sock, server_hostname=creds.host) as ssock:
|
|
19
|
+
return ssock.getpeercert(binary_form=True)
|
mapepire_python/types.py
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
from dataclasses_json import dataclass_json
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JobStatus(Enum):
|
|
9
|
+
NotStarted = "notStarted"
|
|
10
|
+
Ready = "ready"
|
|
11
|
+
Busy = "busy"
|
|
12
|
+
Ended = "ended"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ExplainType(Enum):
|
|
16
|
+
Run = 0
|
|
17
|
+
DoNotRun = 1
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TransactionEndType(Enum):
|
|
21
|
+
COMMIT = 0
|
|
22
|
+
ROLLBACK = 1
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ServerTraceLevel(Enum):
|
|
26
|
+
OFF = "OFF"
|
|
27
|
+
ON = "ON"
|
|
28
|
+
ERRORS = "ERRORS"
|
|
29
|
+
DATASTREAM = "DATASTREAM"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ServerTraceDest(Enum):
|
|
33
|
+
FILE = "FILE"
|
|
34
|
+
IN_MEM = "IN_MEM"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class DaemonServer:
|
|
39
|
+
host: str
|
|
40
|
+
user: str
|
|
41
|
+
password: str
|
|
42
|
+
port: int
|
|
43
|
+
ignoreUnauthorized: Optional[bool] = None
|
|
44
|
+
ca: Optional[Union[str, bytes]] = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass_json
|
|
48
|
+
@dataclass
|
|
49
|
+
class ServerResponse:
|
|
50
|
+
id: str
|
|
51
|
+
success: bool
|
|
52
|
+
sql_rc: int
|
|
53
|
+
sql_state: str
|
|
54
|
+
error: Optional[str] = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass_json
|
|
58
|
+
@dataclass
|
|
59
|
+
class ConnectionResult(ServerResponse):
|
|
60
|
+
job: str
|
|
61
|
+
id: str = field(init=False)
|
|
62
|
+
success: bool = field(init=False)
|
|
63
|
+
sql_rc: int = field(init=False)
|
|
64
|
+
sql_state: str = field(init=False)
|
|
65
|
+
error: Optional[str] = field(default=None, init=False)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass_json
|
|
69
|
+
@dataclass
|
|
70
|
+
class VersionCheckResult(ServerResponse):
|
|
71
|
+
build_date: str
|
|
72
|
+
version: str
|
|
73
|
+
id: str = field(init=False)
|
|
74
|
+
success: bool = field(init=False)
|
|
75
|
+
sql_rc: int = field(init=False)
|
|
76
|
+
sql_state: str = field(init=False)
|
|
77
|
+
error: Optional[str] = field(default=None, init=False)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class ColumnMetaData:
|
|
82
|
+
display_size: int
|
|
83
|
+
label: str
|
|
84
|
+
name: str
|
|
85
|
+
type: str
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class QueryMetaData:
|
|
90
|
+
column_count: int
|
|
91
|
+
columns: List[ColumnMetaData]
|
|
92
|
+
job: str
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class QueryResult:
|
|
97
|
+
metadata: QueryMetaData
|
|
98
|
+
is_done: bool
|
|
99
|
+
has_results: bool
|
|
100
|
+
update_count: int
|
|
101
|
+
data: List[Any]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass
|
|
105
|
+
class ExplainResults(QueryResult):
|
|
106
|
+
vemetadata: QueryMetaData
|
|
107
|
+
vedata: Any
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass_json
|
|
111
|
+
@dataclass
|
|
112
|
+
class GetTraceDataResult(ServerResponse):
|
|
113
|
+
tracedata: str
|
|
114
|
+
id: str = field(init=False)
|
|
115
|
+
success: bool = field(init=False)
|
|
116
|
+
sql_rc: int = field(init=False)
|
|
117
|
+
sql_state: str = field(init=False)
|
|
118
|
+
error: Optional[str] = field(default=None, init=False)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@dataclass
|
|
122
|
+
class JobLogEntry:
|
|
123
|
+
MESSAGE_ID: str
|
|
124
|
+
SEVERITY: str
|
|
125
|
+
MESSAGE_TIMESTAMP: str
|
|
126
|
+
FROM_LIBRARY: str
|
|
127
|
+
FROM_PROGRAM: str
|
|
128
|
+
MESSAGE_TYPE: str
|
|
129
|
+
MESSAGE_TEXT: str
|
|
130
|
+
MESSAGE_SECOND_LEVEL_TEXT: str
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@dataclass_json
|
|
134
|
+
@dataclass
|
|
135
|
+
class CLCommandResult(ServerResponse):
|
|
136
|
+
joblog: List[JobLogEntry]
|
|
137
|
+
id: str = field(init=False)
|
|
138
|
+
success: bool = field(init=False)
|
|
139
|
+
sql_rc: int = field(init=False)
|
|
140
|
+
sql_state: str = field(init=False)
|
|
141
|
+
error: Optional[str] = field(default=None, init=False)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass
|
|
145
|
+
class QueryOptions:
|
|
146
|
+
isTerseResults: Optional[bool] = None
|
|
147
|
+
isClCommand: Optional[bool] = None
|
|
148
|
+
parameters: Optional[List[str]] = None
|
|
149
|
+
autoClose: Optional[bool] = None
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass_json
|
|
153
|
+
@dataclass
|
|
154
|
+
class SetConfigResult(ServerResponse):
|
|
155
|
+
tracedest: ServerTraceDest
|
|
156
|
+
tracelevel: ServerTraceLevel
|
|
157
|
+
id: str = field(init=False)
|
|
158
|
+
success: bool = field(init=False)
|
|
159
|
+
sql_rc: int = field(init=False)
|
|
160
|
+
sql_state: str = field(init=False)
|
|
161
|
+
error: Optional[str] = field(default=None, init=False)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@dataclass
|
|
165
|
+
class JDBCOptions:
|
|
166
|
+
naming: Optional[str] = None
|
|
167
|
+
date_format: Optional[str] = None
|
|
168
|
+
date_separator: Optional[str] = None
|
|
169
|
+
decimal_separator: Optional[str] = None
|
|
170
|
+
time_format: Optional[str] = None
|
|
171
|
+
time_separator: Optional[str] = None
|
|
172
|
+
full_open: Optional[bool] = None
|
|
173
|
+
access: Optional[str] = None
|
|
174
|
+
autocommit_exception: Optional[bool] = None
|
|
175
|
+
bidi_string_type: Optional[str] = None
|
|
176
|
+
bidi_implicit_reordering: Optional[bool] = None
|
|
177
|
+
bidi_numeric_ordering: Optional[bool] = None
|
|
178
|
+
data_truncation: Optional[bool] = None
|
|
179
|
+
driver: Optional[str] = None
|
|
180
|
+
errors: Optional[str] = None
|
|
181
|
+
extended_metadata: Optional[bool] = None
|
|
182
|
+
hold_input_locators: Optional[bool] = None
|
|
183
|
+
hold_statements: Optional[bool] = None
|
|
184
|
+
ignore_warnings: Optional[str] = None
|
|
185
|
+
keep_alive: Optional[bool] = None
|
|
186
|
+
key_ring_name: Optional[str] = None
|
|
187
|
+
key_ring_password: Optional[str] = None
|
|
188
|
+
metadata_source: Optional[str] = None
|
|
189
|
+
proxy_server: Optional[str] = None
|
|
190
|
+
remarks: Optional[str] = None
|
|
191
|
+
secondary_URL: Optional[str] = None
|
|
192
|
+
secure: Optional[bool] = None
|
|
193
|
+
server_trace: Optional[str] = None
|
|
194
|
+
thread_used: Optional[bool] = None
|
|
195
|
+
toolbox_trace: Optional[str] = None
|
|
196
|
+
trace: Optional[bool] = None
|
|
197
|
+
translate_binary: Optional[bool] = None
|
|
198
|
+
translate_boolean: Optional[bool] = None
|
|
199
|
+
libraries: Optional[List[str]] = None
|
|
200
|
+
auto_commit: Optional[bool] = None
|
|
201
|
+
concurrent_access_resolution: Optional[str] = None
|
|
202
|
+
cursor_hold: Optional[bool] = None
|
|
203
|
+
cursor_sensitivity: Optional[str] = None
|
|
204
|
+
database_name: Optional[str] = None
|
|
205
|
+
decfloat_rounding_mode: Optional[str] = None
|
|
206
|
+
maximum_precision: Optional[str] = None
|
|
207
|
+
maximum_scale: Optional[str] = None
|
|
208
|
+
minimum_divide_scale: Optional[str] = None
|
|
209
|
+
package_ccsid: Optional[str] = None
|
|
210
|
+
transaction_isolation: Optional[str] = None
|
|
211
|
+
translate_hex: Optional[str] = None
|
|
212
|
+
true_autocommit: Optional[bool] = None
|
|
213
|
+
XA_loosely_coupled_support: Optional[str] = None
|
|
214
|
+
big_decimal: Optional[bool] = None
|
|
215
|
+
block_criteria: Optional[str] = None
|
|
216
|
+
block_size: Optional[str] = None
|
|
217
|
+
data_compression: Optional[bool] = None
|
|
218
|
+
extended_dynamic: Optional[bool] = None
|
|
219
|
+
lazy_close: Optional[bool] = None
|
|
220
|
+
lob_threshold: Optional[str] = None
|
|
221
|
+
maximum_blocked_input_rows: Optional[str] = None
|
|
222
|
+
package: Optional[str] = None
|
|
223
|
+
package_add: Optional[bool] = None
|
|
224
|
+
package_cache: Optional[bool] = None
|
|
225
|
+
package_criteria: Optional[str] = None
|
|
226
|
+
package_error: Optional[str] = None
|
|
227
|
+
package_library: Optional[str] = None
|
|
228
|
+
prefetch: Optional[bool] = None
|
|
229
|
+
qaqqinilib: Optional[str] = None
|
|
230
|
+
query_optimize_goal: Optional[str] = None
|
|
231
|
+
query_timeout_mechanism: Optional[str] = None
|
|
232
|
+
query_storage_limit: Optional[str] = None
|
|
233
|
+
receive_buffer_size: Optional[str] = None
|
|
234
|
+
send_buffer_size: Optional[str] = None
|
|
235
|
+
variable_field_compression: Optional[bool] = None
|
|
236
|
+
sort: Optional[str] = None
|
|
237
|
+
sort_language: Optional[str] = None
|
|
238
|
+
sort_table: Optional[str] = None
|
|
239
|
+
sort_weight: Optional[str] = None
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
_MAJOR = "0"
|
|
2
|
+
_MINOR = "1"
|
|
3
|
+
# On main and in a nightly release the patch should be one ahead of the last
|
|
4
|
+
# released build.
|
|
5
|
+
_PATCH = "3"
|
|
6
|
+
# This is mainly for nightly builds which have the suffix ".dev$DATE". See
|
|
7
|
+
# https://semver.org/#is-v123-a-semantic-version for the semantics.
|
|
8
|
+
_SUFFIX = ""
|
|
9
|
+
|
|
10
|
+
VERSION_SHORT = "{0}.{1}".format(_MAJOR, _MINOR)
|
|
11
|
+
VERSION = "{0}.{1}.{2}{3}".format(_MAJOR, _MINOR, _PATCH, _SUFFIX)
|