Skip to content

Commit

Permalink
feat(errors): map SQLite errors in DBAPI2 exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniele Briggi committed Aug 22, 2024
1 parent d453f1f commit f0d6486
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 99 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ main.dSYM/
.DS_Store

.idea
SqliteCloud.egg-info
sqlitecloud.egg-info

playground.ipynb

Expand Down
2 changes: 1 addition & 1 deletion src/sqlitecloud/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
SQLiteCloudConfig,
SQLiteCloudConnect,
SQLiteCloudDataTypes,
SQLiteCloudException,
)
from sqlitecloud.driver import Driver
from sqlitecloud.exceptions import SQLiteCloudException
from sqlitecloud.resultset import SQLiteCloudResultSet


Expand Down
33 changes: 2 additions & 31 deletions src/sqlitecloud/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Any, Callable, Dict, Optional, Union
from urllib import parse

from sqlitecloud.exceptions import SQLiteCloudException

from .resultset import SQLiteCloudResultSet

# SQLite supported data types
Expand Down Expand Up @@ -248,34 +250,3 @@ def __init__(self) -> None:
self.value: Optional[SQLiteCloudDataTypes] = None
self.len: int = 0
self.cellsize: int = 0


class SQLiteCloudWarning(Exception):
def __init__(self, message: str, code: int = -1, xerrcode: int = 0) -> None:
super().__init__(message)
self.errmsg = str(message)
self.errcode = code
self.xerrcode = xerrcode


class SQLiteCloudError(Exception):
def __init__(self, message: str, code: int = -1, xerrcode: int = 0) -> None:
super().__init__(message)
self.errmsg = str(message)
self.errcode = code
self.xerrcode = xerrcode


# class SQLiteCloudInterfaceError(SQLiteCloudError):
# def __init__(self, message: str, code: int = -1, xerrcode: int = 0) -> None:
# super().__init__(message, code, xerrcode)


# class SQLiteCloudDatabaseError(SQLiteCloudError):
# def __init__(self, message: str, code: int = -1, xerrcode: int = 0) -> None:
# super().__init__(message, code, xerrcode)


