diff --git a/README.md b/README.md index a2752e0..31e1b98 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# Disclaimer +I am fine tuning this Progress Openedge SQLalchemy dialect for use in a meltano based data infrastructure improvement at my organization. + + + + # SQLAlchemy dialect for Progress OpenEdge An adaption of [this work](https://github.com/dholth/progress_sa) for Python3 and Progress OpenEdge 11.7 @@ -8,6 +14,8 @@ An adaption of [this work](https://github.com/dholth/progress_sa) for Python3 an $ cd progress_sa $ python setup.py install ``` +## DRIVER_NAME env variable +Due to variation in driver names, create an environment variable called PROGRESS_OE_DRIVER_NAME with your particular driver name and the driver will pull it in and use it. ## Usage diff --git a/progress_sa/base.py b/progress_sa/base.py index 0f96566..8016de7 100644 --- a/progress_sa/base.py +++ b/progress_sa/base.py @@ -84,7 +84,7 @@ 'bigint':BIGINT, 'bit':BOOLEAN, 'character':CHAR, - 'date':DATE, + 'date':TIMESTAMP, 'float':FLOAT, # double precision. Also FLOAT(8) in SQL. 'integer':INTEGER, 'numeric':NUMERIC, @@ -96,6 +96,10 @@ 'timestamp_timezone':TIMESTAMP, 'varbinary':VARCHAR, 'varchar':VARCHAR, + 'lvarbinary':VARCHAR, + 'varbina':VARCHAR, + 'lvarchar':VARCHAR, + 'decimal':FLOAT, } class ProgressExecutionContext(default.DefaultExecutionContext): @@ -197,11 +201,17 @@ def _get_default_schema_name(self, connection): def _get_raw_cursor(self, connection): return connection.engine.raw_connection().cursor() + + def get_schema_names(self, connection, **kw): + cursor = self._get_raw_cursor(connection) + schemas = cursor.execute('select distinct owner from sysprogress.SYSTABLES') + return [row[0] for row in schemas] - def get_table_names(self, connection, schema): + def get_table_names(self, connection, schema, **kw): cursor = self._get_raw_cursor(connection) s = cursor.tables(schema=schema or '') return [row.table_name for row in s] + def has_table(self, connection, tablename, schema=None): cursor = self._get_raw_cursor(connection) @@ -221,7 +231,7 @@ def get_columns(self, connection, table_name, schema=None, **kw): type_name = column[index['type_name']] column_size = column[index['column_size']] - coltype = ischema_names[type_name](column_size) + coltype = ischema_names[type_name]() columns.append(dict(name=name, type=coltype, nullable=nullable, default=default, @@ -237,6 +247,25 @@ def get_primary_keys(self, connection, table_name, schema=None, **kw): def get_foreign_keys(self, *args, **kw): # does not seem to be implemented in the database. return [] + + def get_pk_constraint(self, connection, tablename, schema, **kw): + pkeys = [] + cursor = self._get_raw_cursor(connection) + c = cursor.execute('select * from SYSPROGRESS.SYS_TBL_CONSTRS') + constraint_name = None + + for row in c.fetchall(): + if "PRIMARY" in row[1]: + pkeys.append(row[4]) + if constraint_name is None: + constraint_name = row[0] + if pkeys: + return { + "constrained_columns": pkeys, + "name": constraint_name, + } + + def get_indexes(self, connection, table_name, schema=None, **kw): # implemented in the database, not terribly useful. diff --git a/progress_sa/pyodbc.py b/progress_sa/pyodbc.py index 3de1e66..87c13ec 100644 --- a/progress_sa/pyodbc.py +++ b/progress_sa/pyodbc.py @@ -1,7 +1,9 @@ from progress_sa.base import ProgressDialect, ProgressExecutionContext from sqlalchemy.connectors.pyodbc import PyODBCConnector from sqlalchemy import util +from urllib.parse import unquote_plus import sys +import os class ProgressExecutionContext_pyodbc(ProgressExecutionContext): @@ -10,7 +12,7 @@ class ProgressExecutionContext_pyodbc(ProgressExecutionContext): class Progress_pyodbc(PyODBCConnector, ProgressDialect): # pyodbc_driver_name = 'Progress OpenEdge Wire Protocol' - pyodbc_driver_name = 'DataDirect 7.1 Progress OpenEdge Wire Protocol' + pyodbc_driver_name = os.environ.get("PROGRESS_OE_DRIVER_NAME") execution_ctx_cls = ProgressExecutionContext_pyodbc def __init__(self, **kwargs): super(Progress_pyodbc, self).__init__(**kwargs) @@ -30,7 +32,7 @@ def create_connect_args(self, url): connect_args[param] = util.asbool(keys.pop(param)) if "odbc_connect" in keys: - connectors = [util.unquote_plus(keys.pop("odbc_connect"))] + connectors = [unquote_plus(keys.pop("odbc_connect"))] else: def check_quote(token):