def json_type(self): return only_on([ lambda config: against(config, "mysql") and ( (not config.db.dialect._is_mariadb and against( config, "mysql >= 5.7")) or (config.db.dialect._mariadb_normalized_version_info >= (10, 2, 7))), "postgresql >= 9.3", self._sqlite_json, ])
def check(config): if against(config, "mysql+mysqldb"): # can remove once post 1.3.13 is released try: from MySQLdb import converters from decimal import Decimal return Decimal not in converters.conversions except: return True return against( config, "mysql+mysqldb" ) and config.db.dialect._mysql_dbapi_version <= (1, 3, 13)
def json_index_supplementary_unicode_element(self): # for sqlite see https://bugs.python.org/issue38749 return skip_if([ lambda config: against(config, "mysql") and config.db.dialect. _is_mariadb, "sqlite", ])
def reflects_json_type(self): return only_on([ lambda config: against(config, "mysql >= 5.7") and not config.db. dialect._is_mariadb, "postgresql >= 9.3", "sqlite >= 3.9", ])
def check_range_types(config): if not against(config, ["postgresql+psycopg2", "postgresql+psycopg2cffi"]): return False try: config.db.scalar("select '[1,2)'::int4range;") return True except Exception: return False
def _sqlite_json(self, config): if not against(config, "sqlite >= 3.9"): return False else: with config.db.connect() as conn: try: return (conn.scalar( """select json_extract('{"foo": "bar"}', """ """'$."foo"')""") == "bar") except exc.DBAPIError: return False
def has_fastexecutemany(config): if not against(config, "mssql+pyodbc"): return False if config.db.dialect._dbapi_version() < (4, 0, 19): return False with config.db.connect() as conn: drivername = conn.connection.connection.getinfo( config.db.dialect.dbapi.SQL_DRIVER_NAME) # on linux this is something like 'libmsodbcsql-13.1.so.9.2'. # on Windows this is something like 'msodbcsql17.dll'. return "msodbc" in drivername
def get_isolation_levels(self, config): levels = set(config.db.dialect._isolation_lookup) if against(config, "sqlite"): default = "SERIALIZABLE" levels.add("AUTOCOMMIT") elif against(config, "postgresql"): default = "READ COMMITTED" levels.add("AUTOCOMMIT") elif against(config, "mysql"): default = "REPEATABLE READ" levels.add("AUTOCOMMIT") elif against(config, "mssql"): default = "READ COMMITTED" levels.add("AUTOCOMMIT") elif against(config, "oracle"): default = "READ COMMITTED" levels.add("AUTOCOMMIT") else: raise NotImplementedError() return {"default": default, "supported": levels}
def ctes(self): """Target database supports CTEs""" return only_on([ lambda config: against(config, "mysql") and ( (config.db.dialect._is_mariadb and config.db.dialect. _mariadb_normalized_version_info >= (10, 2)) or (not config.db.dialect._is_mariadb and config.db. dialect.server_version_info >= (8, ))), "postgresql", "mssql", "oracle", "sqlite>=3.8.3", ])
def _mysql_and_check_constraints_exist(self, config): # 1. we have mysql / mariadb and # 2. it enforces check constraints if exclusions.against(config, "mysql"): if config.db.dialect._is_mariadb: norm_version_info = ( config.db.dialect._mariadb_normalized_version_info) return norm_version_info >= (10, 2) else: norm_version_info = config.db.dialect.server_version_info return norm_version_info >= (8, 0, 16) else: return False
def pg_prepared_transaction(config): if not against(config, "postgresql"): return False with config.db.connect() as conn: try: num = conn.scalar( text( "select cast(setting AS integer) from pg_settings " "where name = 'max_prepared_transactions'")) except exc.OperationalError: return False else: return num > 0
def non_native_boolean_unconstrained(self): """target database is not native boolean and allows arbitrary integers in it's "bool" column""" return skip_if([ LambdaPredicate( lambda config: against(config, "mssql"), "SQL Server drivers / odbc seem to change " "their mind on this", ), LambdaPredicate( lambda config: config.db.dialect.supports_native_boolean, "native boolean dialect", ), ])
def unicode_ddl(self): """Target driver must support some degree of non-ascii symbol names.""" # TODO: expand to exclude MySQLdb versions w/ broken unicode return skip_if([ no_support("oracle", "FIXME: no support in database?"), no_support("sybase", "FIXME: guessing, needs confirmation"), no_support("mssql+pymssql", "no FreeTDS support"), LambdaPredicate( lambda config: against(config, "mysql+mysqlconnector") and config.db.dialect._mysqlconnector_version_info > (2, 0) and util.py2k, "bug in mysqlconnector 2.0", ), exclude("mysql", "<", (4, 1, 1), "no unicode connection support"), ])
def _prep_testing_database(options, file_config): from sqlalchemy_1_3.testing import config, util from sqlalchemy_1_3.testing.exclusions import against from sqlalchemy_1_3 import schema, inspect if options.dropfirst: for cfg in config.Config.all_configs(): e = cfg.db inspector = inspect(e) try: view_names = inspector.get_view_names() except NotImplementedError: pass else: for vname in view_names: e.execute( schema._DropView(schema.Table(vname, schema.MetaData()))) if config.requirements.schemas.enabled_for_config(cfg): try: view_names = inspector.get_view_names(schema="test_schema") except NotImplementedError: pass else: for vname in view_names: e.execute( schema._DropView( schema.Table( vname, schema.MetaData(), schema="test_schema", ))) util.drop_all_tables(e, inspector) if config.requirements.schemas.enabled_for_config(cfg): util.drop_all_tables(e, inspector, schema=cfg.test_schema) if against(cfg, "postgresql"): from sqlalchemy_1_3.dialects import postgresql for enum in inspector.get_enums("*"): e.execute( postgresql.DropEnumType( postgresql.ENUM(name=enum["name"], schema=enum["schema"])))
def cxoracle6_or_greater(self): return only_if(lambda config: against(config, "oracle+cx_oracle") and config.db.dialect.cx_oracle_ver >= (6, ))
def check(config): if not against(config, "mysql"): return False row = config.db.execute("show variables like 'sql_mode'").first() return not row or "NO_ZERO_DATE" not in row[1]
def broken_cx_oracle(config): return (against(config, "oracle+cx_oracle") and config.db.dialect.cx_oracle_ver <= (6, 0, 2) and config.db.dialect.cx_oracle_ver > (6, ))
def _sqlite_memory_db(self, config): return against( config, "sqlite") and not config.db.dialect._is_url_file_db(config.db.url)
def check(config): if not against(config, "mysql"): return False row = config.db.execute("show variables like 'sql_mode'").first() return not row or "STRICT_TRANS_TABLES" not in row[1]
def _mariadb_102(self, config): return (against(config, "mysql") and config.db.dialect._is_mariadb and config.db.dialect._mariadb_normalized_version_info > (10, 2))
def check(config): return (against(config, "mysql") and not config.db.dialect._is_mariadb and config.db.dialect.server_version_info >= (5, 7))
def _mysql_check_constraints_exist(self, config): # 1. we dont have mysql / mariadb or # 2. we have mysql / mariadb that enforces check constraints return not exclusions.against( config, "mysql") or self._mysql_and_check_constraints_exist(config)
def array_type(self): return only_on([ lambda config: against(config, "postgresql") and not against( config, "+pg8000") and not against(config, "+zxjdbc") ])
def _has_mysql_on_windows(self, config): return (against(config, "mysql") and config.db.dialect._detect_casing(config.db) == 1)
def _mysql_not_mariadb_104(self, config): return against(config, "mysql") and ( not config.db.dialect._is_mariadb or config.db.dialect._mariadb_normalized_version_info < (10, 4))
def _has_mysql_fully_case_sensitive(self, config): return (against(config, "mysql") and config.db.dialect._detect_casing(config.db) == 0)
def _sqlite_tuple_in(config): return against( config, "sqlite" ) and config.db.dialect.dbapi.sqlite_version_info >= (3, 15, 0)
def oracle5x(self): return only_if(lambda config: against(config, "oracle+cx_oracle") and config.db.dialect.cx_oracle_ver < (6, ))
def check(config): if not against(config, "postgresql"): return False count = config.db.scalar("SELECT count(*) FROM pg_extension " "WHERE extname='%s'" % name) return bool(count)
def postgresql_utf8_server_encoding(self): return only_if(lambda config: against(config, "postgresql") and config. db.scalar("show server_encoding").lower() == "utf8")