class SQLiteCloudException(SQLiteCloudError):
def __init__(self, message: str, code: int = -1, xerrcode: int = 0) -> None:
super().__init__(message, code, xerrcode)
85 changes: 39 additions & 46 deletions src/sqlitecloud/dbapi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,21 @@
SQLiteCloudAccount,
SQLiteCloudConfig,
SQLiteCloudConnect,
SQLiteCloudError,
SQLiteCloudException,
SQLiteCloudWarning,
SQLiteDataTypes,
)
from sqlitecloud.driver import Driver
from sqlitecloud.exceptions import (
SQLiteCloudDatabaseError,
SQLiteCloudDataError,
SQLiteCloudError,
SQLiteCloudIntegrityError,
SQLiteCloudInterfaceError,
SQLiteCloudInternalError,
SQLiteCloudNotSupportedError,
SQLiteCloudOperationalError,
SQLiteCloudProgrammingError,
SQLiteCloudWarning,
)
from sqlitecloud.resultset import (
SQLITECLOUD_RESULT_TYPE,
SQLITECLOUD_VALUE_TYPE,
Expand All @@ -54,14 +63,14 @@

Warning = SQLiteCloudWarning
Error = SQLiteCloudError
InterfaceError = SQLiteCloudException
DatabaseError = SQLiteCloudException
DataError = SQLiteCloudException
OperationalError = SQLiteCloudException
IntegrityError = SQLiteCloudException
InternalError = SQLiteCloudException
ProgrammingError = SQLiteCloudException
NotSupportedError = SQLiteCloudException
InterfaceError = SQLiteCloudInterfaceError
DatabaseError = SQLiteCloudDatabaseError
DataError = SQLiteCloudDataError
OperationalError = SQLiteCloudOperationalError
IntegrityError = SQLiteCloudIntegrityError
InternalError = SQLiteCloudInternalError
ProgrammingError = SQLiteCloudProgrammingError
NotSupportedError = SQLiteCloudNotSupportedError

# Map for types for SQLite
STRING = "TEXT"
Expand Down Expand Up @@ -254,9 +263,8 @@ def autocommit(self) -> bool:

@autocommit.setter
def autocommit(self, value: bool) -> None:
# TODO: raise NotSupportedError
if not value:
raise SQLiteCloudException("Disable Autocommit is not supported.")
raise SQLiteCloudNotSupportedError("Disable Autocommit is not supported.")

def execute(
self,
Expand Down Expand Up @@ -300,48 +308,37 @@ def executemany(
return cursor.executemany(sql, seq_of_parameters)

def executescript(self, sql_script: str):
# TODO: raise NotSupportedError
raise SQLiteCloudException("executescript() is not supported.")
raise SQLiteCloudNotSupportedError("executescript() is not supported.")

def create_function(self, name, num_params, func):
# TODO: raise NotSupportedError
raise SQLiteCloudException("create_function() is not supported.")
raise SQLiteCloudNotSupportedError("create_function() is not supported.")

def create_aggregate(self, name, num_params, aggregate_class):
# TODO: raise NotSupportedError
raise SQLiteCloudException("create_aggregate() is not supported.")
raise SQLiteCloudNotSupportedError("create_aggregate() is not supported.")

def create_collation(self, name, func):
# TODO: raise NotSupportedError
raise SQLiteCloudException("create_collation() is not supported.")
raise SQLiteCloudNotSupportedError("create_collation() is not supported.")

def interrupt(self):
# TODO: raise NotSupportedError
raise SQLiteCloudException("interrupt() is not supported.")
raise SQLiteCloudNotSupportedError("interrupt() is not supported.")

def set_authorizer(self, authorizer):
# TODO: raise NotSupportedError
raise SQLiteCloudException("set_authorizer() is not supported.")
raise SQLiteCloudNotSupportedError("set_authorizer() is not supported.")

def set_progress_handler(self, handler, n):
# TODO: raise NotSupportedError
raise SQLiteCloudException("set_progress_handler() is not supported.")
raise SQLiteCloudNotSupportedError("set_progress_handler() is not supported.")

def set_trace_callback(self, trace_callback):
# TODO: raise NotSupportedError
raise SQLiteCloudException("set_trace_callback() is not supported.")
raise SQLiteCloudNotSupportedError("set_trace_callback() is not supported.")

def enable_load_extension(self, enable):
# TODO: raise NotSupportedError
raise SQLiteCloudException("enable_load_extension() is not supported.")
raise SQLiteCloudNotSupportedError("enable_load_extension() is not supported.")

def load_extension(path):
# TODO: raise NotSupportedError
raise SQLiteCloudException("load_extension() is not supported.")
raise SQLiteCloudNotSupportedError("load_extension() is not supported.")

def iterdump(self):
# TODO: raise NotSupportedError
raise SQLiteCloudException("iterdump() is not supported.")
raise SQLiteCloudNotSupportedError("iterdump() is not supported.")

def close(self):
"""
Expand All @@ -360,7 +357,7 @@ def commit(self):
"""
try:
self._driver.execute("COMMIT;", self.sqlitecloud_connection)
except SQLiteCloudException as e:
except SQLiteCloudOperationalError as e:
if (
e.errcode == 1
and e.xerrcode == 1
Expand All @@ -380,7 +377,7 @@ def rollback(self):
"""
try:
self._driver.execute("ROLLBACK;", self.sqlitecloud_connection)
except SQLiteCloudException as e:
except SQLiteCloudOperationalError as e:
if (
e.errcode == 1
and e.xerrcode == 1
Expand Down Expand Up @@ -696,20 +693,16 @@ def fetchall(self) -> List[Any]:
return self.fetchmany(self.rowcount)

def setinputsizes(self, sizes) -> None:
# TODO: raise NotSupportedError
raise SQLiteCloudException("setinputsizes() is not supported.")
raise SQLiteCloudNotSupportedError("setinputsizes() is not supported.")

def setoutputsize(self, size, column=None) -> None:
# TODO: raise NotSupportedError
raise SQLiteCloudException("setoutputsize() is not supported.")
raise SQLiteCloudNotSupportedError("setoutputsize() is not supported.")

def scroll(value, mode="relative"):
# TODO: raise NotSupportedError
raise SQLiteCloudException("scroll() is not supported.")
raise SQLiteCloudNotSupportedError("scroll() is not supported.")

def messages(self):
# TODO: raise NotSupportedError
raise SQLiteCloudException("messages() is not supported.")
raise SQLiteCloudNotSupportedError("messages() is not supported.")

def _call_row_factory(self, row: Tuple) -> object:
if self.row_factory is None:
Expand Down Expand Up @@ -737,7 +730,7 @@ def _ensure_connection(self):
SQLiteCloudException: If the cursor is closed.
"""
if not self._connection:
raise SQLiteCloudException("The cursor is closed.")
raise SQLiteCloudOperationalError("The cursor is closed.")

def _adapt_parameters(self, parameters: Union[Dict, Tuple]) -> Union[Dict, Tuple]:
if isinstance(parameters, dict):
Expand Down
15 changes: 13 additions & 2 deletions src/sqlitecloud/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
SQLITECLOUD_ROWSET,
SQLiteCloudConfig,
SQLiteCloudConnect,
SQLiteCloudException,
SQLiteCloudNumber,
SQLiteCloudRowsetSignature,
SQLiteCloudValue,
SQLiteDataTypes,
)
from sqlitecloud.exceptions import (
SQLiteCloudException,
raise_sqlitecloud_error_with_extended_code,
)
from sqlitecloud.resultset import (
SQLITECLOUD_RESULT_TYPE,
SQLiteCloudOperationResult,
Expand Down Expand Up @@ -485,6 +488,12 @@ def _internal_socket_write(
command (bytes): The command to send.
main_socket (bool): If True, write to the main socket, otherwise write to the pubsub socket.
"""
# try:
# if "ATTACH DATABASE" in command.decode() or '"test_schema".table_info' in command.decode():
# pdb.set_trace()
# except:
# pass

# write buffer
if len(command) == 0:
return
Expand Down Expand Up @@ -712,7 +721,9 @@ def _internal_parse_buffer(
len_ -= cstart2
errmsg = clone[cstart2:]

raise SQLiteCloudException(errmsg.decode(), errcode, xerrcode)
raise raise_sqlitecloud_error_with_extended_code(
errmsg.decode(), errcode, xerrcode
)

elif cmd in [SQLITECLOUD_CMD.ROWSET.value, SQLITECLOUD_CMD.ROWSET_CHUNK.value]:
# CMD_ROWSET: *LEN 0:VERSION ROWS COLS DATA
Expand Down
Loading

0 comments on commit f0d6486

Please sign in to comment.