def array_type(self): return only_on( [ lambda config: against(config, "postgresql") and not against(config, "+pg8000") and not against(config, "+zxjdbc") ] )
def mssql_freetds(self): return only_on( LambdaPredicate( lambda config: ( (against(config, 'mssql+pyodbc') and config.db.dialect.freetds) or against(config, 'mssql+pymssql') ) ) )
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_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" ])
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(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 broken_cx_oracle6_numerics(config): return exclusions.LambdaPredicate( lambda config: against(config, 'oracle+cx_oracle') and config.db.dialect.cx_oracle_ver <= (6, 0, 2) and config.db.dialect.cx_oracle_ver > (6, ), "cx_Oracle github issue #77" )
def check_hstore(config): if not against(config, "postgresql"): return False try: config.db.execute("SELECT 'a=>1,a=>2'::hstore;") return True except: return False
def check_hstore(): if not against("postgresql"): return False try: self.db.execute("SELECT 'a=>1,a=>2'::hstore;") return True except: return False
def json_type(self): return only_on([ lambda config: against(config, "mysql >= 5.7") and not config.db.dialect._is_mariadb and # workaround for: # https://github.com/PyMySQL/PyMySQL/issues/488 not (config.db.dialect.driver == 'pymysql'), "postgresql >= 9.3" ])
def check_range_types(): if not against("postgresql+psycopg2"): return False try: self.db.execute("select '[1,2)'::int4range;") # only supported in psycopg 2.5+ from psycopg2.extras import NumericRange return True except: return False
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: return False
def _prep_testing_database(options, file_config): from sqlalchemy.testing import config, util from sqlalchemy.testing.exclusions import against from sqlalchemy 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.dialects import postgresql for enum in inspector.get_enums("*"): e.execute( postgresql.DropEnumType( postgresql.ENUM( name=enum["name"], schema=enum["schema"] ) ) )
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 'libmsodbcsql-13.1.so.9.2'. # don't know what it is on windows return "msodbc" in drivername
def _prep_testing_database(options, file_config): from sqlalchemy.testing import config from sqlalchemy.testing.exclusions import against from sqlalchemy 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") )) for tname in reversed(inspector.get_table_names( order_by="foreign_key")): e.execute(schema.DropTable( schema.Table(tname, schema.MetaData()) )) if config.requirements.schemas.enabled_for_config(cfg): for tname in reversed(inspector.get_table_names( order_by="foreign_key", schema="test_schema")): e.execute(schema.DropTable( schema.Table(tname, schema.MetaData(), schema="test_schema") )) if against(cfg, "postgresql"): from sqlalchemy.dialects import postgresql for enum in inspector.get_enums("*"): e.execute(postgresql.DropEnumType( postgresql.ENUM( name=enum['name'], schema=enum['schema'])))
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) ), "postgresql", "mssql", "oracle" ])
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" ), LambdaPredicate( lambda config: against(config, 'mssql+pyodbc') and config.db.dialect.freetds and config.db.dialect.freetds_driver_version < "0.91", "older freetds doesn't support unicode DDL" ), exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), ])
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 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 _has_mysql_fully_case_sensitive(self, config): return against(config, 'mysql') and \ config.db.dialect._detect_casing(config.db) == 0
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 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 english_locale_on_postgresql(self): return skip_if(lambda: against('postgresql') \ and not self.db.scalar('SHOW LC_COLLATE').startswith('en'))
def _mysql_80(self, config): return ( against(config, "mysql") and config.db.dialect._is_mysql and config.db.dialect.server_version_info >= (8,) )
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_on_windows(self): return against('mysql') and \ self.db.dialect._detect_casing(self.db) == 1
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 _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 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 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 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 broken_cx_oracle6_numerics(config): return exclusions.LambdaPredicate( lambda config: against(config, 'oracle+cx_oracle' ) and config.db.dialect.cx_oracle_ver <= (6, 0, 2) and config.db.dialect.cx_oracle_ver > (6, ), "cx_Oracle github issue #77")
def postgresql_utf8_server_encoding(self): return only_if(lambda config: against(config, 'postgresql') and config. db.scalar("show server_encoding").lower() == "utf8")
def _prep_testing_database(options, file_config): from sqlalchemy.testing import config, util from sqlalchemy.testing.exclusions import against from sqlalchemy import schema, inspect if options.dropfirst: for cfg in config.Config.all_configs(): e = cfg.db # TODO: this has to be part of provision.py in postgresql if against(cfg, "postgresql"): with e.connect().execution_options( isolation_level="AUTOCOMMIT" ) as conn: for xid in conn.execute( "select gid from pg_prepared_xacts" ).scalars(): conn.execute("ROLLBACK PREPARED '%s'" % xid) 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) # TODO: this has to be part of provision.py in postgresql if against(cfg, "postgresql"): from sqlalchemy.dialects import postgresql for enum in inspector.get_enums("*"): e.execute( postgresql.DropEnumType( postgresql.ENUM( name=enum["name"], schema=enum["schema"] ) ) )
def mssql_freetds(self): return only_on( LambdaPredicate(lambda config: ( (against(config, 'mssql+pyodbc') and config.db.dialect.freetds ) or against(config, 'mssql+pymssql'))))
def cxoracle6_or_greater(self): return only_if( lambda config: against(config, "oracle+cx_oracle") and config.db.dialect.cx_oracle_ver >= (6,) )
def _has_mysql_on_windows(self, config): return ( against(config, "mysql") and config.db.dialect._detect_casing(config.db) == 1 )
def json_type(self): return only_on([ lambda config: against(config, "mysql >= 5.7") and not config.db. dialect._is_mariadb, "postgresql >= 9.3" ])
def _sqlite_tuple_in(config): return against( config, "sqlite" ) and config.db.dialect.dbapi.sqlite_version_info >= (3, 15, 0)
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 _sqlite_memory_db(self, config): return against( config, "sqlite" ) and not config.db.dialect._is_url_file_db(config.db.url)
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 _mysql_not_mariadb_102(self, config): return against(config, "mysql") and ( not config.db.dialect._is_mariadb or config.db.dialect._mariadb_normalized_version_info < (10, 2) )
def postgresql_utf8_server_encoding(self): return only_if( lambda config: against(config, 'postgresql') and config.db.scalar("show server_encoding").lower() == "utf8" )
def oracle5x(self): return only_if( lambda config: against(config, "oracle+cx_oracle") and config.db.dialect.cx_oracle_ver < (6, ) )
def oracle5x(self): return only_if( lambda config: against(config, "oracle+cx_oracle") and config.db.dialect.cx_oracle_ver < (6,) )
def _has_mysql_fully_case_sensitive(self): return against('mysql') and \ self.db.dialect._detect_casing(self.db) == 0
def postgresql_utf8_server_encoding(self): return only_if(lambda config: against(config, "postgresql") and config. db.connect(close_with_result=True).exec_driver_sql( "show server_encoding").scalar().lower() == "utf8")