Skip to content

Commit 7c3fa02

Browse files
committed
requirements cleanup, fixes for date/time formats upgrade to db-api fixes
1 parent e2f16f5 commit 7c3fa02

File tree

4 files changed

+70
-1133
lines changed

4 files changed

+70
-1133
lines changed

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
intersystems_iris>=3.3.0b7
1+
intersystems_iris>=3.3.0b8
22
SQLAlchemy>=1.4

sqlalchemy_iris/base.py

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import datetime
2-
from telnetlib import BINARY
2+
from decimal import Decimal
33
import intersystems_iris.dbapi._DBAPI as dbapi
44
from . import information_schema as ischema
55
from sqlalchemy import exc
@@ -24,6 +24,7 @@
2424
from sqlalchemy.types import TIME
2525
from sqlalchemy.types import NUMERIC
2626
from sqlalchemy.types import FLOAT
27+
from sqlalchemy.types import BINARY
2728
from sqlalchemy.types import VARBINARY
2829
from sqlalchemy.types import TEXT
2930
from sqlalchemy.types import SMALLINT
@@ -440,6 +441,14 @@ def order_by_clause(self, select, **kw):
440441
else:
441442
return ""
442443

444+
def visit_column(self, column, within_columns_clause=False, **kwargs):
445+
text = super().visit_column(column, within_columns_clause=within_columns_clause, **kwargs)
446+
if within_columns_clause:
447+
return text
448+
if isinstance(column.type, sqltypes.Text):
449+
text = 'CONVERT(VARCHAR, %s)' % (text, )
450+
return text
451+
443452

444453
class IRISDDLCompiler(sql.compiler.DDLCompiler):
445454
"""IRIS syntactic idiosyncrasies"""
@@ -487,12 +496,12 @@ def get_column_specification(self, column, **kwargs):
487496
literal = self.sql_compiler.render_literal_value(
488497
comment, sqltypes.String()
489498
)
490-
colspec.append("%%DESCRIPTION " + literal)
499+
colspec.append("%DESCRIPTION " + literal)
491500

492501
return " ".join(colspec)
493502

494503
def post_create_table(self, table):
495-
return " WITH %%CLASSPARAMETER ALLOWIDENTITYINSERT = 1"
504+
return " WITH %CLASSPARAMETER ALLOWIDENTITYINSERT = 1"
496505

497506

498507
class IRISTypeCompiler(compiler.GenericTypeCompiler):
@@ -555,19 +564,47 @@ def process(value):
555564
return process
556565

557566

567+
class _IRISTimeStamp(sqltypes.DateTime):
568+
def bind_processor(self, dialect):
569+
def process(value: datetime.datetime):
570+
if value is not None:
571+
# value = int(value.timestamp() * 1000000)
572+
# value += (2 ** 60) if value > 0 else -(2 ** 61 * 3)
573+
return value.strftime('%Y-%m-%d %H:%M:%S.%f')
574+
return value
575+
576+
return process
577+
578+
def result_processor(self, dialect, coltype):
579+
def process(value):
580+
if isinstance(value, str):
581+
if '.' not in value:
582+
value += '.0'
583+
return datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S.%f')
584+
if isinstance(value, int):
585+
value -= (2 ** 60) if value > 0 else -(2 ** 61 * 3)
586+
value = value / 1000000
587+
value = datetime.datetime.utcfromtimestamp(value)
588+
return value
589+
590+
return process
591+
592+
558593
class _IRISDateTime(sqltypes.DateTime):
559594
def bind_processor(self, dialect):
560595
def process(value):
561596
if value is not None:
562-
return value.strftime('%Y-%m-%d %H:%M:%S')
597+
return value.strftime('%Y-%m-%d %H:%M:%S.%f')
563598
return value
564599

565600
return process
566601

567602
def result_processor(self, dialect, coltype):
568603
def process(value):
569-
if value is not None:
570-
return datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
604+
if isinstance(value, str):
605+
if '.' not in value:
606+
value += '.0'
607+
return datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S.%f')
571608
return value
572609

573610
return process
@@ -577,20 +614,25 @@ class _IRISTime(sqltypes.DateTime):
577614
def bind_processor(self, dialect):
578615
def process(value):
579616
if value is not None:
580-
return value.strftime('%H:%M:%S')
617+
return value.strftime('%H:%M:%S.%f')
581618
return value
582619

