- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
2242 lines
55 KiB
Python
2242 lines
55 KiB
Python
"""
|
|
Java SQL standard library APIs implemented in Python.
|
|
java.sql package - Connection, Statement, ResultSet, Types, etc.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from .lang import RuntimeException, Exception as _JavaException
|
|
import datetime as _datetime
|
|
import typing as _typing
|
|
|
|
__all__ = [
|
|
"Connection", "Statement", "PreparedStatement", "CallableStatement",
|
|
"ResultSet", "ResultSetMetaData", "DatabaseMetaData",
|
|
"Driver", "DriverManager", "DriverPropertyInfo",
|
|
"SQLException", "SQLWarning", "SQLData", "SQLInput", "SQLOutput",
|
|
"BatchUpdateException", "DataTruncation",
|
|
"Date", "Time", "Timestamp", "Savepoint",
|
|
"Blob", "Clob", "NClob", "Ref", "RowId", "Struct", "SQLXML", "Array",
|
|
"Types", "JDBCType", "Wrapper",
|
|
"FETCH_FORWARD", "FETCH_REVERSE", "FETCH_UNKNOWN",
|
|
"TYPE_FORWARD_ONLY", "TYPE_SCROLL_INSENSITIVE", "TYPE_SCROLL_SENSITIVE",
|
|
"HOLD_CURSORS_OVER_COMMIT", "CLOSE_CURSORS_AT_COMMIT",
|
|
"CLOSE_ALL_RESULTS", "KEEP_CURRENT_RESULT",
|
|
"NO_GENERATED_KEYS", "RETURN_GENERATED_KEYS",
|
|
"CLOSE_CURRENT_RESULT",
|
|
]
|
|
|
|
# ============================================================
|
|
# Constants
|
|
# ============================================================
|
|
|
|
FETCH_FORWARD = 1000
|
|
FETCH_REVERSE = 1001
|
|
FETCH_UNKNOWN = 1002
|
|
|
|
TYPE_FORWARD_ONLY = 1003
|
|
TYPE_SCROLL_INSENSITIVE = 1004
|
|
TYPE_SCROLL_SENSITIVE = 1005
|
|
|
|
HOLD_CURSORS_OVER_COMMIT = 1
|
|
CLOSE_CURSORS_AT_COMMIT = 2
|
|
|
|
CLOSE_ALL_RESULTS = 1
|
|
KEEP_CURRENT_RESULT = 2
|
|
CLOSE_CURRENT_RESULT = 3
|
|
|
|
NO_GENERATED_KEYS = 1
|
|
RETURN_GENERATED_KEYS = 2
|
|
|
|
|
|
# ============================================================
|
|
# SQLException hierarchy
|
|
# ============================================================
|
|
|
|
class SQLException(_JavaException):
|
|
"""java.sql.SQLException"""
|
|
def __init__(self, reason=None, sql_state=None, vendor_code=0, cause=None):
|
|
msg = reason or ""
|
|
super().__init__(msg)
|
|
self._reason = reason
|
|
self._sql_state = sql_state
|
|
self._vendor_code = vendor_code
|
|
self._cause = cause
|
|
self._next_exception = None
|
|
|
|
def getMessage(self):
|
|
return self._reason or ""
|
|
|
|
def getSQLState(self):
|
|
return self._sql_state
|
|
|
|
def getErrorCode(self):
|
|
return self._vendor_code
|
|
|
|
def getNextException(self):
|
|
return self._next_exception
|
|
|
|
def setNextException(self, ex):
|
|
self._next_exception = ex
|
|
|
|
def getCause(self):
|
|
return self._cause
|
|
|
|
|
|
class SQLWarning(SQLException):
|
|
"""java.sql.SQLWarning"""
|
|
def __init__(self, reason=None, sql_state=None, vendor_code=0):
|
|
super().__init__(reason, sql_state, vendor_code)
|
|
self._next_warning = None
|
|
|
|
def getNextWarning(self):
|
|
return self._next_warning
|
|
|
|
def setNextWarning(self, warning):
|
|
self._next_warning = warning
|
|
|
|
|
|
class BatchUpdateException(SQLException):
|
|
"""java.sql.BatchUpdateException"""
|
|
def __init__(self, reason=None, sql_state=None, vendor_code=0,
|
|
update_counts=None, cause=None):
|
|
super().__init__(reason, sql_state, vendor_code, cause)
|
|
self._update_counts = update_counts or []
|
|
|
|
def getUpdateCounts(self):
|
|
return self._update_counts
|
|
|
|
def getLargeUpdateCounts(self):
|
|
return [int(c) for c in self._update_counts]
|
|
|
|
|
|
class DataTruncation(SQLWarning):
|
|
"""java.sql.DataTruncation"""
|
|
def __init__(self, index, parameter, read, data_size, transfer_size):
|
|
super().__init__("Data truncation")
|
|
self._index = index
|
|
self._parameter = parameter
|
|
self._read = read
|
|
self._data_size = data_size
|
|
self._transfer_size = transfer_size
|
|
|
|
def getIndex(self):
|
|
return self._index
|
|
|
|
def getParameter(self):
|
|
return self._parameter
|
|
|
|
def getRead(self):
|
|
return self._read
|
|
|
|
def getDataSize(self):
|
|
return self._data_size
|
|
|
|
def getTransferSize(self):
|
|
return self._transfer_size
|
|
|
|
|
|
# ============================================================
|
|
# Wrapper
|
|
# ============================================================
|
|
|
|
class Wrapper(Stub):
|
|
"""java.sql.Wrapper"""
|
|
def unwrap(self, iface):
|
|
if iface is None:
|
|
raise SQLException("iface is null")
|
|
return self
|
|
|
|
def isWrapperFor(self, iface):
|
|
return iface is not None and isinstance(self, iface)
|
|
|
|
|
|
# ============================================================
|
|
# Types Constants
|
|
# ============================================================
|
|
|
|
class Types:
|
|
"""java.sql.Types"""
|
|
ARRAY = 2003
|
|
BIGINT = -5
|
|
BINARY = -2
|
|
BIT = -7
|
|
BLOB = 2004
|
|
BOOLEAN = 16
|
|
CHAR = 1
|
|
CLOB = 2005
|
|
DATALINK = 70
|
|
DATE = 91
|
|
DECIMAL = 3
|
|
DISTINCT = 2001
|
|
DOUBLE = 8
|
|
FLOAT = 6
|
|
INTEGER = 4
|
|
JAVA_OBJECT = 2000
|
|
LONGNVARCHAR = -16
|
|
LONGVARBINARY = -4
|
|
LONGVARCHAR = -1
|
|
NCHAR = -15
|
|
NCLOB = 2011
|
|
NULL = 0
|
|
NUMERIC = 2
|
|
NVARCHAR = -9
|
|
OTHER = 1111
|
|
REAL = 7
|
|
REF = 2006
|
|
REF_CURSOR = 2012
|
|
ROWID = -8
|
|
SMALLINT = 5
|
|
SQLXML = 2009
|
|
STRUCT = 2002
|
|
TIME = 92
|
|
TIMESTAMP = 93
|
|
TINYINT = -6
|
|
VARBINARY = -3
|
|
VARCHAR = 12
|
|
|
|
|
|
class JDBCType(Stub):
|
|
"""java.sql.JDBCType"""
|
|
_type_map = {}
|
|
|
|
def __init__(self, vendor_type_number):
|
|
super().__init__()
|
|
self._vendor_type_number = vendor_type_number
|
|
|
|
def getVendorTypeNumber(self):
|
|
return self._vendor_type_number
|
|
|
|
def getName(self):
|
|
for name, val in vars(Types).items():
|
|
if isinstance(val, int) and val == self._vendor_type_number:
|
|
return name
|
|
return "UNKNOWN"
|
|
|
|
@staticmethod
|
|
def valueOf(name):
|
|
val = getattr(Types, name, None)
|
|
if val is None:
|
|
raise IllegalArgumentException(f"No JDBC type: {name}")
|
|
return JDBCType(val)
|
|
|
|
@staticmethod
|
|
def values():
|
|
return [JDBCType(v) for v in set(
|
|
v for v in vars(Types).values() if isinstance(v, int)
|
|
)]
|
|
|
|
|
|
# ============================================================
|
|
# Date / Time / Timestamp
|
|
# ============================================================
|
|
|
|
class Date(_datetime.date):
|
|
"""java.sql.Date"""
|
|
def __init__(self, *args):
|
|
if len(args) == 1:
|
|
ms = args[0]
|
|
dt = _datetime.datetime.fromtimestamp(ms / 1000.0)
|
|
super().__init__(dt.year, dt.month, dt.day)
|
|
elif len(args) == 3:
|
|
super().__init__(args[0], args[1], args[2])
|
|
else:
|
|
super().__init__()
|
|
|
|
def getTime(self):
|
|
dt = _datetime.datetime.combine(self, _datetime.time.min)
|
|
return int(dt.timestamp() * 1000)
|
|
|
|
def setTime(self, ms):
|
|
dt = _datetime.datetime.fromtimestamp(ms / 1000.0)
|
|
super().__init__(dt.year, dt.month, dt.day)
|
|
|
|
def toString(self):
|
|
return self.strftime("%Y-%m-%d")
|
|
|
|
@staticmethod
|
|
def valueOf(s):
|
|
parts = s.split("-")
|
|
return Date(int(parts[0]), int(parts[1]), int(parts[2]))
|
|
|
|
|
|
class Time(_datetime.time):
|
|
"""java.sql.Time"""
|
|
def __init__(self, *args):
|
|
if len(args) == 1:
|
|
ms = args[0]
|
|
dt = _datetime.datetime.fromtimestamp(ms / 1000.0)
|
|
super().__init__(dt.hour, dt.minute, dt.second)
|
|
elif len(args) == 3:
|
|
super().__init__(args[0], args[1], args[2])
|
|
else:
|
|
super().__init__()
|
|
|
|
def getTime(self):
|
|
dt = _datetime.datetime.combine(_datetime.date.today(), self)
|
|
return int(dt.timestamp() * 1000)
|
|
|
|
def setTime(self, ms):
|
|
dt = _datetime.datetime.fromtimestamp(ms / 1000.0)
|
|
super().__init__(dt.hour, dt.minute, dt.second)
|
|
|
|
def toString(self):
|
|
return self.strftime("%H:%M:%S")
|
|
|
|
@staticmethod
|
|
def valueOf(s):
|
|
parts = s.split(":")
|
|
return Time(int(parts[0]), int(parts[1]), int(parts[2]))
|
|
|
|
|
|
class Timestamp(_datetime.datetime):
|
|
"""java.sql.Timestamp"""
|
|
def __init__(self, *args):
|
|
if len(args) == 1:
|
|
ms = args[0]
|
|
dt = _datetime.datetime.fromtimestamp(ms / 1000.0)
|
|
super().__init__(dt.year, dt.month, dt.day, dt.hour,
|
|
dt.minute, dt.second, dt.microsecond)
|
|
self._nanos = (ms % 1000) * 1000000
|
|
else:
|
|
super().__init__(*args)
|
|
self._nanos = 0
|
|
|
|
def getTime(self):
|
|
return int(self.timestamp() * 1000)
|
|
|
|
def setTime(self, ms):
|
|
dt = _datetime.datetime.fromtimestamp(ms / 1000.0)
|
|
super().__init__(dt.year, dt.month, dt.day, dt.hour,
|
|
dt.minute, dt.second, dt.microsecond)
|
|
self._nanos = (ms % 1000) * 1000000
|
|
|
|
def getNanos(self):
|
|
return self._nanos
|
|
|
|
def setNanos(self, n):
|
|
self._nanos = n
|
|
|
|
def toString(self):
|
|
return self.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
@staticmethod
|
|
def valueOf(s):
|
|
parts = s.split(" ")
|
|
date_part = parts[0].split("-")
|
|
time_part = parts[1].split(":")
|
|
return Timestamp(int(date_part[0]), int(date_part[1]), int(date_part[2]),
|
|
int(time_part[0]), int(time_part[1]), int(time_part[2]))
|
|
|
|
|
|
# ============================================================
|
|
# Savepoint
|
|
# ============================================================
|
|
|
|
class Savepoint(Stub):
|
|
"""java.sql.Savepoint"""
|
|
def __init__(self, name=None):
|
|
super().__init__()
|
|
self._savepoint_id = id(self)
|
|
self._savepoint_name = name
|
|
|
|
def getSavepointId(self):
|
|
if self._savepoint_name is not None:
|
|
raise SQLException("Named savepoint")
|
|
return self._savepoint_id
|
|
|
|
def getSavepointName(self):
|
|
if self._savepoint_name is None:
|
|
raise SQLException("Unnamed savepoint")
|
|
return self._savepoint_name
|
|
|
|
|
|
# ============================================================
|
|
# Blob / Clob / NClob / Ref / RowId / Struct / SQLXML / Array
|
|
# ============================================================
|
|
|
|
class Blob(Stub):
|
|
"""java.sql.Blob"""
|
|
def __init__(self, data=b""):
|
|
super().__init__()
|
|
self._data = bytearray(data)
|
|
self._length = len(data)
|
|
|
|
def length(self):
|
|
return self._length
|
|
|
|
def getBytes(self, pos, length):
|
|
start = pos - 1
|
|
return bytes(self._data[start:start + length])
|
|
|
|
def setBytes(self, pos, bytes_data, offset=0, length=None):
|
|
start = pos - 1
|
|
if length is None:
|
|
length = len(bytes_data) - offset
|
|
self._data[start:start + length] = bytearray(bytes_data[offset:offset + length])
|
|
return length
|
|
|
|
def position(self, pattern, start):
|
|
return -1
|
|
|
|
def truncate(self, length):
|
|
self._data = self._data[:length]
|
|
self._length = length
|
|
|
|
def free(self):
|
|
self._data = bytearray()
|
|
self._length = 0
|
|
|
|
def getBinaryStream(self, pos=None, length=None):
|
|
import io
|
|
return io.BytesIO(bytes(self._data))
|
|
|
|
|
|
class Clob(Stub):
|
|
"""java.sql.Clob"""
|
|
def __init__(self, data=""):
|
|
super().__init__()
|
|
self._data = data
|
|
self._length = len(data)
|
|
|
|
def length(self):
|
|
return self._length
|
|
|
|
def getSubString(self, pos, length):
|
|
start = pos - 1
|
|
return self._data[start:start + length]
|
|
|
|
def setString(self, pos, val, offset=0, length=None):
|
|
start = pos - 1
|
|
if length is None:
|
|
length = len(val) - offset
|
|
self._data = self._data[:start] + val[offset:offset + length] + self._data[start + length:]
|
|
return length
|
|
|
|
def position(self, search_str, start):
|
|
return self._data.find(search_str, start - 1)
|
|
|
|
def truncate(self, length):
|
|
self._data = self._data[:length]
|
|
self._length = length
|
|
|
|
def free(self):
|
|
self._data = ""
|
|
self._length = 0
|
|
|
|
def getAsciiStream(self):
|
|
import io
|
|
return io.BytesIO(self._data.encode())
|
|
|
|
def getCharacterStream(self, pos=None, length=None):
|
|
import io
|
|
if pos is not None and length is not None:
|
|
return io.StringIO(self._data[pos - 1:pos - 1 + length])
|
|
return io.StringIO(self._data)
|
|
|
|
def setAsciiStream(self, pos, stream, length=None):
|
|
data = stream.read() if length is None else stream.read(length)
|
|
if isinstance(data, bytes):
|
|
data = data.decode()
|
|
self._data = self._data[:pos - 1] + data + self._data[pos - 1 + len(data):]
|
|
|
|
|
|
class NClob(Clob):
|
|
"""java.sql.NClob"""
|
|
pass
|
|
|
|
|
|
class Ref(Stub):
|
|
"""java.sql.Ref"""
|
|
def __init__(self, base_type_name=None, obj=None):
|
|
super().__init__()
|
|
self._base_type_name = base_type_name
|
|
self._object = obj
|
|
|
|
def getBaseTypeName(self):
|
|
return self._base_type_name
|
|
|
|
def getObject(self, type_map=None):
|
|
return self._object
|
|
|
|
def setObject(self, obj):
|
|
self._object = obj
|
|
|
|
|
|
class RowId(Stub):
|
|
"""java.sql.RowId"""
|
|
def __init__(self, data=b""):
|
|
super().__init__()
|
|
self._data = bytes(data)
|
|
|
|
def getBytes(self):
|
|
return self._data
|
|
|
|
def toString(self):
|
|
return self._data.hex()
|
|
|
|
def equals(self, other):
|
|
if not isinstance(other, RowId):
|
|
return False
|
|
return self._data == other._data
|
|
|
|
def hashCode(self):
|
|
return hash(self._data)
|
|
|
|
|
|
class Struct(Stub):
|
|
"""java.sql.Struct"""
|
|
def __init__(self, sql_type_name, attributes):
|
|
super().__init__()
|
|
self._sql_type_name = sql_type_name
|
|
self._attributes = list(attributes)
|
|
|
|
def getSQLTypeName(self):
|
|
return self._sql_type_name
|
|
|
|
def getAttributes(self, type_map=None):
|
|
return self._attributes
|
|
|
|
|
|
class SQLXML(Stub):
|
|
"""java.sql.SQLXML"""
|
|
def __init__(self, xml_string=""):
|
|
super().__init__()
|
|
self._xml = xml_string
|
|
|
|
def getString(self):
|
|
return self._xml
|
|
|
|
def setString(self, value):
|
|
self._xml = value
|
|
|
|
def free(self):
|
|
self._xml = ""
|
|
|
|
def getBinaryStream(self):
|
|
import io
|
|
return io.BytesIO(self._xml.encode())
|
|
|
|
def setBinaryStream(self):
|
|
import io
|
|
buf = io.BytesIO()
|
|
return buf
|
|
|
|
def getCharacterStream(self):
|
|
import io
|
|
return io.StringIO(self._xml)
|
|
|
|
def setCharacterStream(self):
|
|
import io
|
|
buf = io.StringIO()
|
|
return buf
|
|
|
|
def getSource(self, source_class=None):
|
|
return None
|
|
|
|
def getResult(self, result_class=None):
|
|
return None
|
|
|
|
|
|
class Array(Stub):
|
|
"""java.sql.Array"""
|
|
def __init__(self, type_name=None, elements=None):
|
|
super().__init__()
|
|
self._type_name = type_name
|
|
self._elements = list(elements) if elements else []
|
|
|
|
def getBaseTypeName(self):
|
|
return self._type_name or "VARCHAR"
|
|
|
|
def getBaseType(self):
|
|
return Types.VARCHAR
|
|
|
|
def getArray(self, index=None, count=None):
|
|
if index is None:
|
|
return self._elements
|
|
start = index - 1
|
|
if count is None:
|
|
return self._elements[start:]
|
|
return self._elements[start:start + count]
|
|
|
|
def getResultSet(self, index=None, count=None):
|
|
raise SQLException("Not implemented")
|
|
|
|
|
|
# ============================================================
|
|
# SQLData / SQLInput / SQLOutput
|
|
# ============================================================
|
|
|
|
class SQLData(Stub):
|
|
"""java.sql.SQLData"""
|
|
def getSQLTypeName(self):
|
|
raise SQLException("Not implemented")
|
|
|
|
def readSQL(self, stream, type_name):
|
|
pass
|
|
|
|
def writeSQL(self, stream):
|
|
pass
|
|
|
|
|
|
class SQLInput(Stub):
|
|
"""java.sql.SQLInput"""
|
|
def __init__(self, data=None):
|
|
super().__init__()
|
|
self._data = list(data) if data else []
|
|
self._pos = 0
|
|
|
|
def readString(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return str(val) if val is not None else None
|
|
|
|
def readBoolean(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return bool(val)
|
|
|
|
def readByte(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return int(val) if val is not None else 0
|
|
|
|
def readShort(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return int(val) if val is not None else 0
|
|
|
|
def readInt(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return int(val) if val is not None else 0
|
|
|
|
def readLong(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return int(val) if val is not None else 0
|
|
|
|
def readFloat(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return float(val) if val is not None else 0.0
|
|
|
|
def readDouble(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return float(val) if val is not None else 0.0
|
|
|
|
def readBigDecimal(self):
|
|
return self.readDouble()
|
|
|
|
def readBytes(self):
|
|
return b""
|
|
|
|
def readDate(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
if isinstance(val, Date):
|
|
return val
|
|
return Date()
|
|
|
|
def readTime(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
if isinstance(val, Time):
|
|
return val
|
|
return Time()
|
|
|
|
def readTimestamp(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
if isinstance(val, Timestamp):
|
|
return val
|
|
return Timestamp()
|
|
|
|
def readCharacterStream(self):
|
|
import io
|
|
return io.StringIO("")
|
|
|
|
def readBinaryStream(self):
|
|
import io
|
|
return io.BytesIO(b"")
|
|
|
|
def readObject(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else None
|
|
self._pos += 1
|
|
return val
|
|
|
|
def readRef(self):
|
|
return Ref()
|
|
|
|
def readBlob(self):
|
|
return Blob()
|
|
|
|
def readClob(self):
|
|
return Clob()
|
|
|
|
def readArray(self):
|
|
return Array()
|
|
|
|
def readURL(self):
|
|
return None
|
|
|
|
def readNClob(self):
|
|
return NClob()
|
|
|
|
def readNString(self):
|
|
return self.readString()
|
|
|
|
def readSQLXML(self):
|
|
return SQLXML()
|
|
|
|
def readRowId(self):
|
|
return RowId()
|
|
|
|
def wasNull(self):
|
|
return False
|
|
|
|
|
|
class SQLOutput(Stub):
|
|
"""java.sql.SQLOutput"""
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._data = []
|
|
|
|
def writeString(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeBoolean(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeByte(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeShort(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeInt(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeLong(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeFloat(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeDouble(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeBigDecimal(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeBytes(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeDate(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeTime(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeTimestamp(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeCharacterStream(self, x):
|
|
self._data.append(x.read() if hasattr(x, 'read') else x)
|
|
|
|
def writeBinaryStream(self, x):
|
|
self._data.append(x.read() if hasattr(x, 'read') else x)
|
|
|
|
def writeObject(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeRef(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeBlob(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeClob(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeStruct(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeArray(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeURL(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeNClob(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeNString(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeSQLXML(self, x):
|
|
self._data.append(x)
|
|
|
|
def writeRowId(self, x):
|
|
self._data.append(x)
|
|
|
|
|
|
# ============================================================
|
|
# Driver / DriverManager / DriverPropertyInfo
|
|
# ============================================================
|
|
|
|
class Driver(Stub):
|
|
"""java.sql.Driver"""
|
|
def connect(self, url, info):
|
|
raise SQLException("No suitable driver")
|
|
|
|
def acceptsURL(self, url):
|
|
return False
|
|
|
|
def getPropertyInfo(self, url, info):
|
|
return []
|
|
|
|
def getMajorVersion(self):
|
|
return 1
|
|
|
|
def getMinorVersion(self):
|
|
return 0
|
|
|
|
def jdbcCompliant(self):
|
|
return False
|
|
|
|
def getParentLogger(self):
|
|
return None
|
|
|
|
|
|
class DriverPropertyInfo(Stub):
|
|
"""java.sql.DriverPropertyInfo"""
|
|
def __init__(self, name, value=None):
|
|
super().__init__()
|
|
self.name = name
|
|
self.description = None
|
|
self.required = False
|
|
self.value = value
|
|
self.choices = None
|
|
|
|
|
|
class DriverManager(Stub):
|
|
"""java.sql.DriverManager"""
|
|
_registered_drivers = []
|
|
_log_stream = None
|
|
_log_writer = None
|
|
_login_timeout = 0
|
|
|
|
@staticmethod
|
|
def getConnection(url, user=None, password=None):
|
|
for driver in DriverManager._registered_drivers:
|
|
if driver.acceptsURL(url):
|
|
props = {}
|
|
if user is not None:
|
|
props["user"] = user
|
|
if password is not None:
|
|
props["password"] = password
|
|
return driver.connect(url, props)
|
|
raise SQLException(f"No suitable driver found for {url}")
|
|
|
|
@staticmethod
|
|
def registerDriver(driver):
|
|
DriverManager._registered_drivers.append(driver)
|
|
|
|
@staticmethod
|
|
def deregisterDriver(driver):
|
|
if driver in DriverManager._registered_drivers:
|
|
DriverManager._registered_drivers.remove(driver)
|
|
|
|
@staticmethod
|
|
def getDrivers():
|
|
return DriverManager._registered_drivers
|
|
|
|
@staticmethod
|
|
def getLoginTimeout():
|
|
return DriverManager._login_timeout
|
|
|
|
@staticmethod
|
|
def setLoginTimeout(seconds):
|
|
DriverManager._login_timeout = seconds
|
|
|
|
@staticmethod
|
|
def getLogWriter():
|
|
return DriverManager._log_writer
|
|
|
|
@staticmethod
|
|
def setLogWriter(writer):
|
|
DriverManager._log_writer = writer
|
|
|
|
@staticmethod
|
|
def println(message):
|
|
if DriverManager._log_writer is not None:
|
|
DriverManager._log_writer.write(str(message) + "\n")
|
|
|
|
|
|
# ============================================================
|
|
# Connection
|
|
# ============================================================
|
|
|
|
class Connection(Stub):
|
|
"""java.sql.Connection"""
|
|
def createStatement(self):
|
|
return Statement()
|
|
|
|
def prepareStatement(self, sql):
|
|
return PreparedStatement(sql)
|
|
|
|
def prepareCall(self, sql):
|
|
return CallableStatement(sql)
|
|
|
|
def nativeSQL(self, sql):
|
|
return sql
|
|
|
|
def setAutoCommit(self, auto_commit):
|
|
pass
|
|
|
|
def getAutoCommit(self):
|
|
return True
|
|
|
|
def commit(self):
|
|
pass
|
|
|
|
def rollback(self, savepoint=None):
|
|
pass
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
def isClosed(self):
|
|
return False
|
|
|
|
def getMetaData(self):
|
|
return DatabaseMetaData()
|
|
|
|
def setReadOnly(self, read_only):
|
|
pass
|
|
|
|
def isReadOnly(self):
|
|
return False
|
|
|
|
def setCatalog(self, catalog):
|
|
pass
|
|
|
|
def getCatalog(self):
|
|
return ""
|
|
|
|
def setTransactionIsolation(self, level):
|
|
pass
|
|
|
|
def getTransactionIsolation(self):
|
|
return Connection.TRANSACTION_READ_COMMITTED
|
|
|
|
def getWarnings(self):
|
|
return None
|
|
|
|
def clearWarnings(self):
|
|
pass
|
|
|
|
def setSavepoint(self, name=None):
|
|
return Savepoint(name)
|
|
|
|
def releaseSavepoint(self, savepoint):
|
|
pass
|
|
|
|
def createStatement(self, result_set_type, result_set_concurrency):
|
|
return Statement()
|
|
|
|
def prepareStatement(self, sql, *args):
|
|
return PreparedStatement(sql)
|
|
|
|
def prepareCall(self, sql, result_set_type, result_set_concurrency):
|
|
return CallableStatement(sql)
|
|
|
|
def setTypeMap(self, type_map):
|
|
pass
|
|
|
|
def getTypeMap(self):
|
|
return {}
|
|
|
|
def setHoldability(self, holdability):
|
|
pass
|
|
|
|
def getHoldability(self):
|
|
return HOLD_CURSORS_OVER_COMMIT
|
|
|
|
def setSchema(self, schema):
|
|
pass
|
|
|
|
def getSchema(self):
|
|
return ""
|
|
|
|
def abort(self, executor):
|
|
pass
|
|
|
|
def getNetworkTimeout(self):
|
|
return 0
|
|
|
|
def setNetworkTimeout(self, executor, milliseconds):
|
|
pass
|
|
|
|
def createArrayOf(self, type_name, elements):
|
|
return Array(type_name, elements)
|
|
|
|
def createBlob(self):
|
|
return Blob()
|
|
|
|
def createClob(self):
|
|
return Clob()
|
|
|
|
def createNClob(self):
|
|
return NClob()
|
|
|
|
def createSQLXML(self):
|
|
return SQLXML()
|
|
|
|
def createStruct(self, type_name, attributes):
|
|
return Struct(type_name, attributes)
|
|
|
|
def isValid(self, timeout):
|
|
return not self.isClosed()
|
|
|
|
# Transaction isolation constants
|
|
TRANSACTION_NONE = 0
|
|
TRANSACTION_READ_COMMITTED = 2
|
|
TRANSACTION_READ_UNCOMMITTED = 1
|
|
TRANSACTION_REPEATABLE_READ = 4
|
|
TRANSACTION_SERIALIZABLE = 8
|
|
|
|
|
|
# ============================================================
|
|
# Statement
|
|
# ============================================================
|
|
|
|
class Statement(Stub):
|
|
"""java.sql.Statement"""
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._max_rows = 0
|
|
self._query_timeout = 0
|
|
self._fetch_direction = FETCH_FORWARD
|
|
self._fetch_size = 0
|
|
self._max_field_size = 0
|
|
self._poolable = True
|
|
self._close_on_completion = False
|
|
self._result_set_type = TYPE_FORWARD_ONLY
|
|
self._result_set_concurrency = 0
|
|
self._result_set_holdability = HOLD_CURSORS_OVER_COMMIT
|
|
self._generated_keys = None
|
|
self._update_count = -1
|
|
self._result_set = None
|
|
self._more_results = False
|
|
self._closed = False
|
|
self._warnings = None
|
|
self._poolable = True
|
|
|
|
def executeQuery(self, sql):
|
|
return ResultSet()
|
|
|
|
def executeUpdate(self, sql):
|
|
return 0
|
|
|
|
def close(self):
|
|
self._closed = True
|
|
|
|
def getMaxFieldSize(self):
|
|
return self._max_field_size
|
|
|
|
def setMaxFieldSize(self, max_size):
|
|
self._max_field_size = max_size
|
|
|
|
def getMaxRows(self):
|
|
return self._max_rows
|
|
|
|
def setMaxRows(self, max_rows):
|
|
self._max_rows = max_rows
|
|
|
|
def setEscapeProcessing(self, enable):
|
|
pass
|
|
|
|
def getQueryTimeout(self):
|
|
return self._query_timeout
|
|
|
|
def setQueryTimeout(self, seconds):
|
|
self._query_timeout = seconds
|
|
|
|
def cancel(self):
|
|
pass
|
|
|
|
def getWarnings(self):
|
|
return self._warnings
|
|
|
|
def clearWarnings(self):
|
|
self._warnings = None
|
|
|
|
def setCursorName(self, name):
|
|
pass
|
|
|
|
def execute(self, sql):
|
|
return False
|
|
|
|
def getResultSet(self):
|
|
return self._result_set
|
|
|
|
def getUpdateCount(self):
|
|
return self._update_count
|
|
|
|
def getMoreResults(self, current=None):
|
|
return False
|
|
|
|
def setFetchDirection(self, direction):
|
|
self._fetch_direction = direction
|
|
|
|
def getFetchDirection(self):
|
|
return self._fetch_direction
|
|
|
|
def setFetchSize(self, rows):
|
|
self._fetch_size = rows
|
|
|
|
def getFetchSize(self):
|
|
return self._fetch_size
|
|
|
|
def getResultSetConcurrency(self):
|
|
return self._result_set_concurrency
|
|
|
|
def getResultSetType(self):
|
|
return self._result_set_type
|
|
|
|
def addBatch(self, sql):
|
|
pass
|
|
|
|
def clearBatch(self):
|
|
pass
|
|
|
|
def executeBatch(self):
|
|
return []
|
|
|
|
def getConnection(self):
|
|
return Connection()
|
|
|
|
def getMoreResults(self, current):
|
|
return False
|
|
|
|
def getGeneratedKeys(self):
|
|
return self._generated_keys or ResultSet()
|
|
|
|
def getResultSetHoldability(self):
|
|
return self._result_set_holdability
|
|
|
|
def isClosed(self):
|
|
return self._closed
|
|
|
|
def setPoolable(self, poolable):
|
|
self._poolable = poolable
|
|
|
|
def isPoolable(self):
|
|
return self._poolable
|
|
|
|
def closeOnCompletion(self):
|
|
self._close_on_completion = True
|
|
|
|
def isCloseOnCompletion(self):
|
|
return self._close_on_completion
|
|
|
|
def executeLargeUpdate(self, sql):
|
|
return 0
|
|
|
|
def getLargeUpdateCount(self):
|
|
return self._update_count
|
|
|
|
def getLargeMaxRows(self):
|
|
return self._max_rows
|
|
|
|
def setLargeMaxRows(self, max_rows):
|
|
self._max_rows = max_rows
|
|
|
|
def executeLargeBatch(self):
|
|
return []
|
|
|
|
def unwrap(self, iface):
|
|
return self
|
|
|
|
def isWrapperFor(self, iface):
|
|
return isinstance(self, iface)
|
|
|
|
SUCCESS_NO_INFO = -2
|
|
EXECUTE_FAILED = -3
|
|
RETURN_GENERATED_KEYS = 1
|
|
NO_GENERATED_KEYS = 2
|
|
CLOSE_ALL_RESULTS = 3
|
|
KEEP_CURRENT_RESULT = 2
|
|
CLOSE_CURRENT_RESULT = 1
|
|
NO_GENERATED_KEYS = 2
|
|
RETURN_GENERATED_KEYS = 1
|
|
|
|
|
|
# ============================================================
|
|
# PreparedStatement
|
|
# ============================================================
|
|
|
|
class PreparedStatement(Statement):
|
|
"""java.sql.PreparedStatement"""
|
|
def __init__(self, sql=""):
|
|
super().__init__()
|
|
self._sql = sql
|
|
self._parameters = []
|
|
|
|
def setNull(self, parameter_index, sql_type, type_name=None):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = None
|
|
|
|
def setBoolean(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setByte(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setShort(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setInt(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setLong(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setFloat(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setDouble(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setBigDecimal(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setString(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setBytes(self, parameter_index, x):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = bytes(x) if x else None
|
|
|
|
def setDate(self, parameter_index, x, calendar=None):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setTime(self, parameter_index, x, calendar=None):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setTimestamp(self, parameter_index, x, calendar=None):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setAsciiStream(self, parameter_index, stream, length=None):
|
|
self._ensure_params(parameter_index)
|
|
data = stream.read() if hasattr(stream, 'read') else stream
|
|
if isinstance(data, bytes):
|
|
data = data.decode()
|
|
self._parameters[parameter_index - 1] = data
|
|
|
|
def setBinaryStream(self, parameter_index, stream, length=None):
|
|
self._ensure_params(parameter_index)
|
|
data = stream.read() if hasattr(stream, 'read') else stream
|
|
self._parameters[parameter_index - 1] = data
|
|
|
|
def setObject(self, parameter_index, x, target_sql_type=None, scale_or_length=None):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = x
|
|
|
|
def setCharacterStream(self, parameter_index, reader, length=None):
|
|
self._ensure_params(parameter_index)
|
|
data = reader.read() if hasattr(reader, 'read') else reader
|
|
self._parameters[parameter_index - 1] = data
|
|
|
|
def setBlob(self, parameter_index, blob):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = blob
|
|
|
|
def setClob(self, parameter_index, clob):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = clob
|
|
|
|
def setArray(self, parameter_index, array):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = array
|
|
|
|
def setRef(self, parameter_index, ref):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = ref
|
|
|
|
def setNString(self, parameter_index, value):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = value
|
|
|
|
def setNClob(self, parameter_index, nclob):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = nclob
|
|
|
|
def setNCharacterStream(self, parameter_index, reader, length=None):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = reader
|
|
|
|
def setRowId(self, parameter_index, row_id):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = row_id
|
|
|
|
def setSQLXML(self, parameter_index, xml):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = xml
|
|
|
|
def setURL(self, parameter_index, url):
|
|
self._ensure_params(parameter_index)
|
|
self._parameters[parameter_index - 1] = url
|
|
|
|
def clearParameters(self):
|
|
self._parameters = []
|
|
|
|
def executeQuery(self):
|
|
return ResultSet()
|
|
|
|
def executeUpdate(self):
|
|
return 0
|
|
|
|
def execute(self):
|
|
return False
|
|
|
|
def addBatch(self):
|
|
pass
|
|
|
|
def getParameterMetaData(self):
|
|
return ResultSetMetaData()
|
|
|
|
def getMetaData(self):
|
|
return ResultSetMetaData()
|
|
|
|
def _ensure_params(self, idx):
|
|
while len(self._parameters) < idx:
|
|
self._parameters.append(None)
|
|
|
|
|
|
# ============================================================
|
|
# CallableStatement
|
|
# ============================================================
|
|
|
|
class CallableStatement(PreparedStatement):
|
|
"""java.sql.CallableStatement"""
|
|
def __init__(self, sql=""):
|
|
super().__init__(sql)
|
|
self._output_params = {}
|
|
|
|
def registerOutParameter(self, parameter_index, sql_type, scale_or_type_name=None):
|
|
pass
|
|
|
|
def wasNull(self):
|
|
return False
|
|
|
|
def getString(self, parameter_index):
|
|
return self._output_params.get(parameter_index)
|
|
|
|
def getBoolean(self, parameter_index):
|
|
return bool(self._output_params.get(parameter_index))
|
|
|
|
def getByte(self, parameter_index):
|
|
return self._output_params.get(parameter_index, 0)
|
|
|
|
def getShort(self, parameter_index):
|
|
return self._output_params.get(parameter_index, 0)
|
|
|
|
def getInt(self, parameter_index):
|
|
return self._output_params.get(parameter_index, 0)
|
|
|
|
def getLong(self, parameter_index):
|
|
return self._output_params.get(parameter_index, 0)
|
|
|
|
def getFloat(self, parameter_index):
|
|
return float(self._output_params.get(parameter_index, 0.0))
|
|
|
|
def getDouble(self, parameter_index):
|
|
return float(self._output_params.get(parameter_index, 0.0))
|
|
|
|
def getBigDecimal(self, parameter_index):
|
|
return self._output_params.get(parameter_index)
|
|
|
|
def getBytes(self, parameter_index):
|
|
return b""
|
|
|
|
def getDate(self, parameter_index):
|
|
return Date()
|
|
|
|
def getTime(self, parameter_index):
|
|
return Time()
|
|
|
|
def getTimestamp(self, parameter_index):
|
|
return Timestamp()
|
|
|
|
def getObject(self, parameter_index, type_map=None):
|
|
return self._output_params.get(parameter_index)
|
|
|
|
def getRef(self, parameter_index):
|
|
return Ref()
|
|
|
|
def getBlob(self, parameter_index):
|
|
return Blob()
|
|
|
|
def getClob(self, parameter_index):
|
|
return Clob()
|
|
|
|
def getArray(self, parameter_index):
|
|
return Array()
|
|
|
|
def getURL(self, parameter_index):
|
|
return None
|
|
|
|
def getNClob(self, parameter_index):
|
|
return NClob()
|
|
|
|
def getNString(self, parameter_index):
|
|
return self.getString(parameter_index)
|
|
|
|
def getNCharacterStream(self, parameter_index):
|
|
import io
|
|
return io.StringIO("")
|
|
|
|
def getRowId(self, parameter_index):
|
|
return RowId()
|
|
|
|
def getSQLXML(self, parameter_index):
|
|
return SQLXML()
|
|
|
|
|
|
# ============================================================
|
|
# ResultSet
|
|
# ============================================================
|
|
|
|
class ResultSet(Stub):
|
|
"""java.sql.ResultSet"""
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._rows = []
|
|
self._row_index = -1
|
|
self._closed = False
|
|
self._warnings = None
|
|
self._fetch_direction = FETCH_FORWARD
|
|
self._fetch_size = 0
|
|
self._type = TYPE_FORWARD_ONLY
|
|
self._concurrency = 0
|
|
self._holdability = HOLD_CURSORS_OVER_COMMIT
|
|
self._meta_data = ResultSetMetaData()
|
|
|
|
def next(self):
|
|
if self._row_index + 1 < len(self._rows):
|
|
self._row_index += 1
|
|
return True
|
|
return False
|
|
|
|
def close(self):
|
|
self._closed = True
|
|
|
|
def wasNull(self):
|
|
return False
|
|
|
|
def getString(self, column_index_or_label):
|
|
return str(self._get_value(column_index_or_label) or "")
|
|
|
|
def getBoolean(self, column_index_or_label):
|
|
return bool(self._get_value(column_index_or_label))
|
|
|
|
def getByte(self, column_index_or_label):
|
|
return int(self._get_value(column_index_or_label) or 0)
|
|
|
|
def getShort(self, column_index_or_label):
|
|
return int(self._get_value(column_index_or_label) or 0)
|
|
|
|
def getInt(self, column_index_or_label):
|
|
return int(self._get_value(column_index_or_label) or 0)
|
|
|
|
def getLong(self, column_index_or_label):
|
|
return int(self._get_value(column_index_or_label) or 0)
|
|
|
|
def getFloat(self, column_index_or_label):
|
|
return float(self._get_value(column_index_or_label) or 0.0)
|
|
|
|
def getDouble(self, column_index_or_label):
|
|
return float(self._get_value(column_index_or_label) or 0.0)
|
|
|
|
def getBytes(self, column_index_or_label):
|
|
val = self._get_value(column_index_or_label)
|
|
if isinstance(val, bytes):
|
|
return val
|
|
if isinstance(val, str):
|
|
return val.encode()
|
|
return b""
|
|
|
|
def getDate(self, column_index_or_label):
|
|
val = self._get_value(column_index_or_label)
|
|
if isinstance(val, Date):
|
|
return val
|
|
return Date()
|
|
|
|
def getTime(self, column_index_or_label):
|
|
val = self._get_value(column_index_or_label)
|
|
if isinstance(val, Time):
|
|
return val
|
|
return Time()
|
|
|
|
def getTimestamp(self, column_index_or_label):
|
|
val = self._get_value(column_index_or_label)
|
|
if isinstance(val, Timestamp):
|
|
return val
|
|
return Timestamp()
|
|
|
|
def getObject(self, column_index_or_label, type_map=None):
|
|
return self._get_value(column_index_or_label)
|
|
|
|
def findColumn(self, column_label):
|
|
return 1
|
|
|
|
def getMetaData(self):
|
|
return self._meta_data
|
|
|
|
def getWarnings(self):
|
|
return self._warnings
|
|
|
|
def clearWarnings(self):
|
|
self._warnings = None
|
|
|
|
def setFetchDirection(self, direction):
|
|
self._fetch_direction = direction
|
|
|
|
def getFetchDirection(self):
|
|
return self._fetch_direction
|
|
|
|
def setFetchSize(self, rows):
|
|
self._fetch_size = rows
|
|
|
|
def getFetchSize(self):
|
|
return self._fetch_size
|
|
|
|
def getType(self):
|
|
return self._type
|
|
|
|
def getConcurrency(self):
|
|
return self._concurrency
|
|
|
|
def rowUpdated(self):
|
|
return False
|
|
|
|
def rowInserted(self):
|
|
return False
|
|
|
|
def rowDeleted(self):
|
|
return False
|
|
|
|
def updateNull(self, column_index_or_label):
|
|
pass
|
|
|
|
def updateBoolean(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateByte(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateShort(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateInt(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateLong(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateFloat(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateDouble(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateString(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateBytes(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateDate(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateTime(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateTimestamp(self, column_index_or_label, x):
|
|
pass
|
|
|
|
def updateRow(self):
|
|
pass
|
|
|
|
def insertRow(self):
|
|
pass
|
|
|
|
def deleteRow(self):
|
|
pass
|
|
|
|
def refreshRow(self):
|
|
pass
|
|
|
|
def cancelRowUpdates(self):
|
|
pass
|
|
|
|
def moveToInsertRow(self):
|
|
pass
|
|
|
|
def moveToCurrentRow(self):
|
|
pass
|
|
|
|
def isClosed(self):
|
|
return self._closed
|
|
|
|
def getHoldability(self):
|
|
return self._holdability
|
|
|
|
def getStatement(self):
|
|
return None
|
|
|
|
def getArray(self, column_index_or_label):
|
|
return Array()
|
|
|
|
def getBlob(self, column_index_or_label):
|
|
return Blob()
|
|
|
|
def getClob(self, column_index_or_label):
|
|
return Clob()
|
|
|
|
def getRef(self, column_index_or_label):
|
|
return Ref()
|
|
|
|
def getURL(self, column_index_or_label):
|
|
return None
|
|
|
|
def getNClob(self, column_index_or_label):
|
|
return NClob()
|
|
|
|
def getNString(self, column_index_or_label):
|
|
return self.getString(column_index_or_label)
|
|
|
|
def getNCharacterStream(self, column_index_or_label):
|
|
import io
|
|
return io.StringIO("")
|
|
|
|
def getRowId(self, column_index_or_label):
|
|
return RowId()
|
|
|
|
def getSQLXML(self, column_index_or_label):
|
|
return SQLXML()
|
|
|
|
def getBinaryStream(self, column_index_or_label):
|
|
import io
|
|
return io.BytesIO(b"")
|
|
|
|
def getCharacterStream(self, column_index_or_label):
|
|
import io
|
|
return io.StringIO("")
|
|
|
|
def getAsciiStream(self, column_index_or_label):
|
|
import io
|
|
return io.BytesIO(b"")
|
|
|
|
def updateObject(self, column_index_or_label, x, scale_or_target=None):
|
|
pass
|
|
|
|
def beforeFirst(self):
|
|
self._row_index = -1
|
|
|
|
def afterLast(self):
|
|
self._row_index = len(self._rows)
|
|
|
|
def first(self):
|
|
if self._rows:
|
|
self._row_index = 0
|
|
return True
|
|
return False
|
|
|
|
def last(self):
|
|
if self._rows:
|
|
self._row_index = len(self._rows) - 1
|
|
return True
|
|
return False
|
|
|
|
def absolute(self, row):
|
|
if row == 0:
|
|
self._row_index = -1
|
|
return False
|
|
idx = row - 1 if row > 0 else len(self._rows) + row
|
|
if 0 <= idx < len(self._rows):
|
|
self._row_index = idx
|
|
return True
|
|
return False
|
|
|
|
def relative(self, rows):
|
|
new_idx = self._row_index + rows
|
|
if 0 <= new_idx < len(self._rows):
|
|
self._row_index = new_idx
|
|
return True
|
|
return False
|
|
|
|
def previous(self):
|
|
if self._row_index > 0:
|
|
self._row_index -= 1
|
|
return True
|
|
return False
|
|
|
|
def isBeforeFirst(self):
|
|
return self._row_index < 0 and len(self._rows) > 0
|
|
|
|
def isAfterLast(self):
|
|
return self._row_index >= len(self._rows) and len(self._rows) > 0
|
|
|
|
def isFirst(self):
|
|
return self._row_index == 0
|
|
|
|
def isLast(self):
|
|
return self._row_index == len(self._rows) - 1
|
|
|
|
def getRow(self):
|
|
return self._row_index + 1 if 0 <= self._row_index < len(self._rows) else 0
|
|
|
|
def _get_value(self, col):
|
|
if 0 <= self._row_index < len(self._rows):
|
|
row = self._rows[self._row_index]
|
|
if isinstance(col, int) and col - 1 < len(row):
|
|
return row[col - 1]
|
|
return None
|
|
|
|
# Constants
|
|
FETCH_FORWARD = 1000
|
|
FETCH_REVERSE = 1001
|
|
FETCH_UNKNOWN = 1002
|
|
TYPE_FORWARD_ONLY = 1003
|
|
TYPE_SCROLL_INSENSITIVE = 1004
|
|
TYPE_SCROLL_SENSITIVE = 1005
|
|
CONCUR_READ_ONLY = 1007
|
|
CONCUR_UPDATABLE = 1008
|
|
HOLD_CURSORS_OVER_COMMIT = 1
|
|
CLOSE_CURSORS_AT_COMMIT = 2
|
|
|
|
|
|
# ============================================================
|
|
# ResultSetMetaData
|
|
# ============================================================
|
|
|
|
class ResultSetMetaData(Stub):
|
|
"""java.sql.ResultSetMetaData"""
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._column_count = 0
|
|
self._column_names = []
|
|
self._column_types = []
|
|
|
|
def getColumnCount(self):
|
|
return self._column_count
|
|
|
|
def isAutoIncrement(self, column):
|
|
return False
|
|
|
|
def isCaseSensitive(self, column):
|
|
return True
|
|
|
|
def isSearchable(self, column):
|
|
return True
|
|
|
|
def isCurrency(self, column):
|
|
return False
|
|
|
|
def isNullable(self, column):
|
|
return ResultSetMetaData.columnNullable
|
|
|
|
def isSigned(self, column):
|
|
return True
|
|
|
|
def getColumnDisplaySize(self, column):
|
|
return 255
|
|
|
|
def getColumnLabel(self, column):
|
|
return self.getColumnName(column)
|
|
|
|
def getColumnName(self, column):
|
|
if column - 1 < len(self._column_names):
|
|
return self._column_names[column - 1]
|
|
return f"COLUMN_{column}"
|
|
|
|
def getSchemaName(self, column):
|
|
return ""
|
|
|
|
def getPrecision(self, column):
|
|
return 0
|
|
|
|
def getScale(self, column):
|
|
return 0
|
|
|
|
def getTableName(self, column):
|
|
return ""
|
|
|
|
def getCatalogName(self, column):
|
|
return ""
|
|
|
|
def getColumnType(self, column):
|
|
if column - 1 < len(self._column_types):
|
|
return self._column_types[column - 1]
|
|
return Types.VARCHAR
|
|
|
|
def getColumnTypeName(self, column):
|
|
return "VARCHAR"
|
|
|
|
def isReadOnly(self, column):
|
|
return False
|
|
|
|
def isWritable(self, column):
|
|
return True
|
|
|
|
def isDefinitelyWritable(self, column):
|
|
return True
|
|
|
|
def getColumnClassName(self, column):
|
|
return "java.lang.String"
|
|
|
|
columnNoNulls = 0
|
|
columnNullable = 1
|
|
columnNullableUnknown = 2
|
|
|
|
|
|
# ============================================================
|
|
# DatabaseMetaData
|
|
# ============================================================
|
|
|
|
class DatabaseMetaData(Stub):
|
|
"""java.sql.DatabaseMetaData"""
|
|
def getDatabaseProductName(self):
|
|
return "Android-pyApi SQL"
|
|
|
|
def getDatabaseProductVersion(self):
|
|
return "1.0"
|
|
|
|
def getDriverName(self):
|
|
return "Android-pyApi JDBC Driver"
|
|
|
|
def getDriverVersion(self):
|
|
return "1.0"
|
|
|
|
def getDriverMajorVersion(self):
|
|
return 1
|
|
|
|
def getDriverMinorVersion(self):
|
|
return 0
|
|
|
|
def getURL(self):
|
|
return ""
|
|
|
|
def getUserName(self):
|
|
return ""
|
|
|
|
def isReadOnly(self):
|
|
return False
|
|
|
|
def nullsAreSortedHigh(self):
|
|
return True
|
|
|
|
def nullsAreSortedLow(self):
|
|
return False
|
|
|
|
def nullsAreSortedAtStart(self):
|
|
return False
|
|
|
|
def nullsAreSortedAtEnd(self):
|
|
return False
|
|
|
|
def getDatabaseMajorVersion(self):
|
|
return 1
|
|
|
|
def getDatabaseMinorVersion(self):
|
|
return 0
|
|
|
|
def getJDBCMajorVersion(self):
|
|
return 4
|
|
|
|
def getJDBCMinorVersion(self):
|
|
return 2
|
|
|
|
def getDefaultTransactionIsolation(self):
|
|
return Connection.TRANSACTION_READ_COMMITTED
|
|
|
|
def supportsTransactions(self):
|
|
return True
|
|
|
|
def supportsTransactionIsolationLevel(self, level):
|
|
return True
|
|
|
|
def supportsResultSetType(self, type_):
|
|
return True
|
|
|
|
def supportsResultSetConcurrency(self, type_, concurrency):
|
|
return True
|
|
|
|
def getTables(self, catalog, schema_pattern, table_name_pattern, types):
|
|
return ResultSet()
|
|
|
|
def getColumns(self, catalog, schema_pattern, table_name_pattern, column_name_pattern):
|
|
return ResultSet()
|
|
|
|
def getPrimaryKeys(self, catalog, schema, table):
|
|
return ResultSet()
|
|
|
|
def getImportedKeys(self, catalog, schema, table):
|
|
return ResultSet()
|
|
|
|
def getExportedKeys(self, catalog, schema, table):
|
|
return ResultSet()
|
|
|
|
def getSchemas(self):
|
|
return ResultSet()
|
|
|
|
def getCatalogs(self):
|
|
return ResultSet()
|
|
|
|
def getTableTypes(self):
|
|
return ResultSet()
|
|
|
|
def getTypeInfo(self):
|
|
return ResultSet()
|
|
|
|
def getIndexInfo(self, catalog, schema, table, unique, approximate):
|
|
return ResultSet()
|
|
|
|
def getProcedures(self, catalog, schema_pattern, procedure_name_pattern):
|
|
return ResultSet()
|
|
|
|
def getProcedureColumns(self, catalog, schema_pattern, procedure_name_pattern, column_name_pattern):
|
|
return ResultSet()
|
|
|
|
def supportsSavepoints(self):
|
|
return True
|
|
|
|
def supportsBatchUpdates(self):
|
|
return True
|
|
|
|
def supportsStoredProcedures(self):
|
|
return True
|
|
|
|
def allProceduresAreCallable(self):
|
|
return True
|
|
|
|
def allTablesAreSelectable(self):
|
|
return True
|
|
|
|
def dataDefinitionCausesTransactionCommit(self):
|
|
return False
|
|
|
|
def dataDefinitionIgnoredInTransactions(self):
|
|
return False
|
|
|
|
def doesMaxRowSizeIncludeBlobs(self):
|
|
return False
|
|
|
|
def getMaxBinaryLiteralLength(self):
|
|
return 0
|
|
|
|
def getMaxCharLiteralLength(self):
|
|
return 0
|
|
|
|
def getMaxColumnNameLength(self):
|
|
return 128
|
|
|
|
def getMaxColumnsInGroupBy(self):
|
|
return 0
|
|
|
|
def getMaxColumnsInIndex(self):
|
|
return 0
|
|
|
|
def getMaxColumnsInOrderBy(self):
|
|
return 0
|
|
|
|
def getMaxColumnsInSelect(self):
|
|
return 0
|
|
|
|
def getMaxColumnsInTable(self):
|
|
return 0
|
|
|
|
def getMaxConnections(self):
|
|
return 0
|
|
|
|
def getMaxCursorNameLength(self):
|
|
return 0
|
|
|
|
def getMaxIndexLength(self):
|
|
return 0
|
|
|
|
def getMaxSchemaNameLength(self):
|
|
return 0
|
|
|
|
def getMaxProcedureNameLength(self):
|
|
return 0
|
|
|
|
def getMaxRowSize(self):
|
|
return 0
|
|
|
|
def getMaxStatementLength(self):
|
|
return 0
|
|
|
|
def getMaxStatements(self):
|
|
return 0
|
|
|
|
def getMaxTableNameLength(self):
|
|
return 0
|
|
|
|
def getMaxTablesInSelect(self):
|
|
return 0
|
|
|
|
def getMaxUserNameLength(self):
|
|
return 0
|
|
|
|
def getNumericFunctions(self):
|
|
return ""
|
|
|
|
def getSQLKeywords(self):
|
|
return ""
|
|
|
|
def getStringFunctions(self):
|
|
return ""
|
|
|
|
def getSystemFunctions(self):
|
|
return ""
|
|
|
|
def getTimeDateFunctions(self):
|
|
return ""
|
|
|
|
def getSearchStringEscape(self):
|
|
return "\\"
|
|
|
|
def getExtraNameCharacters(self):
|
|
return ""
|
|
|
|
def getSchemaTerm(self):
|
|
return "schema"
|
|
|
|
def getCatalogTerm(self):
|
|
return "catalog"
|
|
|
|
def getProcedureTerm(self):
|
|
return "procedure"
|
|
|
|
def getCatalogSeparator(self):
|
|
return "."
|
|
|
|
def isCatalogAtStart(self):
|
|
return True
|
|
|
|
def autoCommitFailureClosesAllResultSets(self):
|
|
return False
|
|
|
|
def generatedKeyAlwaysReturned(self):
|
|
return True
|
|
|
|
def getSQLStateType(self):
|
|
return DatabaseMetaData.sqlStateSQL
|
|
|
|
def locatorsUpdateCopy(self):
|
|
return False
|
|
|
|
def supportsDifferentTableCorrelationNames(self):
|
|
return True
|
|
|
|
def supportsANSI92EntryLevelSQL(self):
|
|
return True
|
|
|
|
def supportsANSI92IntermediateSQL(self):
|
|
return True
|
|
|
|
def supportsANSI92FullSQL(self):
|
|
return False
|
|
|
|
def supportsIntegrityEnhancementFacility(self):
|
|
return False
|
|
|
|
def supportsOuterJoins(self):
|
|
return True
|
|
|
|
def supportsFullOuterJoins(self):
|
|
return True
|
|
|
|
def supportsLimitedOuterJoins(self):
|
|
return True
|
|
|
|
def supportsSchemasInDataManipulation(self):
|
|
return True
|
|
|
|
def supportsSchemasInProcedureCalls(self):
|
|
return True
|
|
|
|
def supportsSchemasInTableDefinitions(self):
|
|
return True
|
|
|
|
def supportsSchemasInIndexDefinitions(self):
|
|
return True
|
|
|
|
def supportsSchemasInPrivilegeDefinitions(self):
|
|
return True
|
|
|
|
def supportsCatalogsInDataManipulation(self):
|
|
return True
|
|
|
|
def supportsCatalogsInProcedureCalls(self):
|
|
return True
|
|
|
|
def supportsCatalogsInTableDefinitions(self):
|
|
return True
|
|
|
|
def supportsCatalogsInIndexDefinitions(self):
|
|
return True
|
|
|
|
def supportsCatalogsInPrivilegeDefinitions(self):
|
|
return True
|
|
|
|
def supportsPositionedDelete(self):
|
|
return False
|
|
|
|
def supportsPositionedUpdate(self):
|
|
return False
|
|
|
|
def supportsSelectForUpdate(self):
|
|
return True
|
|
|
|
def supportsSubqueriesInComparisons(self):
|
|
return True
|
|
|
|
def supportsSubqueriesInExists(self):
|
|
return True
|
|
|
|
def supportsSubqueriesInIns(self):
|
|
return True
|
|
|
|
def supportsSubqueriesInQuantifieds(self):
|
|
return True
|
|
|
|
def supportsCorrelatedSubqueries(self):
|
|
return True
|
|
|
|
def supportsUnion(self):
|
|
return True
|
|
|
|
def supportsUnionAll(self):
|
|
return True
|
|
|
|
def supportsOpenCursorsAcrossCommit(self):
|
|
return True
|
|
|
|
def supportsOpenCursorsAcrossRollback(self):
|
|
return True
|
|
|
|
def supportsOpenStatementsAcrossCommit(self):
|
|
return True
|
|
|
|
def supportsOpenStatementsAcrossRollback(self):
|
|
return True
|
|
|
|
def supportsMixedCaseIdentifiers(self):
|
|
return True
|
|
|
|
def storesMixedCaseIdentifiers(self):
|
|
return True
|
|
|
|
def supportsMixedCaseQuotedIdentifiers(self):
|
|
return True
|
|
|
|
def storesMixedCaseQuotedIdentifiers(self):
|
|
return True
|
|
|
|
def supportsAlterTableWithAddColumn(self):
|
|
return True
|
|
|
|
def supportsAlterTableWithDropColumn(self):
|
|
return True
|
|
|
|
def supportsColumnAliasing(self):
|
|
return True
|
|
|
|
def supportsConvert(self):
|
|
return True
|
|
|
|
def supportsTableCorrelationNames(self):
|
|
return True
|
|
|
|
def getConnection(self):
|
|
return Connection()
|
|
|
|
# Constants
|
|
attributeNoNulls = 0
|
|
attributeNullable = 1
|
|
attributeNullableUnknown = 2
|
|
bestRowTemporary = 0
|
|
bestRowTransaction = 1
|
|
bestRowSession = 2
|
|
bestRowUnknown = 0
|
|
bestRowNotPseudo = 1
|
|
bestRowPseudo = 2
|
|
columnNoNulls = 0
|
|
columnNullable = 1
|
|
columnNullableUnknown = 2
|
|
functionColumnIn = 1
|
|
functionColumnInOut = 2
|
|
functionColumnOut = 3
|
|
functionColumnReturn = 4
|
|
functionColumnResult = 5
|
|
functionNoNulls = 0
|
|
functionNullable = 1
|
|
functionNullableUnknown = 2
|
|
functionResultUnknown = 0
|
|
functionNoTable = 1
|
|
functionReturnsTable = 2
|
|
importedKeyCascade = 0
|
|
importedKeyRestrict = 1
|
|
importedKeySetNull = 2
|
|
importedKeyNoAction = 3
|
|
importedKeySetDefault = 4
|
|
importedKeyInitiallyDeferred = 5
|
|
importedKeyInitiallyImmediate = 6
|
|
importedKeyNotDeferrable = 7
|
|
procedureColumnIn = 1
|
|
procedureColumnInOut = 2
|
|
procedureColumnOut = 4
|
|
procedureColumnReturn = 5
|
|
procedureColumnResult = 3
|
|
procedureNoNulls = 0
|
|
procedureNullable = 1
|
|
procedureNullableUnknown = 2
|
|
procedureResultUnknown = 0
|
|
sqlStateSQL = 2
|
|
sqlStateXOpen = 1
|
|
tableIndexStatistic = 0
|
|
tableIndexClustered = 1
|
|
tableIndexHashed = 2
|
|
tableIndexOther = 3
|
|
versionColumnUnknown = 0
|
|
versionColumnNotPseudo = 1
|
|
versionColumnPseudo = 2
|
|
|
|
|
|
# ============================================================
|
|
# IllegalArgumentException
|
|
# ============================================================
|
|
|
|
class IllegalArgumentException(RuntimeException):
|
|
"""java.lang.IllegalArgumentException"""
|
|
pass |