def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) options = self.settings_dict.get('OPTIONS', None) if options: self.MARS_Connection = options.get('MARS_Connection', False) self.datefirst = options.get('datefirst', 7) self.unicode_results = options.get('unicode_results', False) self.encoding = options.get('encoding', 'utf-8') self.driver_supports_utf8 = options.get('driver_supports_utf8', None) self.driver_needs_utf8 = options.get('driver_needs_utf8', None) self.limit_table_list = options.get('limit_table_list', False) # make lookup operators to be collation-sensitive if needed self.collation = options.get('collation', None) if self.collation: self.operators = dict(self.__class__.operators) ops = {} for op in self.operators: sql = self.operators[op] if sql.startswith('LIKE '): ops[op] = '%s COLLATE %s' % (sql, self.collation) self.operators.update(ops) self.test_create = self.settings_dict.get('TEST_CREATE', True) self.features = DatabaseFeatures(self) self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = BaseDatabaseValidation(self) self.connection = None
def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) options = self.settings_dict.get('OPTIONS', None) if options: self.datefirst = options.get('datefirst', 7) self.unicode_results = options.get('unicode_results', False) self.encoding = options.get('encoding', 'utf-8') self.driver_needs_utf8 = options.get('driver_needs_utf8', None) self.limit_table_list = options.get('limit_table_list', False) # make lookup operators to be collation-sensitive if needed self.collation = options.get('collation', None) if self.collation: self.operators = dict(self.__class__.operators) ops = {} for op in self.operators: sql = self.operators[op] if sql.startswith('LIKE '): ops[op] = '%s COLLATE %s' % (sql, self.collation) self.operators.update(ops) self.test_create = self.settings_dict.get('TEST_CREATE', True) if _DJANGO_VERSION >= 13: self.features = DatabaseFeatures(self) else: self.features = DatabaseFeatures() self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = BaseDatabaseValidation(self) self.connection = None
class DatabaseWrapper(BaseDatabaseWrapper): _DJANGO_VERSION = _DJANGO_VERSION drv_name = None driver_supports_utf8 = None MARS_Connection = False unicode_results = False datefirst = 7 Database = Database limit_table_list = False # Collations: http://msdn2.microsoft.com/en-us/library/ms184391.aspx # http://msdn2.microsoft.com/en-us/library/ms179886.aspx # T-SQL LIKE: http://msdn2.microsoft.com/en-us/library/ms179859.aspx # Full-Text search: http://msdn2.microsoft.com/en-us/library/ms142571.aspx # CONTAINS: http://msdn2.microsoft.com/en-us/library/ms187787.aspx # FREETEXT: http://msdn2.microsoft.com/en-us/library/ms176078.aspx vendor = 'microsoft' operators = { # Since '=' is used not only for string comparision there is no way # to make it case (in)sensitive. It will simply fallback to the # database collation. 'exact': '= %s', 'iexact': "= UPPER(%s)", 'contains': "LIKE %s ESCAPE '\\'", 'icontains': "LIKE UPPER(%s) ESCAPE '\\'", 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', 'lte': '<= %s', 'startswith': "LIKE %s ESCAPE '\\'", 'endswith': "LIKE %s ESCAPE '\\'", 'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", # TODO: remove, keep native T-SQL LIKE wildcards support # or use a "compatibility layer" and replace '*' with '%' # and '.' with '_' 'regex': 'LIKE %s', 'iregex': 'LIKE %s', # TODO: freetext, full-text contains... } # In Django 1.8 data_types was moved from DatabaseCreation to DatabaseWrapper. # See https://docs.djangoproject.com/en/1.10/releases/1.8/#database-backend-api data_types = DatabaseCreation.data_types def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) options = self.settings_dict.get('OPTIONS', None) if options: self.MARS_Connection = options.get('MARS_Connection', False) self.datefirst = options.get('datefirst', 7) self.unicode_results = options.get('unicode_results', False) self.encoding = options.get('encoding', 'utf-8') self.driver_supports_utf8 = options.get('driver_supports_utf8', None) self.driver_needs_utf8 = options.get('driver_needs_utf8', None) self.limit_table_list = options.get('limit_table_list', False) # make lookup operators to be collation-sensitive if needed self.collation = options.get('collation', None) if self.collation: self.operators = dict(self.__class__.operators) ops = {} for op in self.operators: sql = self.operators[op] if sql.startswith('LIKE '): ops[op] = '%s COLLATE %s' % (sql, self.collation) self.operators.update(ops) self.test_create = self.settings_dict.get('TEST_CREATE', True) if _DJANGO_VERSION >= 13: self.features = DatabaseFeatures(self) else: self.features = DatabaseFeatures() self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = BaseDatabaseValidation(self) self.connection = None def get_connection_params(self): settings_dict = self.settings_dict if not settings_dict['NAME']: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "settings.DATABASES is improperly configured. " "Please supply the NAME value.") conn_params = { 'database': settings_dict['NAME'], } conn_params.update(settings_dict['OPTIONS']) if 'autocommit' in conn_params: del conn_params['autocommit'] if settings_dict['USER']: conn_params['user'] = settings_dict['USER'] if settings_dict['PASSWORD']: conn_params['password'] = settings_dict['PASSWORD'] if settings_dict['HOST']: conn_params['host'] = settings_dict['HOST'] if settings_dict['PORT']: conn_params['port'] = settings_dict['PORT'] return conn_params def get_new_connection(self, conn_params): return Database.connect(**conn_params) def init_connection_state(self): pass def _set_autocommit(self, autocommit): pass def _get_connection_string(self): settings_dict = self.settings_dict db_str, user_str, passwd_str, port_str = None, None, "", None options = settings_dict['OPTIONS'] if settings_dict['NAME']: db_str = settings_dict['NAME'] if settings_dict['HOST']: host_str = settings_dict['HOST'] else: host_str = 'localhost' if settings_dict['USER']: user_str = settings_dict['USER'] if settings_dict['PASSWORD']: passwd_str = settings_dict['PASSWORD'] if settings_dict['PORT']: port_str = settings_dict['PORT'] if not db_str: raise ImproperlyConfigured( 'You need to specify NAME in your Django settings file.') cstr_parts = [] if 'driver' in options: driver = options['driver'] else: if os.name == 'nt': driver = 'SQL Server' else: driver = 'FreeTDS' if driver == 'FreeTDS' or driver.endswith('/libtdsodbc.so'): driver_is_freetds = True else: driver_is_freetds = False # Microsoft driver names assumed here are: # * SQL Server # * SQL Native Client # * SQL Server Native Client 10.0/11.0 # * ODBC Driver 11 for SQL Server ms_drivers = re.compile('.*SQL (Server$|(Server )?Native Client)') if 'dsn' in options: cstr_parts.append('DSN=%s' % options['dsn']) else: # Only append DRIVER if DATABASE_ODBC_DSN hasn't been set if os.path.isabs(driver): cstr_parts.append('DRIVER=%s' % driver) else: cstr_parts.append('DRIVER={%s}' % driver) if ms_drivers.match(driver) or driver_is_freetds and \ options.get('host_is_server', False): if port_str: host_str += ';PORT=%s' % port_str cstr_parts.append('SERVER=%s' % host_str) elif self.ops.is_openedge: if port_str: host_str += ';PortNumber=%s' % port_str cstr_parts.append('HostName=%s' % host_str) else: cstr_parts.append('SERVERNAME=%s' % host_str) if user_str: cstr_parts.append('UID=%s;PWD=%s' % (user_str, passwd_str)) else: if ms_drivers.match(driver): cstr_parts.append('Trusted_Connection=yes') else: cstr_parts.append('Integrated Security=SSPI') cstr_parts.append('DATABASE=%s' % db_str) if self.MARS_Connection: cstr_parts.append('MARS_Connection=yes') if 'extra_params' in options: cstr_parts.append(options['extra_params']) connectionstring = ';'.join(cstr_parts) return connectionstring def _cursor(self): new_conn = False settings_dict = self.settings_dict if self.connection is None: new_conn = True connstr = self._get_connection_string() #';'.join(cstr_parts) options = settings_dict['OPTIONS'] autocommit = options.get('autocommit', False) if self.unicode_results: self.connection = Database.connect(connstr, \ autocommit=autocommit, \ unicode_results='True') else: self.connection = Database.connect(connstr, \ autocommit=autocommit) connection_created.send(sender=self.__class__, connection=self) cursor = self.connection.cursor() if new_conn: # Set date format for the connection. Also, make sure Sunday is # considered the first day of the week (to be consistent with the # Django convention for the 'week_day' Django lookup) if the user # hasn't told us otherwise if not self.ops.is_db2 and not self.ops.is_openedge: # IBM's DB2 doesn't support this syntax and a suitable # equivalent could not be found. cursor.execute("SET DATEFORMAT ymd; SET DATEFIRST %s" % self.datefirst) if self.ops.sql_server_ver < 2005: self.creation.data_types['TextField'] = 'ntext' self.data_types['TextField'] = 'ntext' self.features.can_return_id_from_insert = False ms_sqlncli = re.compile('^((LIB)?SQLN?CLI|LIBMSODBCSQL)') self.drv_name = self.connection.getinfo( Database.SQL_DRIVER_NAME).upper() # http://msdn.microsoft.com/en-us/library/ms131686.aspx if self.ops.sql_server_ver >= 2005 and ms_sqlncli.match( self.drv_name) and self.MARS_Connection: # How to to activate it: Add 'MARS_Connection': True # to the DATABASE_OPTIONS dictionary setting self.features.can_use_chunked_reads = True if self.drv_name.startswith('LIBTDSODBC'): # FreeTDS can't execute some sql queries like CREATE DATABASE etc. # in multi-statement, so we need to commit the above SQL sentence(s) # to avoid this if not self.connection.autocommit: self.connection.commit() freetds_version = self.connection.getinfo( Database.SQL_DRIVER_VER) if self.driver_supports_utf8 is None: try: from distutils.version import LooseVersion except ImportError: warnings.warn( Warning( 'Using naive FreeTDS version detection. Install distutils to get better version detection.' )) self.driver_supports_utf8 = not freetds_version.startswith( '0.82') else: # This is the minimum version that properly supports # Unicode. Though it started in version 0.82, the # implementation in that version was buggy. self.driver_supports_utf8 = LooseVersion( freetds_version) >= LooseVersion('0.91') elif self.driver_supports_utf8 is None: self.driver_supports_utf8 = (self.drv_name == 'SQLSRV32.DLL' or ms_sqlncli.match(self.drv_name)) return CursorWrapper(cursor, self.driver_supports_utf8, self.encoding) def _execute_foreach(self, sql, table_names=None): cursor = self.cursor() if not table_names: table_names = self.introspection.get_table_list(cursor) for table_name in table_names: cursor.execute(sql % self.ops.quote_name(table_name)) def check_constraints(self, table_names=None): self._execute_foreach('ALTER TABLE %s WITH CHECK CHECK CONSTRAINT ALL', table_names) def disable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL"') self._execute_foreach('ALTER TABLE %s NOCHECK CONSTRAINT ALL') return True def enable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL"') self.check_constraints()
class DatabaseWrapper(BaseDatabaseWrapper): _DJANGO_VERSION = _DJANGO_VERSION drv_name = None driver_supports_utf8 = None MARS_Connection = False unicode_results = False datefirst = 7 Database = Database # Collations: http://msdn2.microsoft.com/en-us/library/ms184391.aspx # http://msdn2.microsoft.com/en-us/library/ms179886.aspx # T-SQL LIKE: http://msdn2.microsoft.com/en-us/library/ms179859.aspx # Full-Text search: http://msdn2.microsoft.com/en-us/library/ms142571.aspx # CONTAINS: http://msdn2.microsoft.com/en-us/library/ms187787.aspx # FREETEXT: http://msdn2.microsoft.com/en-us/library/ms176078.aspx vendor = 'microsoft' operators = { # Since '=' is used not only for string comparision there is no way # to make it case (in)sensitive. It will simply fallback to the # database collation. 'exact': '= %s', 'iexact': "= UPPER(%s)", 'contains': "LIKE %s ESCAPE '\\'", 'icontains': "LIKE UPPER(%s) ESCAPE '\\'", 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', 'lte': '<= %s', 'startswith': "LIKE %s ESCAPE '\\'", 'endswith': "LIKE %s ESCAPE '\\'", 'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", # TODO: remove, keep native T-SQL LIKE wildcards support # or use a "compatibility layer" and replace '*' with '%' # and '.' with '_' 'regex': 'LIKE %s', 'iregex': 'LIKE %s', # TODO: freetext, full-text contains... } def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) options = self.settings_dict.get('OPTIONS', None) if options: self.MARS_Connection = options.get('MARS_Connection', False) self.datefirst = options.get('datefirst', 7) self.unicode_results = options.get('unicode_results', False) self.encoding = options.get('encoding', 'utf-8') self.driver_supports_utf8 = options.get('driver_supports_utf8', None) # make lookup operators to be collation-sensitive if needed self.collation = options.get('collation', None) if self.collation: self.operators = dict(self.__class__.operators) ops = {} for op in self.operators: sql = self.operators[op] if sql.startswith('LIKE '): ops[op] = '%s COLLATE %s' % (sql, self.collation) self.operators.update(ops) self.test_create = self.settings_dict.get('TEST_CREATE', True) if _DJANGO_VERSION >= 13: self.features = DatabaseFeatures(self) else: self.features = DatabaseFeatures() self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = BaseDatabaseValidation(self) self.connection = None def get_connection_params(self): settings_dict = self.settings_dict if not settings_dict['NAME']: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "settings.DATABASES is improperly configured. " "Please supply the NAME value.") conn_params = { 'database': settings_dict['NAME'], } conn_params.update(settings_dict['OPTIONS']) if 'autocommit' in conn_params: del conn_params['autocommit'] if settings_dict['USER']: conn_params['user'] = settings_dict['USER'] if settings_dict['PASSWORD']: conn_params['password'] = settings_dict['PASSWORD'] if settings_dict['HOST']: conn_params['host'] = settings_dict['HOST'] if settings_dict['PORT']: conn_params['port'] = settings_dict['PORT'] return conn_params def get_new_connection(self, conn_params): return Database.connect(**conn_params) def init_connection_state(self): pass def _set_autocommit(self, autocommit): pass def _get_connection_string(self): settings_dict = self.settings_dict db_str, user_str, passwd_str, port_str = None, None, "", None options = settings_dict['OPTIONS'] if settings_dict['NAME']: db_str = settings_dict['NAME'] if settings_dict['HOST']: host_str = settings_dict['HOST'] else: host_str = 'localhost' if settings_dict['USER']: user_str = settings_dict['USER'] if settings_dict['PASSWORD']: passwd_str = settings_dict['PASSWORD'] if settings_dict['PORT']: port_str = settings_dict['PORT'] if not db_str: raise ImproperlyConfigured('You need to specify NAME in your Django settings file.') cstr_parts = [] if 'driver' in options: driver = options['driver'] else: if os.name == 'nt': driver = 'SQL Server' else: driver = 'FreeTDS' if driver == 'FreeTDS' or driver.endswith('/libtdsodbc.so'): driver_is_freetds = True else: driver_is_freetds = False # Microsoft driver names assumed here are: # * SQL Server # * SQL Native Client # * SQL Server Native Client 10.0/11.0 # * ODBC Driver 11 for SQL Server ms_drivers = re.compile('.*SQL (Server$|(Server )?Native Client)') if 'dsn' in options: cstr_parts.append('DSN=%s' % options['dsn']) else: # Only append DRIVER if DATABASE_ODBC_DSN hasn't been set if os.path.isabs(driver): cstr_parts.append('DRIVER=%s' % driver) else: cstr_parts.append('DRIVER={%s}' % driver) if ms_drivers.match(driver) or driver_is_freetds and \ options.get('host_is_server', False): if port_str: host_str += ';PORT=%s' % port_str cstr_parts.append('SERVER=%s' % host_str) else: cstr_parts.append('SERVERNAME=%s' % host_str) if user_str: cstr_parts.append('UID=%s;PWD=%s' % (user_str, passwd_str)) else: if ms_drivers.match(driver): cstr_parts.append('Trusted_Connection=yes') else: cstr_parts.append('Integrated Security=SSPI') cstr_parts.append('DATABASE=%s' % db_str) if self.MARS_Connection: cstr_parts.append('MARS_Connection=yes') if 'extra_params' in options: cstr_parts.append(options['extra_params']) connectionstring = ';'.join(cstr_parts) return connectionstring def _cursor(self): new_conn = False settings_dict = self.settings_dict if self.connection is None: new_conn = True connstr = self._get_connection_string()#';'.join(cstr_parts) options = settings_dict['OPTIONS'] autocommit = options.get('autocommit', False) if self.unicode_results: self.connection = Database.connect(connstr, \ autocommit=autocommit, \ unicode_results='True') else: self.connection = Database.connect(connstr, \ autocommit=autocommit) connection_created.send(sender=self.__class__, connection=self) cursor = self.connection.cursor() if new_conn: # Set date format for the connection. Also, make sure Sunday is # considered the first day of the week (to be consistent with the # Django convention for the 'week_day' Django lookup) if the user # hasn't told us otherwise cursor.execute("SET DATEFORMAT ymd; SET DATEFIRST %s" % self.datefirst) if self.ops.sql_server_ver < 2005: self.creation.data_types['TextField'] = 'ntext' self.features.can_return_id_from_insert = False ms_sqlncli = re.compile('^((LIB)?SQLN?CLI|LIBMSODBCSQL)') self.drv_name = self.connection.getinfo(Database.SQL_DRIVER_NAME).upper() # http://msdn.microsoft.com/en-us/library/ms131686.aspx if self.ops.sql_server_ver >= 2005 and ms_sqlncli.match(self.drv_name) and self.MARS_Connection: # How to to activate it: Add 'MARS_Connection': True # to the DATABASE_OPTIONS dictionary setting self.features.can_use_chunked_reads = True if self.drv_name.startswith('LIBTDSODBC'): # FreeTDS can't execute some sql queries like CREATE DATABASE etc. # in multi-statement, so we need to commit the above SQL sentence(s) # to avoid this if not self.connection.autocommit: self.connection.commit() freetds_version = self.connection.getinfo(Database.SQL_DRIVER_VER) if self.driver_supports_utf8 is None: try: from distutils.version import LooseVersion except ImportError: warnings.warn(Warning('Using naive FreeTDS version detection. Install distutils to get better version detection.')) self.driver_supports_utf8 = not freetds_version.startswith('0.82') else: # This is the minimum version that properly supports # Unicode. Though it started in version 0.82, the # implementation in that version was buggy. self.driver_supports_utf8 = LooseVersion(freetds_version) >= LooseVersion('0.91') elif self.driver_supports_utf8 is None: self.driver_supports_utf8 = (self.drv_name == 'SQLSRV32.DLL' or ms_sqlncli.match(self.drv_name)) return CursorWrapper(cursor, self.driver_supports_utf8, self.encoding) def _execute_foreach(self, sql, table_names=None): cursor = self.cursor() if not table_names: table_names = self.introspection.get_table_list(cursor) for table_name in table_names: cursor.execute(sql % self.ops.quote_name(table_name)) def check_constraints(self, table_names=None): self._execute_foreach('ALTER TABLE %s WITH CHECK CHECK CONSTRAINT ALL', table_names) def disable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL"') self._execute_foreach('ALTER TABLE %s NOCHECK CONSTRAINT ALL') return True def enable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL"') self.check_constraints()
class DatabaseWrapper(BaseDatabaseWrapper): _DJANGO_VERSION = _DJANGO_VERSION drv_name = None unicode_results = False datefirst = 7 Database = Database limit_table_list = False # Collations: http://msdn2.microsoft.com/en-us/library/ms184391.aspx # http://msdn2.microsoft.com/en-us/library/ms179886.aspx # T-SQL LIKE: http://msdn2.microsoft.com/en-us/library/ms179859.aspx # Full-Text search: http://msdn2.microsoft.com/en-us/library/ms142571.aspx # CONTAINS: http://msdn2.microsoft.com/en-us/library/ms187787.aspx # FREETEXT: http://msdn2.microsoft.com/en-us/library/ms176078.aspx vendor = 'microsoft' operators = { # Since '=' is used not only for string comparision there is no way # to make it case (in)sensitive. It will simply fallback to the # database collation. 'exact': '= %s', 'iexact': "= UPPER(%s)", 'contains': "LIKE %s ESCAPE '\\'", 'icontains': "LIKE UPPER(%s) ESCAPE '\\'", 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', 'lte': '<= %s', 'startswith': "LIKE %s ESCAPE '\\'", 'endswith': "LIKE %s ESCAPE '\\'", 'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", # TODO: remove, keep native T-SQL LIKE wildcards support # or use a "compatibility layer" and replace '*' with '%' # and '.' with '_' 'regex': 'REGEXP_LIKE %s', 'iregex': "REGEXP_LIKE '(?i)' || %s", # TODO: freetext, full-text contains... } def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) options = self.settings_dict.get('OPTIONS', None) if options: self.datefirst = options.get('datefirst', 7) self.unicode_results = options.get('unicode_results', False) self.encoding = options.get('encoding', 'utf-8') self.driver_needs_utf8 = options.get('driver_needs_utf8', None) self.limit_table_list = options.get('limit_table_list', False) # make lookup operators to be collation-sensitive if needed self.collation = options.get('collation', None) if self.collation: self.operators = dict(self.__class__.operators) ops = {} for op in self.operators: sql = self.operators[op] if sql.startswith('LIKE '): ops[op] = '%s COLLATE %s' % (sql, self.collation) self.operators.update(ops) self.test_create = self.settings_dict.get('TEST_CREATE', True) if _DJANGO_VERSION >= 13: self.features = DatabaseFeatures(self) else: self.features = DatabaseFeatures() self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = BaseDatabaseValidation(self) self.connection = None def get_connection_params(self): settings_dict = self.settings_dict if not settings_dict['NAME']: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "settings.DATABASES is improperly configured. " "Please supply the NAME value.") conn_params = { 'database': settings_dict['NAME'], } conn_params.update(settings_dict['OPTIONS']) if 'autocommit' in conn_params: del conn_params['autocommit'] if settings_dict['USER']: conn_params['user'] = settings_dict['USER'] if settings_dict['PASSWORD']: conn_params['password'] = settings_dict['PASSWORD'] if settings_dict['HOST']: conn_params['host'] = settings_dict['HOST'] if settings_dict['PORT']: conn_params['port'] = settings_dict['PORT'] return conn_params def get_new_connection(self, conn_params=None): # assert False, "JAMI: I think this method is never used" # bad assumption assert conn_params is None, "JAMI: We don't use conn_params that come from outside... should we?" connstr = self._get_connection_string() options = self.settings_dict['OPTIONS'] autocommit = options.get('autocommit', False) if self.unicode_results: connection = Database.connect(connstr, autocommit=autocommit, unicode_results='True') else: connection = Database.connect(connstr, autocommit=autocommit) return connection def init_connection_state(self): pass def _set_autocommit(self, autocommit): pass def _get_connection_string(self): settings_dict = self.settings_dict db_str, user_str, passwd_str, host_str, port_str = None, None, "", None, None options = settings_dict['OPTIONS'] if settings_dict['NAME']: db_str = settings_dict['NAME'] if settings_dict['USER']: user_str = settings_dict['USER'] if settings_dict['PASSWORD']: passwd_str = settings_dict['PASSWORD'] if settings_dict['HOST']: host_str = settings_dict['HOST'] if settings_dict['PORT']: port_str = settings_dict['PORT'] cstr_parts = [] if db_str: cstr_parts.append('DATABASE=%s' % db_str) else: raise ImproperlyConfigured('You need to specify NAME in your Django settings file.') # parse extra params connection string into a dict of keys and values extra_params = {k:v for k,v in [param.split('=') for param in options.get('extra_params','').split(';')]} if 'dsn' in options: cstr_parts.append('DSN=%s' % options['dsn']) elif 'driver' in options: cstr_parts.append('DRIVER={%s}' % options['driver']) else: raise ImproperlyConfigured("You need to specify the ODBC 'driver' or ODBC 'dsn' in your Django settings file.") if user_str and passwd_str: cstr_parts.append('UID=%s;PWD=%s' % (user_str, passwd_str)) else: raise ImproperlyConfigured("You need to specify 'USER' and 'PASSWORD' in your Django settings file.") if host_str: if 'EXAHOST' in extra_params: raise ImproperlyConfigured("Either specify HOST and PORT settings or EXAHOST in extra_params but not both") else: if ':' in host_str: host_str, port_str = host_str.split(':') port_str = unicode(port_str) or '8563' # default exasol port cstr_parts.append('EXAHOST=%s:%s' % (host_str, port_str)) cstr_parts.extend(["%s=%s" % (k,v) for k,v in extra_params.items()]) # enable efficient conversion to Python types: see https://www.exasol.com/support/browse/EXASOL-898 # unless explictly told otherwise if not any('INTTYPESINRESULTSIFPOSSIBLE' in p for p in cstr_parts): cstr_parts.append('INTTYPESINRESULTSIFPOSSIBLE=y') connectionstring = ';'.join(cstr_parts) return connectionstring def _cursor(self): if self.connection is None: self.connection = self.get_new_connection() # JAMI: shouldn't we send the signal from within get_new_connection() ? connection_created.send(sender=self.__class__, connection=self) cursor = self.connection.cursor() return CursorWrapper(cursor, self.encoding) def _execute_foreach(self, sql, table_names=None): cursor = self.cursor() if not table_names: table_names = self.introspection.get_table_list(cursor) for table_name in table_names: cursor.execute(sql % self.ops.quote_name(table_name)) def check_constraints(self, table_names=None): self._execute_foreach('ALTER TABLE %s WITH CHECK CHECK CONSTRAINT ALL', table_names) def disable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL"') self._execute_foreach('ALTER TABLE %s NOCHECK CONSTRAINT ALL') return True def enable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL"') self.check_constraints()
class DatabaseWrapper(BaseDatabaseWrapper): _DJANGO_VERSION = _DJANGO_VERSION drv_name = None driver_needs_utf8 = None MARS_Connection = False unicode_results = False datefirst = 7 # Collations: http://msdn2.microsoft.com/en-us/library/ms184391.aspx # http://msdn2.microsoft.com/en-us/library/ms179886.aspx # T-SQL LIKE: http://msdn2.microsoft.com/en-us/library/ms179859.aspx # Full-Text search: http://msdn2.microsoft.com/en-us/library/ms142571.aspx # CONTAINS: http://msdn2.microsoft.com/en-us/library/ms187787.aspx # FREETEXT: http://msdn2.microsoft.com/en-us/library/ms176078.aspx vendor = 'microsoft' operators = { # Since '=' is used not only for string comparision there is no way # to make it case (in)sensitive. It will simply fallback to the # database collation. 'exact': '= %s', 'iexact': "= UPPER(%s)", 'contains': "LIKE %s ESCAPE '\\'", 'icontains': "LIKE UPPER(%s) ESCAPE '\\'", 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', 'lte': '<= %s', 'startswith': "LIKE %s ESCAPE '\\'", 'endswith': "LIKE %s ESCAPE '\\'", 'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", # TODO: remove, keep native T-SQL LIKE wildcards support # or use a "compatibility layer" and replace '*' with '%' # and '.' with '_' 'regex': 'LIKE %s', 'iregex': 'LIKE %s', # TODO: freetext, full-text contains... } def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) options = self.settings_dict.get('OPTIONS', None) if options: self.MARS_Connection = options.get('MARS_Connection', False) self.datefirst = options.get('datefirst', 7) self.unicode_results = options.get('unicode_results', False) # make lookup operators to be collation-sensitive if needed self.collation = options.get('collation', None) if self.collation: self.operators = dict(self.__class__.operators) ops = {} for op in self.operators: sql = self.operators[op] if sql.startswith('LIKE '): ops[op] = '%s COLLATE %s' % (sql, self.collation) self.operators.update(ops) self.test_create = self.settings_dict.get('TEST_CREATE', True) if _DJANGO_VERSION >= 13: self.features = DatabaseFeatures(self) else: self.features = DatabaseFeatures() self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = BaseDatabaseValidation(self) self.connection = None def _cursor(self): new_conn = False settings_dict = self.settings_dict db_str, user_str, passwd_str, port_str = None, None, "", None options = settings_dict['OPTIONS'] if settings_dict['NAME']: db_str = settings_dict['NAME'] if settings_dict['HOST']: host_str = settings_dict['HOST'] else: host_str = 'localhost' if settings_dict['USER']: user_str = settings_dict['USER'] if settings_dict['PASSWORD']: passwd_str = settings_dict['PASSWORD'] if settings_dict['PORT']: port_str = settings_dict['PORT'] if self.connection is None: new_conn = True if not db_str: raise ImproperlyConfigured('You need to specify NAME in your Django settings file.') cstr_parts = [] if 'driver' in options: driver = options['driver'] else: if os.name == 'nt': driver = 'SQL Server' else: driver = 'FreeTDS' # Microsoft driver names assumed here are: # * SQL Server # * SQL Native Client # * SQL Server Native Client 10.0/11.0 # * ODBC Driver 11 for SQL Server ms_drivers = re.compile('.*SQL (Server$|(Server )?Native Client)') if 'dsn' in options: cstr_parts.append('DSN=%s' % options['dsn']) else: # Only append DRIVER if DATABASE_ODBC_DSN hasn't been set cstr_parts.append('DRIVER={%s}' % driver) if ms_drivers.match(driver) or driver == 'FreeTDS' and \ options.get('host_is_server', False): if port_str: host_str += ';PORT=%s' % port_str cstr_parts.append('SERVER=%s' % host_str) else: cstr_parts.append('SERVERNAME=%s' % host_str) if user_str: cstr_parts.append('UID=%s;PWD=%s' % (user_str, passwd_str)) else: if ms_drivers.match(driver): cstr_parts.append('Trusted_Connection=yes') else: cstr_parts.append('Integrated Security=SSPI') cstr_parts.append('DATABASE=%s' % db_str) if self.MARS_Connection: cstr_parts.append('MARS_Connection=yes') if 'extra_params' in options: cstr_parts.append(options['extra_params']) connstr = ';'.join(cstr_parts) autocommit = options.get('autocommit', False) if self.unicode_results: self.connection = Database.connect(connstr, \ autocommit=autocommit, \ unicode_results='True') else: self.connection = Database.connect(connstr, \ autocommit=autocommit) connection_created.send(sender=self.__class__, connection=self) cursor = self.connection.cursor() if new_conn: # Set date format for the connection. Also, make sure Sunday is # considered the first day of the week (to be consistent with the # Django convention for the 'week_day' Django lookup) if the user # hasn't told us otherwise cursor.execute("SET DATEFORMAT ymd; SET DATEFIRST %s" % self.datefirst) if self.ops.sql_server_ver < 2005: self.creation.data_types['TextField'] = 'ntext' self.features.can_return_id_from_insert = False ms_sqlncli = re.compile('^((LIB)?SQLN?CLI|LIBMSODBCSQL)') if self.driver_needs_utf8 is None: self.driver_needs_utf8 = True self.drv_name = self.connection.getinfo(Database.SQL_DRIVER_NAME).upper() if self.drv_name == 'SQLSRV32.DLL' or ms_sqlncli.match(self.drv_name): self.driver_needs_utf8 = False # http://msdn.microsoft.com/en-us/library/ms131686.aspx if self.ops.sql_server_ver >= 2005 and ms_sqlncli.match(self.drv_name) and self.MARS_Connection: # How to to activate it: Add 'MARS_Connection': True # to the DATABASE_OPTIONS dictionary setting self.features.can_use_chunked_reads = True # FreeTDS can't execute some sql queries like CREATE DATABASE etc. # in multi-statement, so we need to commit the above SQL sentence(s) # to avoid this if self.drv_name.startswith('LIBTDSODBC') and not self.connection.autocommit: self.connection.commit() return CursorWrapper(cursor, self.driver_needs_utf8) def _execute_foreach(self, sql, table_names=None): # This method needs to take schemas into account, otherwise SQL Server # will throw errors saying it can't find any table that's not in the # current default schema. This is a problem for databases that use # schemas as a way to organize tables into related groups. In order # to avoid breaking the previous API this will default the schema to # 'dbo' when given a list of table_names that is not a list of tuples. cursor = self.cursor() if not table_names: table_names = self.introspection.get_table_schemas(cursor) for pair in table_names: if type(pair) is not tuple: pair = ('dbo', pair) schema_table = self.ops.quote_schema_name(pair[0], pair[1]) cursor.execute(sql % schema_table) def check_constraints(self, table_names=None): self._execute_foreach('ALTER TABLE %s WITH CHECK CHECK CONSTRAINT ALL', table_names) def disable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL"') self._execute_foreach('ALTER TABLE %s NOCHECK CONSTRAINT ALL') return True def enable_constraint_checking(self): # Windows Azure SQL Database doesn't support sp_msforeachtable #cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL"') self.check_constraints()