583620
return process
584621

585622
def result_processor(self, dialect, coltype):
586623
def process(value):
587-
if value is not None:
624+
if isinstance(value, str):
625+
if '.' not in value:
626+
value += '.0'
627+
return datetime.datetime.strptime(value, '%H:%M:%S.%f').time()
628+
if isinstance(value, int) or isinstance(value, Decimal):
588629
horolog = value
589-
hour = horolog // 3600
590-
horolog -= hour * 3600
591-
minute = horolog // 60
592-
second = horolog % 60
593-
return datetime.time(hour, minute, second)
630+
hour = int(horolog // 3600)
631+
horolog -= int(hour * 3600)
632+
minute = int(horolog // 60)
633+
second = int(horolog % 60)
634+
micro = int(value % 1 * 1000000)
635+
return datetime.time(hour, minute, second, micro)
594636
return value
595637

596638
return process
@@ -599,6 +641,7 @@ def process(value):
599641
colspecs = {
600642
sqltypes.Date: _IRISDate,
601643
sqltypes.DateTime: _IRISDateTime,
644+
sqltypes.TIMESTAMP: _IRISTimeStamp,
602645
sqltypes.Time: _IRISTime,
603646
}
604647

@@ -653,7 +696,7 @@ def __init__(self, **kwargs):
653696
def _get_option(self, connection, option):
654697
cursor = connection.cursor()
655698
# cursor = connection.cursor()
656-
cursor.execute('SELECT %SYSTEM_SQL.Util_GetOption(?)', [option, ])
699+
cursor.execute('SELECT %SYSTEM_SQL.Util_GetOption(?)', option)
657700
row = cursor.fetchone()
658701
if row:
659702
return row[0]
@@ -662,7 +705,7 @@ def _get_option(self, connection, option):
662705
def _set_option(self, connection, option, value):
663706
cursor = connection.cursor()
664707
# cursor = connection.cursor()
665-
cursor.execute('SELECT %SYSTEM_SQL.Util_SetOption(?, ?)', [option, value, ])
708+
cursor.execute('SELECT %SYSTEM_SQL.Util_SetOption(?, ?)', option, value)
666709
row = cursor.fetchone()
667710
if row:
668711
return row[0]
@@ -692,8 +735,7 @@ def set_isolation_level(self, connection, level_str):
692735

693736
@classmethod
694737
def dbapi(cls):
695-
dbapi.connect = irisnative.connect
696-
dbapi.paramstyle = "format"
738+
# dbapi.paramstyle = "format"
697739
return dbapi
698740

699741
def create_connect_args(self, url):
@@ -708,36 +750,15 @@ def create_connect_args(self, url):
708750

709751
return ([], opts)
710752

711-
def _fix_for_params(self, query, params, many=False):
712-
if query.endswith(';'):
713-
query = query[:-1]
714-
if params is None:
715-
params = []
716-
elif hasattr(params, 'keys'):
717-
# Handle params as dict
718-
args = {k: "?" % k for k in params}
719-
query = query % args
720-
else:
721-
# Handle params as sequence
722-
args = ['?' for i in range(len(params if not many else params[0]))]
723-
query = query % tuple(args)
724-
newparams = list()
725-
for p in params:
726-
newparams.append(p if not many else list(p)
727-
if len(p) > 1 else p[0])
728-
return query, newparams
729-
730753
def do_execute(self, cursor, query, params, context=None):
731-
query, params = self._fix_for_params(query, params)
732-
# print('do_execute', query, params)
733-
cursor.execute(query, params)
754+
cursor.execute(query, *params)
734755

735756
def do_executemany(self, cursor, query, params, context=None):
736-
query, params = self._fix_for_params(query, params, True)
737757
cursor.executemany(query, params)
738758

739759
def do_begin(self, connection):
740760
pass
761+
# connection.cursor().execute("START TRANSACTION")
741762

742763
def do_rollback(self, connection):
743764
connection.rollback()

sqlalchemy_iris/provision.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from sqlalchemy.testing.provision import temp_table_keyword_args
2+
3+
4+
@temp_table_keyword_args.for_db("iris")
5+
def _iris_temp_table_keyword_args(cfg, eng):
6+
return {"prefixes": ["GLOBAL TEMPORARY"]}

0 commit comments

Comments
 (0)