[
  {
    "path": ".editorconfig",
    "content": "# https://editorconfig.org/\n\nroot = true\n\n[*]\nindent_style = space\nindent_size = 4\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nend_of_line = lf\ncharset = utf-8\nmax_line_length = 119\n\n[*.{yml,yaml}]\nindent_size = 2\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: Tests\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\nenv:\n  DATABASE_URL: \"mssql://SA:MyPassword42@localhost:1433/default?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server\"\n  DATABASE_URL_OTHER: \"mssql://SA:MyPassword42@localhost:1433/other?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server\"\n\njobs:\n  linting:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v1\n\n      - name: Set up Python\n        uses: actions/setup-python@v1\n        with:\n          python-version: \"3.8\"\n\n      - name: Install\n        run: |\n          python -m pip install --upgrade pip\n          pip install flake8\n      - name: Linting\n        run: |\n          flake8 --exclude testapp\n\n  build:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, windows-latest]\n        tox_env:\n          - \"py36-django22\"\n          - \"py36-django30\"\n          - \"py36-django31\"\n\n          - \"py37-django22\"\n          - \"py37-django30\"\n          - \"py37-django31\"\n\n          - \"py38-django30\"\n          - \"py38-django31\"\n\n        include:\n          - python: \"3.6\"\n            tox_env: \"py36-django22\"\n\n          - python: \"3.6\"\n            tox_env: \"py36-django30\"\n\n          - python: \"3.6\"\n            tox_env: \"py36-django31\"\n\n          - python: \"3.7\"\n            tox_env: \"py37-django22\"\n\n          - python: \"3.7\"\n            tox_env: \"py37-django30\"\n\n          - python: \"3.7\"\n            tox_env: \"py37-django31\"\n\n          - python: \"3.8\"\n            tox_env: \"py38-django30\"\n\n          - python: \"3.8\"\n            tox_env: \"py38-django31\"\n\n\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/checkout@v2\n        with:\n          repository: django/django\n          path: django\n      - name: Set up Python\n        uses: actions/setup-python@v1\n        with:\n          python-version: ${{ matrix.python }}\n\n      - name: Install Linux deps\n        if: matrix.os == 'ubuntu-latest'\n        run: |\n          curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -\n          curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list\n          sudo apt-get update\n          sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17 g++ unixodbc-dev libmemcached-dev\n\n      - name: Install Windows deps\n        if: matrix.os == 'windows-latest'\n        run: |\n            powershell wget https://download.microsoft.com/download/E/6/B/E6BFDC7A-5BCD-4C51-9912-635646DA801E/en-US/msodbcsql_17.3.1.1_x64.msi -OutFile msodbcsql_17.3.1.1_x64.msi\n            powershell \"Start-Process msiexec.exe -Wait -ArgumentList '/I msodbcsql_17.3.1.1_x64.msi /qn /norestart IACCEPTMSODBCSQLLICENSETERMS=YES'\"\n\n      - name: Install\n        run: |\n          python -m pip install --upgrade pip wheel setuptools\n          pip install tox tox-venv\n\n      - name: Test Linux\n        if: matrix.os == 'ubuntu-latest'\n        run: |\n          docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyPassword42' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu\n          tox -e ${{ matrix.tox_env }}\n\n      - name: Test Windows\n        if: matrix.os == 'windows-latest'\n        run: |\n          docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyPassword42' -p 1433:1433 -d christianacca/mssql-server-windows-express:1809\n          tox -e ${{ matrix.tox_env }}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.py[co]\n*.sw[a-z]\n*.orig\n*~\n.DS_Store\nThumbs.db\n\n*.egg-info\n\ntests/local_settings.py\n\n# Virtual Env\n/venv/\n.idea/\n"
  },
  {
    "path": ".travis.yml",
    "content": "sudo: required\nlanguage: python\ndist: xenial\ncache: pip\n\nbranches:\n  only:\n    - master\n\nenv:\n  global:\n    - PYTHONPATH=$PYTHONPATH:$TRAVIS_BUILD_DIR/django\n    - DATABASE_URL=\"mssql://SA:MyPassword42@localhost:1433/default?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server\"\n    - DATABASE_URL_OTHER=\"mssql://SA:MyPassword42@localhost:1433/other?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server\"\n\nservices: docker\n\ntemplates:\n  linux_before_install: &linux_before_install\n    - docker pull mcr.microsoft.com/mssql/server:2017-latest-ubuntu\n    - docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyPassword42' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu\n    - curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -\n    - curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list\n    - sudo apt-get update\n    - sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17 g++ unixodbc-dev\n\n  win_before_install: &win_before_install\n    - docker pull christianacca/mssql-server-windows-express:1803\n    - docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyPassword42' -p 1433:1433 -d christianacca/mssql-server-windows-express:1803\n    - wget https://download.microsoft.com/download/E/6/B/E6BFDC7A-5BCD-4C51-9912-635646DA801E/en-US/msodbcsql_17.3.1.1_x64.msi\n    - powershell \"Start-Process msiexec.exe -Wait -ArgumentList '/I msodbcsql_17.3.1.1_x64.msi /qn /norestart IACCEPTMSODBCSQLLICENSETERMS=YES'\"\n    - choco install python3 --version 3.7.2\n    - export PATH=\"/c/Python37:/c/Python37/Scripts:$PATH\"\n\nmatrix:\n  include:\n    - env: FLAKE8\n      python: \"3.7\"\n      install: pip install flake8==3.7.1\n      script: flake8\n\n    - { before_install: *linux_before_install, python: \"3.6\", os: linux, env: TOX_ENV=py36-django22 }\n    - { before_install: *linux_before_install, python: \"3.6\", os: linux, env: TOX_ENV=py36-django30 }\n    - { before_install: *linux_before_install, python: \"3.6\", os: linux, env: TOX_ENV=py36-django31 }\n\n    - { before_install: *linux_before_install, python: \"3.7\", os: linux, env: TOX_ENV=py37-django22 }\n    - { before_install: *linux_before_install, python: \"3.7\", os: linux, env: TOX_ENV=py37-django30 }\n    - { before_install: *linux_before_install, python: \"3.7\", os: linux, env: TOX_ENV=py37-django31 }\n\n    - { before_install: *linux_before_install, python: \"3.8\", os: linux, env: TOX_ENV=py38-django30 }\n    - { before_install: *linux_before_install, python: \"3.8\", os: linux, env: TOX_ENV=py38-django31 }\n\n    - { before_install: *win_before_install, language: sh, python: \"3.6\", os: windows, env: TOX_ENV=py36-django22 }\n    - { before_install: *win_before_install, language: sh, python: \"3.6\", os: windows, env: TOX_ENV=py36-django30 }\n    - { before_install: *win_before_install, language: sh, python: \"3.6\", os: windows, env: TOX_ENV=py36-django31 }\n\n    - { before_install: *win_before_install, language: sh, python: \"3.7\", os: windows, env: TOX_ENV=py37-django22 }\n    - { before_install: *win_before_install, language: sh, python: \"3.7\", os: windows, env: TOX_ENV=py37-django30 }\n    - { before_install: *win_before_install, language: sh, python: \"3.7\", os: windows, env: TOX_ENV=py37-django31 }\n\n    - { before_install: *win_before_install, language: sh, python: \"3.8\", os: windows, env: TOX_ENV=py38-django30 }\n    - { before_install: *win_before_install, language: sh, python: \"3.8\", os: windows, env: TOX_ENV=py38-django31 }\n\n\n\ninstall:\n  - python -m pip install --upgrade pip wheel setuptools\n  - pip install tox tox-travis tox-venv\n  - git clone https://github.com/django/django.git\n\nscript:\n  - tox -e $TOX_ENV\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2019, ES Solutions AB\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include LICENSE\ninclude MANIFEST.in\ninclude README.rst\nrecursive-include sql_server *.py\nrecursive-exclude docker *\n"
  },
  {
    "path": "README.rst",
    "content": "django-mssql-backend\n====================\n\n.. image:: https://img.shields.io/pypi/v/django-mssql-backend.svg\n   :target: https://pypi.python.org/pypi/django-mssql-backend\n\n*django-mssql-backend* is a fork of\n`django-pyodbc-azure <https://pypi.org/project/django-pyodbc-azure/>`__\n\nFeatures\n--------\n\n-  Supports Django 2.2, 3.0\n-  Supports Microsoft SQL Server 2008/2008R2, 2012, 2014, 2016, 2017, 2019\n-  Passes most of the tests of the Django test suite\n-  Compatible with\n   `Micosoft ODBC Driver for SQL Server <https://docs.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server>`__,\n   `SQL Server Native Client <https://msdn.microsoft.com/en-us/library/ms131321(v=sql.120).aspx>`__,\n   and `FreeTDS <http://www.freetds.org/>`__ ODBC drivers\n\nDependencies\n------------\n\n-  Django 2.2 or newer\n-  pyodbc 3.0 or newer\n\nInstallation\n------------\n\n1. Install pyodbc and Django\n\n2. Install django-mssql-backend ::\n\n    pip install django-mssql-backend\n\n3. Now you can point the ``ENGINE`` setting in the settings file used by\n   your Django application or project to the ``'sql_server.pyodbc'``\n   module path ::\n\n    'ENGINE': 'sql_server.pyodbc'\n\nRegex Support\n-------------\n\ndjango-mssql-backend supports regex using a CLR .dll file. To install it, run ::\n\n    python manage.py install_regex_clr {database_name}\n\nConfiguration\n-------------\n\nStandard Django settings\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe following entries in a database-level settings dictionary\nin DATABASES control the behavior of the backend:\n\n-  ENGINE\n\n   String. It must be ``\"sql_server.pyodbc\"``.\n\n-  NAME\n\n   String. Database name. Required.\n\n-  HOST\n\n   String. SQL Server instance in ``\"server\\instance\"`` format.\n\n-  PORT\n\n   String. Server instance port.\n   An empty string means the default port.\n\n-  USER\n\n   String. Database user name in ``\"user\"`` format.\n   If not given then MS Integrated Security will be used.\n\n-  PASSWORD\n\n   String. Database user password.\n\n-  AUTOCOMMIT\n\n   Boolean. Set this to False if you want to disable\n   Django's transaction management and implement your own.\n\nand the following entries are also available in the TEST dictionary\nfor any given database-level settings dictionary:\n\n-  NAME\n\n   String. The name of database to use when running the test suite.\n   If the default value (``None``) is used, the test database will use\n   the name \"test\\_\" + ``NAME``.\n\n-  COLLATION\n\n   String. The collation order to use when creating the test database.\n   If the default value (``None``) is used, the test database is assigned\n   the default collation of the instance of SQL Server.\n\n-  DEPENDENCIES\n\n   String. The creation-order dependencies of the database.\n   See the official Django documentation for more details.\n\n-  MIRROR\n\n   String. The alias of the database that this database should\n   mirror during testing. Default value is ``None``.\n   See the official Django documentation for more details.\n\nOPTIONS\n~~~~~~~\n\nDictionary. Current available keys are:\n\n-  driver\n\n   String. ODBC Driver to use (``\"ODBC Driver 13 for SQL Server\"``,\n   ``\"SQL Server Native Client 11.0\"``, ``\"FreeTDS\"`` etc).\n   Default is ``\"ODBC Driver 13 for SQL Server\"``.\n\n-  isolation_level\n\n   String. Sets `transaction isolation level\n   <https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql>`__\n   for each database session. Valid values for this entry are\n   ``READ UNCOMMITTED``, ``READ COMMITTED``, ``REPEATABLE READ``,\n   ``SNAPSHOT``, and ``SERIALIZABLE``. Default is ``None`` which means\n   no isolation levei is set to a database session and SQL Server default\n   will be used.\n\n-  dsn\n\n   String. A named DSN can be used instead of ``HOST``.\n\n-  host_is_server\n\n   Boolean. Only relevant if using the FreeTDS ODBC driver under\n   Unix/Linux.\n\n   By default, when using the FreeTDS ODBC driver the value specified in\n   the ``HOST`` setting is used in a ``SERVERNAME`` ODBC connection\n   string component instead of being used in a ``SERVER`` component;\n   this means that this value should be the name of a *dataserver*\n   definition present in the ``freetds.conf`` FreeTDS configuration file\n   instead of a hostname or an IP address.\n\n   But if this option is present and its value is ``True``, this\n   special behavior is turned off. Instead, connections to the database\n   server will be established using ``HOST`` and ``PORT`` options, without\n   requiring ``freetds.conf`` to be configured.\n\n   See https://www.freetds.org/userguide/dsnless.html for more information.\n\n-  unicode_results\n\n   Boolean. If it is set to ``True``, pyodbc's *unicode_results* feature\n   is activated and strings returned from pyodbc are always Unicode.\n   Default value is ``False``.\n\n-  extra_params\n\n   String. Additional parameters for the ODBC connection. The format is\n   ``\"param=value;param=value\"``.\n\n-  collation\n\n   String. Name of the collation to use when performing text field\n   lookups against the database. Default is ``None``; this means no\n   collation specifier is added to your lookup SQL (the default\n   collation of your database will be used). For Chinese language you\n   can set it to ``\"Chinese_PRC_CI_AS\"``.\n\n-  connection_timeout\n\n   Integer. Sets the timeout in seconds for the database connection process.\n   Default value is ``0`` which disables the timeout.\n\n-  connection_retries\n\n   Integer. Sets the times to retry the database connection process.\n   Default value is ``5``.\n\n-  connection_retry_backoff_time\n\n   Integer. Sets the back off time in seconds for reries of\n   the database connection process. Default value is ``5``.\n\n-  query_timeout\n\n   Integer. Sets the timeout in seconds for the database query.\n   Default value is ``0`` which disables the timeout.\n\nbackend-specific settings\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe following project-level settings also control the behavior of the backend:\n\n-  DATABASE_CONNECTION_POOLING\n\n   Boolean. If it is set to ``False``, pyodbc's connection pooling feature\n   won't be activated.\n\nExample\n~~~~~~~\n\nHere is an example of the database settings:\n\n::\n\n    DATABASES = {\n        'default': {\n            'ENGINE': 'sql_server.pyodbc',\n            'NAME': 'mydb',\n            'USER': 'user@myserver',\n            'PASSWORD': 'password',\n            'HOST': 'myserver.database.windows.net',\n            'PORT': '',\n\n            'OPTIONS': {\n                'driver': 'ODBC Driver 13 for SQL Server',\n            },\n        },\n    }\n\n    # set this to False if you want to turn off pyodbc's connection pooling\n    DATABASE_CONNECTION_POOLING = False\n\nLimitations\n-----------\n\nThe following features are currently not supported:\n\n- Altering a model field from or to AutoField at migration\n"
  },
  {
    "path": "docker/Dockerfile",
    "content": "FROM python:3.7\n\nENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn\n\nRUN apt-get update && apt-get install -y apt-transport-https git\n\nRUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -\nRUN curl https://packages.microsoft.com/config/debian/9/prod.list > /etc/apt/sources.list.d/mssql-release.list\nRUN apt-get update\nRUN ACCEPT_EULA=Y apt-get install -y msodbcsql17 g++ unixodbc-dev\n\nADD . /code\nWORKDIR /code\nRUN pip install -e .[\"tests\"]\n\nENV PYTHONPATH=$PYTHONPATH:/code\n\nRUN git clone --branch=stable/2.2.x https://github.com/django/django.git \"/code/django\" --depth=1\n\nRUN pip install -r /code/django/tests/requirements/py3.txt\n"
  },
  {
    "path": "docker/docker-compose.yml",
    "content": "version: \"3.3\"\n\nservices:\n  app:\n    build:\n      context: ..\n      dockerfile: docker/Dockerfile\n    volumes:\n      - ..:/code\n    environment:\n      DATABASE_URL: \"mssql://SA:MyPassword42@db:1433/default?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server\"\n      DATABASE_URL_OTHER: \"mssql://SA:MyPassword42@db:1433/other?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server\"\n    depends_on:\n      - db\n\n  db:\n    image: \"mcr.microsoft.com/mssql/server:2017-latest-ubuntu\"\n    environment:\n      ACCEPT_EULA: Y\n      SA_PASSWORD: MyPassword42\n    ports:\n      - 1433:1433\n"
  },
  {
    "path": "manage.py",
    "content": "#!/usr/bin/env python\nimport os\nimport sys\n\nif __name__ == \"__main__\":\n    os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"testapp.settings\")\n\n    from django.core.management import execute_from_command_line\n\n    execute_from_command_line(sys.argv)\n"
  },
  {
    "path": "setup.cfg",
    "content": "[flake8]\nexclude = .git,__pycache__,migrations\n# W504 is mutually exclusive with W503\nignore = W504\nmax-line-length = 119\n"
  },
  {
    "path": "setup.py",
    "content": "from setuptools import find_packages, setup\n\nCLASSIFIERS = [\n    'License :: OSI Approved :: BSD License',\n    'Framework :: Django',\n    \"Operating System :: POSIX :: Linux\",\n    \"Operating System :: Microsoft :: Windows\",\n    'Programming Language :: Python',\n    'Programming Language :: Python :: 3',\n    'Programming Language :: Python :: 3.5',\n    'Programming Language :: Python :: 3.6',\n    'Programming Language :: Python :: 3.7',\n    'Framework :: Django :: 2.2',\n    'Framework :: Django :: 3.0',\n]\n\nsetup(\n    name='django-mssql-backend',\n    version='2.8.1',\n    description='Django backend for Microsoft SQL Server',\n    long_description=open('README.rst').read(),\n    author='ES Solutions AB',\n    author_email='info@essolutions.se',\n    url='https://github.com/ESSolutions/django-mssql-backend',\n    license='BSD',\n    packages=find_packages(),\n    install_requires=[\n        'pyodbc>=3.0',\n    ],\n    package_data={'sql_server.pyodbc': ['regex_clr.dll']},\n    classifiers=CLASSIFIERS,\n    keywords='django',\n)\n"
  },
  {
    "path": "sql_server/__init__.py",
    "content": ""
  },
  {
    "path": "sql_server/pyodbc/__init__.py",
    "content": "import sql_server.pyodbc.functions  # noqa\n"
  },
  {
    "path": "sql_server/pyodbc/base.py",
    "content": "\"\"\"\nMS SQL Server database backend for Django.\n\"\"\"\nimport os\nimport re\nimport time\n\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    import pyodbc as Database\nexcept ImportError as e:\n    raise ImproperlyConfigured(\"Error loading pyodbc module: %s\" % e)\n\nfrom django.utils.version import get_version_tuple  # noqa\n\npyodbc_ver = get_version_tuple(Database.version)\nif pyodbc_ver < (3, 0):\n    raise ImproperlyConfigured(\"pyodbc 3.0 or newer is required; you have %s\" % Database.version)\n\nfrom django.conf import settings  # noqa\nfrom django.db import NotSupportedError  # noqa\nfrom django.db.backends.base.base import BaseDatabaseWrapper  # noqa\nfrom django.utils.encoding import smart_str  # noqa\nfrom django.utils.functional import cached_property  # noqa\n\nif hasattr(settings, 'DATABASE_CONNECTION_POOLING'):\n    if not settings.DATABASE_CONNECTION_POOLING:\n        Database.pooling = False\n\nfrom .client import DatabaseClient  # noqa\nfrom .creation import DatabaseCreation  # noqa\nfrom .features import DatabaseFeatures  # noqa\nfrom .introspection import DatabaseIntrospection  # noqa\nfrom .operations import DatabaseOperations  # noqa\nfrom .schema import DatabaseSchemaEditor  # noqa\n\nEDITION_AZURE_SQL_DB = 5\n\n\ndef encode_connection_string(fields):\n    \"\"\"Encode dictionary of keys and values as an ODBC connection String.\n\n    See [MS-ODBCSTR] document:\n    https://msdn.microsoft.com/en-us/library/ee208909%28v=sql.105%29.aspx\n    \"\"\"\n    # As the keys are all provided by us, don't need to encode them as we know\n    # they are ok.\n    return ';'.join(\n        '%s=%s' % (k, encode_value(v))\n        for k, v in fields.items()\n    )\n\n\ndef encode_value(v):\n    \"\"\"If the value contains a semicolon, or starts with a left curly brace,\n    then enclose it in curly braces and escape all right curly braces.\n    \"\"\"\n    if ';' in v or v.strip(' ').startswith('{'):\n        return '{%s}' % (v.replace('}', '}}'),)\n    return v\n\n\nclass DatabaseWrapper(BaseDatabaseWrapper):\n    vendor = 'microsoft'\n    display_name = 'SQL Server'\n    # This dictionary maps Field objects to their associated MS SQL column\n    # types, as strings. Column-type strings can contain format strings; they'll\n    # be interpolated against the values of Field.__dict__ before being output.\n    # If a column type is set to None, it won't be included in the output.\n    data_types = {\n        'AutoField': 'int IDENTITY (1, 1)',\n        'BigAutoField': 'bigint IDENTITY (1, 1)',\n        'BigIntegerField': 'bigint',\n        'BinaryField': 'varbinary(max)',\n        'BooleanField': 'bit',\n        'CharField': 'nvarchar(%(max_length)s)',\n        'DateField': 'date',\n        'DateTimeField': 'datetime2',\n        'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',\n        'DurationField': 'bigint',\n        'FileField': 'nvarchar(%(max_length)s)',\n        'FilePathField': 'nvarchar(%(max_length)s)',\n        'FloatField': 'double precision',\n        'IntegerField': 'int',\n        'IPAddressField': 'nvarchar(15)',\n        'GenericIPAddressField': 'nvarchar(39)',\n        'NullBooleanField': 'bit',\n        'OneToOneField': 'int',\n        'PositiveIntegerField': 'int',\n        'PositiveSmallIntegerField': 'smallint',\n        'PositiveBigIntegerField': 'bigint',\n        'SlugField': 'nvarchar(%(max_length)s)',\n        'SmallAutoField': 'smallint IDENTITY (1, 1)',\n        'SmallIntegerField': 'smallint',\n        'TextField': 'nvarchar(max)',\n        'TimeField': 'time',\n        'UUIDField': 'char(32)',\n        'JSONField': 'nvarchar(max)',\n    }\n    data_type_check_constraints = {\n        'PositiveIntegerField': '[%(column)s] >= 0',\n        'PositiveSmallIntegerField': '[%(column)s] >= 0',\n    }\n    operators = {\n        # Since '=' is used not only for string comparision there is no way\n        # to make it case (in)sensitive.\n        'exact': '= %s',\n        'iexact': \"= UPPER(%s)\",\n        'contains': \"LIKE %s ESCAPE '\\\\'\",\n        'icontains': \"LIKE UPPER(%s) ESCAPE '\\\\'\",\n        'gt': '> %s',\n        'gte': '>= %s',\n        'lt': '< %s',\n        'lte': '<= %s',\n        'startswith': \"LIKE %s ESCAPE '\\\\'\",\n        'endswith': \"LIKE %s ESCAPE '\\\\'\",\n        'istartswith': \"LIKE UPPER(%s) ESCAPE '\\\\'\",\n        'iendswith': \"LIKE UPPER(%s) ESCAPE '\\\\'\",\n    }\n\n    # The patterns below are used to generate SQL pattern lookup clauses when\n    # the right-hand side of the lookup isn't a raw string (it might be an expression\n    # or the result of a bilateral transformation).\n    # In those cases, special characters for LIKE operators (e.g. \\, *, _) should be\n    # escaped on database side.\n    #\n    # Note: we use str.format() here for readability as '%' is used as a wildcard for\n    # the LIKE operator.\n    pattern_esc = r\"REPLACE(REPLACE(REPLACE({}, '\\', '[\\]'), '%%', '[%%]'), '_', '[_]')\"\n    pattern_ops = {\n        'contains': \"LIKE '%%' + {} + '%%'\",\n        'icontains': \"LIKE '%%' + UPPER({}) + '%%'\",\n        'startswith': \"LIKE {} + '%%'\",\n        'istartswith': \"LIKE UPPER({}) + '%%'\",\n        'endswith': \"LIKE '%%' + {}\",\n        'iendswith': \"LIKE '%%' + UPPER({})\",\n    }\n\n    Database = Database\n    SchemaEditorClass = DatabaseSchemaEditor\n    # Classes instantiated in __init__().\n    client_class = DatabaseClient\n    creation_class = DatabaseCreation\n    features_class = DatabaseFeatures\n    introspection_class = DatabaseIntrospection\n    ops_class = DatabaseOperations\n\n    _codes_for_networkerror = (\n        '08S01',\n        '08S02',\n    )\n    _sql_server_versions = {\n        9: 2005,\n        10: 2008,\n        11: 2012,\n        12: 2014,\n        13: 2016,\n        14: 2017,\n        15: 2019,\n    }\n\n    # https://azure.microsoft.com/en-us/documentation/articles/sql-database-develop-csharp-retry-windows/\n    _transient_error_numbers = (\n        '4060',\n        '10928',\n        '10929',\n        '40197',\n        '40501',\n        '40613',\n        '49918',\n        '49919',\n        '49920',\n    )\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n        opts = self.settings_dict[\"OPTIONS\"]\n\n        # capability for multiple result sets or cursors\n        self.supports_mars = False\n\n        # Some drivers need unicode encoded as UTF8. If this is left as\n        # None, it will be determined based on the driver, namely it'll be\n        # False if the driver is a windows driver and True otherwise.\n        #\n        # However, recent versions of FreeTDS and pyodbc (0.91 and 3.0.6 as\n        # of writing) are perfectly okay being fed unicode, which is why\n        # this option is configurable.\n        if 'driver_needs_utf8' in opts:\n            self.driver_charset = 'utf-8'\n        else:\n            self.driver_charset = opts.get('driver_charset', None)\n\n        # interval to wait for recovery from network error\n        interval = opts.get('connection_recovery_interval_msec', 0.0)\n        self.connection_recovery_interval_msec = float(interval) / 1000\n\n        # make lookup operators to be collation-sensitive if needed\n        collation = opts.get('collation', None)\n        if collation:\n            self.operators = dict(self.__class__.operators)\n            ops = {}\n            for op in self.operators:\n                sql = self.operators[op]\n                if sql.startswith('LIKE '):\n                    ops[op] = '%s COLLATE %s' % (sql, collation)\n            self.operators.update(ops)\n\n    def create_cursor(self, name=None):\n        return CursorWrapper(self.connection.cursor(), self)\n\n    def _cursor(self):\n        new_conn = False\n\n        if self.connection is None:\n            new_conn = True\n\n        conn = super()._cursor()\n        if new_conn:\n            if self.sql_server_version <= 2005:\n                self.data_types['DateField'] = 'datetime'\n                self.data_types['DateTimeField'] = 'datetime'\n                self.data_types['TimeField'] = 'datetime'\n\n        return conn\n\n    def get_connection_params(self):\n        settings_dict = self.settings_dict\n        if settings_dict['NAME'] == '':\n            raise ImproperlyConfigured(\n                \"settings.DATABASES is improperly configured. \"\n                \"Please supply the NAME value.\")\n        conn_params = settings_dict.copy()\n        if conn_params['NAME'] is None:\n            conn_params['NAME'] = 'master'\n        return conn_params\n\n    def get_new_connection(self, conn_params):\n        database = conn_params['NAME']\n        host = conn_params.get('HOST', 'localhost')\n        user = conn_params.get('USER', None)\n        password = conn_params.get('PASSWORD', None)\n        port = conn_params.get('PORT', None)\n\n        options = conn_params.get('OPTIONS', {})\n        driver = options.get('driver', 'ODBC Driver 13 for SQL Server')\n        dsn = options.get('dsn', None)\n\n        # Microsoft driver names assumed here are:\n        # * SQL Server Native Client 10.0/11.0\n        # * ODBC Driver 11/13 for SQL Server\n        ms_drivers = re.compile('^ODBC Driver .* for SQL Server$|^SQL Server Native Client')\n\n        # available ODBC connection string keywords:\n        # (Microsoft drivers for Windows)\n        # https://docs.microsoft.com/en-us/sql/relational-databases/native-client/applications/using-connection-string-keywords-with-sql-server-native-client\n        # (Microsoft drivers for Linux/Mac)\n        # https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/connection-string-keywords-and-data-source-names-dsns\n        # (FreeTDS)\n        # http://www.freetds.org/userguide/odbcconnattr.htm\n        cstr_parts = {}\n        if dsn:\n            cstr_parts['DSN'] = dsn\n        else:\n            # Only append DRIVER if DATABASE_ODBC_DSN hasn't been set\n            cstr_parts['DRIVER'] = driver\n\n            if ms_drivers.match(driver):\n                if port:\n                    host = ','.join((host, str(port)))\n                cstr_parts['SERVER'] = host\n            elif options.get('host_is_server', False):\n                if port:\n                    cstr_parts['PORT'] = str(port)\n                cstr_parts['SERVER'] = host\n            else:\n                cstr_parts['SERVERNAME'] = host\n\n        if user:\n            cstr_parts['UID'] = user\n            cstr_parts['PWD'] = password\n        else:\n            if ms_drivers.match(driver):\n                cstr_parts['Trusted_Connection'] = 'yes'\n            else:\n                cstr_parts['Integrated Security'] = 'SSPI'\n\n        cstr_parts['DATABASE'] = database\n\n        if ms_drivers.match(driver) and os.name == 'nt':\n            cstr_parts['MARS_Connection'] = 'yes'\n\n        connstr = encode_connection_string(cstr_parts)\n\n        # extra_params are glued on the end of the string without encoding,\n        # so it's up to the settings writer to make sure they're appropriate -\n        # use encode_connection_string if constructing from external input.\n        if options.get('extra_params', None):\n            connstr += ';' + options['extra_params']\n\n        unicode_results = options.get('unicode_results', False)\n        timeout = options.get('connection_timeout', 0)\n        retries = options.get('connection_retries', 5)\n        backoff_time = options.get('connection_retry_backoff_time', 5)\n        query_timeout = options.get('query_timeout', 0)\n\n        conn = None\n        retry_count = 0\n        need_to_retry = False\n        while conn is None:\n            try:\n                conn = Database.connect(connstr,\n                                        unicode_results=unicode_results,\n                                        timeout=timeout)\n            except Exception as e:\n                for error_number in self._transient_error_numbers:\n                    if error_number in e.args[1]:\n                        if error_number in e.args[1] and retry_count < retries:\n                            time.sleep(backoff_time)\n                            need_to_retry = True\n                            retry_count = retry_count + 1\n                        else:\n                            need_to_retry = False\n                        break\n                if not need_to_retry:\n                    raise\n\n        conn.timeout = query_timeout\n        return conn\n\n    def init_connection_state(self):\n        drv_name = self.connection.getinfo(Database.SQL_DRIVER_NAME).upper()\n\n        if drv_name.startswith('LIBTDSODBC'):\n            try:\n                drv_ver = self.connection.getinfo(Database.SQL_DRIVER_VER)\n                ver = get_version_tuple(drv_ver)[:2]\n                if ver < (0, 95):\n                    raise ImproperlyConfigured(\n                        \"FreeTDS 0.95 or newer is required.\")\n            except Exception:\n                # unknown driver version\n                pass\n\n        ms_drv_names = re.compile('^(LIB)?(SQLNCLI|MSODBCSQL)')\n\n        if ms_drv_names.match(drv_name):\n            self.driver_charset = None\n            # http://msdn.microsoft.com/en-us/library/ms131686.aspx\n            self.supports_mars = True\n            self.features.can_use_chunked_reads = True\n\n        settings_dict = self.settings_dict\n        cursor = self.create_cursor()\n\n        options = settings_dict.get('OPTIONS', {})\n        isolation_level = options.get('isolation_level', None)\n        if isolation_level:\n            cursor.execute('SET TRANSACTION ISOLATION LEVEL %s' % isolation_level)\n\n        # Set date format for the connection. Also, make sure Sunday is\n        # considered the first day of the week (to be consistent with the\n        # Django convention for the 'week_day' Django lookup) if the user\n        # hasn't told us otherwise\n        datefirst = options.get('datefirst', 7)\n        cursor.execute('SET DATEFORMAT ymd; SET DATEFIRST %s' % datefirst)\n\n        val = self.get_system_datetime()\n        if isinstance(val, str):\n            raise ImproperlyConfigured(\n                \"The database driver doesn't support modern datatime types.\")\n\n    def is_usable(self):\n        try:\n            self.create_cursor().execute(\"SELECT 1\")\n        except Database.Error:\n            return False\n        else:\n            return True\n\n    def get_system_datetime(self):\n        # http://blogs.msdn.com/b/sqlnativeclient/archive/2008/02/27/microsoft-sql-server-native-client-and-microsoft-sql-server-2008-native-client.aspx\n        with self.temporary_connection() as cursor:\n            if self.sql_server_version <= 2005:\n                return cursor.execute('SELECT GETDATE()').fetchone()[0]\n            else:\n                return cursor.execute('SELECT SYSDATETIME()').fetchone()[0]\n\n    @cached_property\n    def sql_server_version(self, _known_versions={}):\n        \"\"\"\n        Get the SQL server version\n\n        The _known_versions default dictionary is created on the class. This is\n        intentional - it allows us to cache this property's value across instances.\n        Therefore, when Django creates a new database connection using the same\n        alias, we won't need query the server again.\n        \"\"\"\n        if self.alias not in _known_versions:\n            with self.temporary_connection() as cursor:\n                cursor.execute(\"SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)\")\n                ver = cursor.fetchone()[0]\n                ver = int(ver.split('.')[0])\n                if ver not in self._sql_server_versions:\n                    raise NotSupportedError('SQL Server v%d is not supported.' % ver)\n                _known_versions[self.alias] = self._sql_server_versions[ver]\n        return _known_versions[self.alias]\n\n    @cached_property\n    def to_azure_sql_db(self, _known_azures={}):\n        \"\"\"\n        Whether this connection is to a Microsoft Azure database server\n\n        The _known_azures default dictionary is created on the class. This is\n        intentional - it allows us to cache this property's value across instances.\n        Therefore, when Django creates a new database connection using the same\n        alias, we won't need query the server again.\n        \"\"\"\n        if self.alias not in _known_azures:\n            with self.temporary_connection() as cursor:\n                cursor.execute(\"SELECT CAST(SERVERPROPERTY('EngineEdition') AS integer)\")\n                _known_azures[self.alias] = cursor.fetchone()[0] == EDITION_AZURE_SQL_DB\n        return _known_azures[self.alias]\n\n    def _execute_foreach(self, sql, table_names=None):\n        cursor = self.cursor()\n        if table_names is None:\n            table_names = self.introspection.table_names(cursor)\n        for table_name in table_names:\n            cursor.execute(sql % self.ops.quote_name(table_name))\n\n    def _get_trancount(self):\n        with self.connection.cursor() as cursor:\n            return cursor.execute('SELECT @@TRANCOUNT').fetchone()[0]\n\n    def _on_error(self, e):\n        if e.args[0] in self._codes_for_networkerror:\n            try:\n                # close the stale connection\n                self.close()\n                # wait a moment for recovery from network error\n                time.sleep(self.connection_recovery_interval_msec)\n            except Exception:\n                pass\n            self.connection = None\n\n    def _savepoint(self, sid):\n        with self.cursor() as cursor:\n            cursor.execute('SELECT @@TRANCOUNT')\n            trancount = cursor.fetchone()[0]\n            if trancount == 0:\n                cursor.execute(self.ops.start_transaction_sql())\n            cursor.execute(self.ops.savepoint_create_sql(sid))\n\n    def _savepoint_commit(self, sid):\n        # SQL Server has no support for partial commit in a transaction\n        pass\n\n    def _savepoint_rollback(self, sid):\n        with self.cursor() as cursor:\n            # FreeTDS requires TRANCOUNT that is greater than 0\n            cursor.execute('SELECT @@TRANCOUNT')\n            trancount = cursor.fetchone()[0]\n            if trancount > 0:\n                cursor.execute(self.ops.savepoint_rollback_sql(sid))\n\n    def _set_autocommit(self, autocommit):\n        with self.wrap_database_errors:\n            allowed = not autocommit\n            if not allowed:\n                # FreeTDS requires TRANCOUNT that is greater than 0\n                allowed = self._get_trancount() > 0\n            if allowed:\n                self.connection.autocommit = autocommit\n\n    def check_constraints(self, table_names=None):\n        self._execute_foreach('ALTER TABLE %s WITH CHECK CHECK CONSTRAINT ALL',\n                              table_names)\n\n    def disable_constraint_checking(self):\n        if not self.needs_rollback:\n            self.cursor().execute('EXEC sp_msforeachtable \"ALTER TABLE ? NOCHECK CONSTRAINT ALL\"')\n        return not self.needs_rollback\n\n    def enable_constraint_checking(self):\n        if not self.needs_rollback:\n            self.cursor().execute('EXEC sp_msforeachtable \"ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL\"')\n\n\nclass CursorWrapper(object):\n    \"\"\"\n    A wrapper around the pyodbc's cursor that takes in account a) some pyodbc\n    DB-API 2.0 implementation and b) some common ODBC driver particularities.\n    \"\"\"\n\n    def __init__(self, cursor, connection):\n        self.active = True\n        self.cursor = cursor\n        self.connection = connection\n        self.driver_charset = connection.driver_charset\n        self.last_sql = ''\n        self.last_params = ()\n\n    def close(self):\n        if self.active:\n            self.active = False\n            self.cursor.close()\n\n    def format_sql(self, sql, params):\n        if self.driver_charset and isinstance(sql, str):\n            # FreeTDS (and other ODBC drivers?) doesn't support Unicode\n            # yet, so we need to encode the SQL clause itself in utf-8\n            sql = smart_str(sql, self.driver_charset)\n\n        # pyodbc uses '?' instead of '%s' as parameter placeholder.\n        if params is not None:\n            sql = sql % tuple('?' * len(params))\n\n        return sql\n\n    def format_params(self, params):\n        fp = []\n        if params is not None:\n            for p in params:\n                if isinstance(p, str):\n                    if self.driver_charset:\n                        # FreeTDS (and other ODBC drivers?) doesn't support Unicode\n                        # yet, so we need to encode parameters in utf-8\n                        fp.append(smart_str(p, self.driver_charset))\n                    else:\n                        fp.append(p)\n\n                elif isinstance(p, bytes):\n                    fp.append(p)\n\n                elif isinstance(p, type(True)):\n                    if p:\n                        fp.append(1)\n                    else:\n                        fp.append(0)\n\n                else:\n                    fp.append(p)\n\n        return tuple(fp)\n\n    def execute(self, sql, params=None):\n        self.last_sql = sql\n        sql = self.format_sql(sql, params)\n        params = self.format_params(params)\n        self.last_params = params\n        try:\n            return self.cursor.execute(sql, params)\n        except Database.Error as e:\n            self.connection._on_error(e)\n            raise\n\n    def executemany(self, sql, params_list=()):\n        if not params_list:\n            return None\n        raw_pll = [p for p in params_list]\n        sql = self.format_sql(sql, raw_pll[0])\n        params_list = [self.format_params(p) for p in raw_pll]\n        try:\n            return self.cursor.executemany(sql, params_list)\n        except Database.Error as e:\n            self.connection._on_error(e)\n            raise\n\n    def format_rows(self, rows):\n        return list(map(self.format_row, rows))\n\n    def format_row(self, row):\n        \"\"\"\n        Decode data coming from the database if needed and convert rows to tuples\n        (pyodbc Rows are not hashable).\n        \"\"\"\n        if self.driver_charset:\n            for i in range(len(row)):\n                f = row[i]\n                # FreeTDS (and other ODBC drivers?) doesn't support Unicode\n                # yet, so we need to decode utf-8 data coming from the DB\n                if isinstance(f, bytes):\n                    row[i] = f.decode(self.driver_charset)\n        return tuple(row)\n\n    def fetchone(self):\n        row = self.cursor.fetchone()\n        if row is not None:\n            row = self.format_row(row)\n        # Any remaining rows in the current set must be discarded\n        # before changing autocommit mode when you use FreeTDS\n        if not self.connection.supports_mars:\n            self.cursor.nextset()\n        return row\n\n    def fetchmany(self, chunk):\n        return self.format_rows(self.cursor.fetchmany(chunk))\n\n    def fetchall(self):\n        return self.format_rows(self.cursor.fetchall())\n\n    def __getattr__(self, attr):\n        if attr in self.__dict__:\n            return self.__dict__[attr]\n        return getattr(self.cursor, attr)\n\n    def __iter__(self):\n        return iter(self.cursor)\n"
  },
  {
    "path": "sql_server/pyodbc/client.py",
    "content": "import re\nimport subprocess\n\nfrom django.db.backends.base.client import BaseDatabaseClient\n\n\nclass DatabaseClient(BaseDatabaseClient):\n    executable_name = 'sqlcmd'\n\n    def runshell(self):\n        settings_dict = self.connection.settings_dict\n        options = settings_dict['OPTIONS']\n        user = options.get('user', settings_dict['USER'])\n        password = options.get('passwd', settings_dict['PASSWORD'])\n\n        driver = options.get('driver', 'ODBC Driver 13 for SQL Server')\n        ms_drivers = re.compile('^ODBC Driver .* for SQL Server$|^SQL Server Native Client')\n        if not ms_drivers.match(driver):\n            self.executable_name = 'isql'\n\n        if self.executable_name == 'sqlcmd':\n            db = options.get('db', settings_dict['NAME'])\n            server = options.get('host', settings_dict['HOST'])\n            port = options.get('port', settings_dict['PORT'])\n            defaults_file = options.get('read_default_file')\n\n            args = [self.executable_name]\n            if server:\n                if port:\n                    server = ','.join((server, str(port)))\n                args += [\"-S\", server]\n            if user:\n                args += [\"-U\", user]\n                if password:\n                    args += [\"-P\", password]\n            else:\n                args += [\"-E\"]  # Try trusted connection instead\n            if db:\n                args += [\"-d\", db]\n            if defaults_file:\n                args += [\"-i\", defaults_file]\n        else:\n            dsn = options.get('dsn', '')\n            args = ['%s -v %s %s %s' % (self.executable_name, dsn, user, password)]\n\n        try:\n            subprocess.check_call(args)\n        except KeyboardInterrupt:\n            pass\n"
  },
  {
    "path": "sql_server/pyodbc/compiler.py",
    "content": "import types\nfrom itertools import chain\n\nimport django\nfrom django.db.models.aggregates import Avg, Count, StdDev, Variance\nfrom django.db.models.expressions import Ref, Subquery, Value\nfrom django.db.models.functions import (\n    Chr, ConcatPair, Greatest, Least, Length, LPad, Repeat, RPad, StrIndex, Substr, Trim\n)\nfrom django.db.models.sql import compiler\nfrom django.db.transaction import TransactionManagementError\nfrom django.db.utils import NotSupportedError\n\n\ndef _as_sql_agv(self, compiler, connection):\n    return self.as_sql(compiler, connection, template='%(function)s(CONVERT(float, %(field)s))')\n\n\ndef _as_sql_chr(self, compiler, connection):\n    return self.as_sql(compiler, connection, function='NCHAR')\n\n\ndef _as_sql_concatpair(self, compiler, connection):\n    if connection.sql_server_version < 2012:\n        node = self.coalesce()\n        return node.as_sql(compiler, connection, arg_joiner=' + ', template='%(expressions)s')\n    else:\n        return self.as_sql(compiler, connection)\n\n\ndef _as_sql_count(self, compiler, connection):\n    return self.as_sql(compiler, connection, function='COUNT_BIG')\n\n\ndef _as_sql_greatest(self, compiler, connection):\n    # SQL Server does not provide GREATEST function,\n    # so we emulate it with a table value constructor\n    # https://msdn.microsoft.com/en-us/library/dd776382.aspx\n    template = '(SELECT MAX(value) FROM (VALUES (%(expressions)s)) AS _%(function)s(value))'\n    return self.as_sql(compiler, connection, arg_joiner='), (', template=template)\n\n\ndef _as_sql_least(self, compiler, connection):\n    # SQL Server does not provide LEAST function,\n    # so we emulate it with a table value constructor\n    # https://msdn.microsoft.com/en-us/library/dd776382.aspx\n    template = '(SELECT MIN(value) FROM (VALUES (%(expressions)s)) AS _%(function)s(value))'\n    return self.as_sql(compiler, connection, arg_joiner='), (', template=template)\n\n\ndef _as_sql_length(self, compiler, connection):\n    return self.as_sql(compiler, connection, function='LEN')\n\n\ndef _as_sql_lpad(self, compiler, connection):\n    i = iter(self.get_source_expressions())\n    expression, expression_arg = compiler.compile(next(i))\n    length, length_arg = compiler.compile(next(i))\n    fill_text, fill_text_arg = compiler.compile(next(i))\n    params = []\n    params.extend(fill_text_arg)\n    params.extend(length_arg)\n    params.extend(length_arg)\n    params.extend(expression_arg)\n    params.extend(length_arg)\n    params.extend(expression_arg)\n    params.extend(expression_arg)\n    template = ('LEFT(REPLICATE(%(fill_text)s, %(length)s), CASE WHEN %(length)s > LEN(%(expression)s) '\n                'THEN %(length)s - LEN(%(expression)s) ELSE 0 END) + %(expression)s')\n    return template % {'expression': expression, 'length': length, 'fill_text': fill_text}, params\n\n\ndef _as_sql_repeat(self, compiler, connection):\n    return self.as_sql(compiler, connection, function='REPLICATE')\n\n\ndef _as_sql_rpad(self, compiler, connection):\n    i = iter(self.get_source_expressions())\n    expression, expression_arg = compiler.compile(next(i))\n    length, length_arg = compiler.compile(next(i))\n    fill_text, fill_text_arg = compiler.compile(next(i))\n    params = []\n    params.extend(expression_arg)\n    params.extend(fill_text_arg)\n    params.extend(length_arg)\n    params.extend(length_arg)\n    template = 'LEFT(%(expression)s + REPLICATE(%(fill_text)s, %(length)s), %(length)s)'\n    return template % {'expression': expression, 'length': length, 'fill_text': fill_text}, params\n\n\ndef _as_sql_stddev(self, compiler, connection):\n    function = 'STDEV'\n    if self.function == 'STDDEV_POP':\n        function = '%sP' % function\n    return self.as_sql(compiler, connection, function=function)\n\n\ndef _as_sql_strindex(self, compiler, connection):\n    self.source_expressions.reverse()\n    sql = self.as_sql(compiler, connection, function='CHARINDEX')\n    self.source_expressions.reverse()\n    return sql\n\n\ndef _as_sql_substr(self, compiler, connection):\n    if len(self.get_source_expressions()) < 3:\n        self.get_source_expressions().append(Value(2**31 - 1))\n    return self.as_sql(compiler, connection)\n\n\ndef _as_sql_trim(self, compiler, connection):\n    return self.as_sql(compiler, connection, template='LTRIM(RTRIM(%(expressions)s))')\n\n\ndef _as_sql_variance(self, compiler, connection):\n    function = 'VAR'\n    if self.function == 'VAR_POP':\n        function = '%sP' % function\n    return self.as_sql(compiler, connection, function=function)\n\n\ndef _cursor_iter(cursor, sentinel, col_count, itersize):\n    \"\"\"\n    Yields blocks of rows from a cursor and ensures the cursor is closed when\n    done.\n    \"\"\"\n    if not hasattr(cursor.db, 'supports_mars') or cursor.db.supports_mars:\n        # same as the original Django implementation\n        try:\n            for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel):\n                yield rows if col_count is None else [r[:col_count] for r in rows]\n        finally:\n            cursor.close()\n    else:\n        # retrieve all chunks from the cursor and close it before yielding\n        # so that we can open an another cursor over an iteration\n        # (for drivers such as FreeTDS)\n        chunks = []\n        try:\n            for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel):\n                chunks.append(rows if col_count is None else [r[:col_count] for r in rows])\n        finally:\n            cursor.close()\n        for rows in chunks:\n            yield rows\n\n\ncompiler.cursor_iter = _cursor_iter\n\n\nclass SQLCompiler(compiler.SQLCompiler):\n\n    def as_sql(self, with_limits=True, with_col_aliases=False):\n        \"\"\"\n        Create the SQL for this query. Return the SQL string and list of\n        parameters.\n\n        If 'with_limits' is False, any limit/offset information is not included\n        in the query.\n        \"\"\"\n        refcounts_before = self.query.alias_refcount.copy()\n        try:\n            extra_select, order_by, group_by = self.pre_sql_setup()\n            for_update_part = None\n            # Is a LIMIT/OFFSET clause needed?\n            with_limit_offset = with_limits and (self.query.high_mark is not None or self.query.low_mark)\n            combinator = self.query.combinator\n            features = self.connection.features\n\n            # The do_offset flag indicates whether we need to construct\n            # the SQL needed to use limit/offset w/SQL Server.\n            high_mark = self.query.high_mark\n            low_mark = self.query.low_mark\n            do_limit = with_limits and high_mark is not None\n            do_offset = with_limits and low_mark != 0\n            # SQL Server 2012 or newer supports OFFSET/FETCH clause\n            supports_offset_clause = self.connection.sql_server_version >= 2012\n            do_offset_emulation = do_offset and not supports_offset_clause\n\n            if combinator:\n                if not getattr(features, 'supports_select_{}'.format(combinator)):\n                    raise NotSupportedError('{} is not supported on this database backend.'.format(combinator))\n                result, params = self.get_combinator_sql(combinator, self.query.combinator_all)\n            else:\n                distinct_fields, distinct_params = self.get_distinct()\n                # This must come after 'select', 'ordering', and 'distinct' -- see\n                # docstring of get_from_clause() for details.\n                from_, f_params = self.get_from_clause()\n                where, w_params = self.compile(self.where) if self.where is not None else (\"\", [])\n                having, h_params = self.compile(self.having) if self.having is not None else (\"\", [])\n                params = []\n                result = ['SELECT']\n\n                if self.query.distinct:\n                    distinct_result, distinct_params = self.connection.ops.distinct_sql(\n                        distinct_fields,\n                        distinct_params,\n                    )\n                    result += distinct_result\n                    params += distinct_params\n\n                # SQL Server requires the keword for limitting at the begenning\n                if do_limit and not do_offset:\n                    result.append('TOP %d' % high_mark)\n\n                out_cols = []\n                col_idx = 1\n                for _, (s_sql, s_params), alias in self.select + extra_select:\n                    if alias:\n                        s_sql = '%s AS %s' % (s_sql, self.connection.ops.quote_name(alias))\n                    elif with_col_aliases or do_offset_emulation:\n                        s_sql = '%s AS %s' % (s_sql, 'Col%d' % col_idx)\n                        col_idx += 1\n                    params.extend(s_params)\n                    out_cols.append(s_sql)\n\n                # SQL Server requires an order-by clause for offsetting\n                if do_offset:\n                    meta = self.query.get_meta()\n                    qn = self.quote_name_unless_alias\n                    offsetting_order_by = '%s.%s' % (qn(meta.db_table), qn(meta.pk.db_column or meta.pk.column))\n                    if do_offset_emulation:\n                        if order_by:\n                            ordering = []\n                            for expr, (o_sql, o_params, _) in order_by:\n                                # value_expression in OVER clause cannot refer to\n                                # expressions or aliases in the select list. See:\n                                # http://msdn.microsoft.com/en-us/library/ms189461.aspx\n                                src = next(iter(expr.get_source_expressions()))\n                                if isinstance(src, Ref):\n                                    src = next(iter(src.get_source_expressions()))\n                                    o_sql, _ = src.as_sql(self, self.connection)\n                                    odir = 'DESC' if expr.descending else 'ASC'\n                                    o_sql = '%s %s' % (o_sql, odir)\n                                ordering.append(o_sql)\n                                params.extend(o_params)\n                            offsetting_order_by = ', '.join(ordering)\n                            order_by = []\n                        out_cols.append('ROW_NUMBER() OVER (ORDER BY %s) AS [rn]' % offsetting_order_by)\n                    elif not order_by:\n                        order_by.append(((None, ('%s ASC' % offsetting_order_by, [], None))))\n\n                if self.query.select_for_update and self.connection.features.has_select_for_update:\n                    if self.connection.get_autocommit():\n                        raise TransactionManagementError('select_for_update cannot be used outside of a transaction.')\n\n                    if with_limit_offset and not self.connection.features.supports_select_for_update_with_limit:\n                        raise NotSupportedError(\n                            'LIMIT/OFFSET is not supported with '\n                            'select_for_update on this database backend.'\n                        )\n                    nowait = self.query.select_for_update_nowait\n                    skip_locked = self.query.select_for_update_skip_locked\n                    of = self.query.select_for_update_of\n                    # If it's a NOWAIT/SKIP LOCKED/OF query but the backend\n                    # doesn't support it, raise NotSupportedError to prevent a\n                    # possible deadlock.\n                    if nowait and not self.connection.features.has_select_for_update_nowait:\n                        raise NotSupportedError('NOWAIT is not supported on this database backend.')\n                    elif skip_locked and not self.connection.features.has_select_for_update_skip_locked:\n                        raise NotSupportedError('SKIP LOCKED is not supported on this database backend.')\n                    elif of and not self.connection.features.has_select_for_update_of:\n                        raise NotSupportedError('FOR UPDATE OF is not supported on this database backend.')\n                    for_update_part = self.connection.ops.for_update_sql(\n                        nowait=nowait,\n                        skip_locked=skip_locked,\n                        of=self.get_select_for_update_of_arguments(),\n                    )\n\n                if for_update_part and self.connection.features.for_update_after_from:\n                    from_.insert(1, for_update_part)\n\n                result += [', '.join(out_cols), 'FROM', *from_]\n                params.extend(f_params)\n\n                if where:\n                    result.append('WHERE %s' % where)\n                    params.extend(w_params)\n\n                grouping = []\n                for g_sql, g_params in group_by:\n                    grouping.append(g_sql)\n                    params.extend(g_params)\n                if grouping:\n                    if distinct_fields:\n                        raise NotImplementedError('annotate() + distinct(fields) is not implemented.')\n                    order_by = order_by or self.connection.ops.force_no_ordering()\n                    result.append('GROUP BY %s' % ', '.join(grouping))\n\n                if having:\n                    result.append('HAVING %s' % having)\n                    params.extend(h_params)\n\n            if self.query.explain_query:\n                result.insert(0, self.connection.ops.explain_query_prefix(\n                    self.query.explain_format,\n                    **self.query.explain_options\n                ))\n\n            if order_by:\n                ordering = []\n                for _, (o_sql, o_params, _) in order_by:\n                    ordering.append(o_sql)\n                    params.extend(o_params)\n                result.append('ORDER BY %s' % ', '.join(ordering))\n\n            # SQL Server requires the backend-specific emulation (2008 or earlier)\n            # or an offset clause (2012 or newer) for offsetting\n            if do_offset:\n                if do_offset_emulation:\n                    # Construct the final SQL clause, using the initial select SQL\n                    # obtained above.\n                    result = ['SELECT * FROM (%s) AS X WHERE X.rn' % ' '.join(result)]\n                    # Place WHERE condition on `rn` for the desired range.\n                    if do_limit:\n                        result.append('BETWEEN %d AND %d' % (low_mark + 1, high_mark))\n                    else:\n                        result.append('>= %d' % (low_mark + 1))\n                    if not self.query.subquery:\n                        result.append('ORDER BY X.rn')\n                else:\n                    result.append(self.connection.ops.limit_offset_sql(self.query.low_mark, self.query.high_mark))\n\n            if self.query.subquery and extra_select:\n                # If the query is used as a subquery, the extra selects would\n                # result in more columns than the left-hand side expression is\n                # expecting. This can happen when a subquery uses a combination\n                # of order_by() and distinct(), forcing the ordering expressions\n                # to be selected as well. Wrap the query in another subquery\n                # to exclude extraneous selects.\n                sub_selects = []\n                sub_params = []\n                for index, (select, _, alias) in enumerate(self.select, start=1):\n                    if not alias and with_col_aliases:\n                        alias = 'col%d' % index\n                    if alias:\n                        sub_selects.append(\"%s.%s\" % (\n                            self.connection.ops.quote_name('subquery'),\n                            self.connection.ops.quote_name(alias),\n                        ))\n                    else:\n                        select_clone = select.relabeled_clone({select.alias: 'subquery'})\n                        subselect, subparams = select_clone.as_sql(self, self.connection)\n                        sub_selects.append(subselect)\n                        sub_params.extend(subparams)\n                return 'SELECT %s FROM (%s) subquery' % (\n                    ', '.join(sub_selects),\n                    ' '.join(result),\n                ), tuple(sub_params + params)\n\n            return ' '.join(result), tuple(params)\n        finally:\n            # Finally do cleanup - get rid of the joins we created above.\n            self.query.reset_refcounts(refcounts_before)\n\n    def compile(self, node, *args, **kwargs):\n        node = self._as_microsoft(node)\n        return super().compile(node, *args, **kwargs)\n\n    def collapse_group_by(self, expressions, having):\n        expressions = super().collapse_group_by(expressions, having)\n        return [e for e in expressions if not isinstance(e, Subquery)]\n\n    def _as_microsoft(self, node):\n        as_microsoft = None\n        if isinstance(node, Avg):\n            as_microsoft = _as_sql_agv\n        elif isinstance(node, Chr):\n            as_microsoft = _as_sql_chr\n        elif isinstance(node, ConcatPair):\n            as_microsoft = _as_sql_concatpair\n        elif isinstance(node, Count):\n            as_microsoft = _as_sql_count\n        elif isinstance(node, Greatest):\n            as_microsoft = _as_sql_greatest\n        elif isinstance(node, Least):\n            as_microsoft = _as_sql_least\n        elif isinstance(node, Length):\n            as_microsoft = _as_sql_length\n        elif isinstance(node, RPad):\n            as_microsoft = _as_sql_rpad\n        elif isinstance(node, LPad):\n            as_microsoft = _as_sql_lpad\n        elif isinstance(node, Repeat):\n            as_microsoft = _as_sql_repeat\n        elif isinstance(node, StdDev):\n            as_microsoft = _as_sql_stddev\n        elif isinstance(node, StrIndex):\n            as_microsoft = _as_sql_strindex\n        elif isinstance(node, Substr):\n            as_microsoft = _as_sql_substr\n        elif isinstance(node, Trim):\n            as_microsoft = _as_sql_trim\n        elif isinstance(node, Variance):\n            as_microsoft = _as_sql_variance\n        if as_microsoft:\n            node = node.copy()\n            node.as_microsoft = types.MethodType(as_microsoft, node)\n        return node\n\n\nclass SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler):\n    def get_returned_fields(self):\n        if django.VERSION >= (3, 0, 0):\n            return self.returning_fields\n        return self.return_id\n\n    def fix_auto(self, sql, opts, fields, qn):\n        if opts.auto_field is not None:\n            # db_column is None if not explicitly specified by model field\n            auto_field_column = opts.auto_field.db_column or opts.auto_field.column\n            columns = [f.column for f in fields]\n            if auto_field_column in columns:\n                id_insert_sql = []\n                table = qn(opts.db_table)\n                sql_format = 'SET IDENTITY_INSERT %s ON; %s; SET IDENTITY_INSERT %s OFF'\n                for q, p in sql:\n                    id_insert_sql.append((sql_format % (table, q, table), p))\n                sql = id_insert_sql\n\n        return sql\n\n    def as_sql(self):\n        # We don't need quote_name_unless_alias() here, since these are all\n        # going to be column names (so we can avoid the extra overhead).\n        qn = self.connection.ops.quote_name\n        opts = self.query.get_meta()\n        result = ['INSERT INTO %s' % qn(opts.db_table)]\n        fields = self.query.fields or [opts.pk]\n\n        if self.query.fields:\n            result.append('(%s)' % ', '.join(qn(f.column) for f in fields))\n            values_format = 'VALUES (%s)'\n            value_rows = [\n                [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]\n                for obj in self.query.objs\n            ]\n        else:\n            values_format = '%s VALUES'\n            # An empty object.\n            value_rows = [[self.connection.ops.pk_default_value()] for _ in self.query.objs]\n            fields = [None]\n\n        # Currently the backends just accept values when generating bulk\n        # queries and generate their own placeholders. Doing that isn't\n        # necessary and it should be possible to use placeholders and\n        # expressions in bulk inserts too.\n        can_bulk = (not self.get_returned_fields() and self.connection.features.has_bulk_insert) and self.query.fields\n\n        placeholder_rows, param_rows = self.assemble_as_sql(fields, value_rows)\n\n        if self.get_returned_fields() and self.connection.features.can_return_id_from_insert:\n            result.insert(0, 'SET NOCOUNT ON')\n            result.append((values_format + ';') % ', '.join(placeholder_rows[0]))\n            params = [param_rows[0]]\n            result.append('SELECT CAST(SCOPE_IDENTITY() AS bigint)')\n            sql = [(\" \".join(result), tuple(chain.from_iterable(params)))]\n        else:\n            if can_bulk:\n                result.append(self.connection.ops.bulk_insert_sql(fields, placeholder_rows))\n                sql = [(\" \".join(result), tuple(p for ps in param_rows for p in ps))]\n            else:\n                sql = [\n                    (\" \".join(result + [values_format % \", \".join(p)]), vals)\n                    for p, vals in zip(placeholder_rows, param_rows)\n                ]\n\n        if self.query.fields:\n            sql = self.fix_auto(sql, opts, fields, qn)\n\n        return sql\n\n\nclass SQLDeleteCompiler(compiler.SQLDeleteCompiler, SQLCompiler):\n    def as_sql(self):\n        sql, params = super().as_sql()\n        if sql:\n            sql = '; '.join(['SET NOCOUNT OFF', sql])\n        return sql, params\n\n\nclass SQLUpdateCompiler(compiler.SQLUpdateCompiler, SQLCompiler):\n    def as_sql(self):\n        sql, params = super().as_sql()\n        if sql:\n            sql = '; '.join(['SET NOCOUNT OFF', sql])\n        return sql, params\n\n\nclass SQLAggregateCompiler(compiler.SQLAggregateCompiler, SQLCompiler):\n    pass\n"
  },
  {
    "path": "sql_server/pyodbc/creation.py",
    "content": "import binascii\nimport os\n\nimport django\nfrom django.db.backends.base.creation import BaseDatabaseCreation\n\n\nclass DatabaseCreation(BaseDatabaseCreation):\n    @property\n    def cursor(self):\n        if django.VERSION >= (3, 1):\n            return self.connection._nodb_cursor\n\n        return self.connection._nodb_connection.cursor\n\n    def _destroy_test_db(self, test_database_name, verbosity):\n        \"\"\"\n        Internal implementation - remove the test db tables.\n        \"\"\"\n        # Remove the test database to clean up after\n        # ourselves. Connect to the previous database (not the test database)\n        # to do so, because it's not allowed to delete a database while being\n        # connected to it.\n        with self.cursor() as cursor:\n            to_azure_sql_db = self.connection.to_azure_sql_db\n            if not to_azure_sql_db:\n                cursor.execute(\"ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE\"\n                               % self.connection.ops.quote_name(test_database_name))\n            cursor.execute(\"DROP DATABASE %s\"\n                           % self.connection.ops.quote_name(test_database_name))\n\n    def sql_table_creation_suffix(self):\n        suffix = []\n        collation = self.connection.settings_dict['TEST'].get('COLLATION', None)\n        if collation:\n            suffix.append('COLLATE %s' % collation)\n        return ' '.join(suffix)\n\n    # The following code to add regex support in SQLServer is taken from django-mssql\n    # see https://bitbucket.org/Manfre/django-mssql\n    def enable_clr(self):\n        \"\"\" Enables clr for server if not already enabled\n        This function will not fail if current user doesn't have\n        permissions to enable clr, and clr is already enabled\n        \"\"\"\n        with self.cursor() as cursor:\n            # check whether clr is enabled\n            cursor.execute('''\n            SELECT value FROM sys.configurations\n            WHERE name = 'clr enabled'\n            ''')\n            res = None\n            try:\n                res = cursor.fetchone()\n            except Exception:\n                pass\n\n            if not res or not res[0]:\n                # if not enabled enable clr\n                cursor.execute(\"sp_configure 'clr enabled', 1\")\n                cursor.execute(\"RECONFIGURE\")\n\n                cursor.execute(\"sp_configure 'show advanced options', 1\")\n                cursor.execute(\"RECONFIGURE\")\n\n                cursor.execute(\"sp_configure 'clr strict security', 0\")\n                cursor.execute(\"RECONFIGURE\")\n\n    def install_regex_clr(self, database_name):\n        sql = '''\nUSE {database_name};\n-- Drop and recreate the function if it already exists\nIF OBJECT_ID('REGEXP_LIKE') IS NOT NULL\nDROP FUNCTION [dbo].[REGEXP_LIKE]\nIF EXISTS(select * from sys.assemblies where name like 'regex_clr')\nDROP ASSEMBLY regex_clr\n;\nCREATE ASSEMBLY regex_clr\nFROM 0x{assembly_hex}\nWITH PERMISSION_SET = SAFE;\ncreate function [dbo].[REGEXP_LIKE]\n(\n@input nvarchar(max),\n@pattern nvarchar(max),\n@caseSensitive int\n)\nRETURNS INT  AS\nEXTERNAL NAME regex_clr.UserDefinedFunctions.REGEXP_LIKE\n        '''.format(\n            database_name=self.connection.ops.quote_name(database_name),\n            assembly_hex=self.get_regex_clr_assembly_hex(),\n        ).split(';')\n\n        self.enable_clr()\n\n        with self.cursor() as cursor:\n            for s in sql:\n                cursor.execute(s)\n\n    def get_regex_clr_assembly_hex(self):\n        with open(os.path.join(os.path.dirname(__file__), 'regex_clr.dll'), 'rb') as f:\n            return binascii.hexlify(f.read()).decode('ascii')\n"
  },
  {
    "path": "sql_server/pyodbc/features.py",
    "content": "from django.db.backends.base.features import BaseDatabaseFeatures\nfrom django.utils.functional import cached_property\n\n\nclass DatabaseFeatures(BaseDatabaseFeatures):\n    can_introspect_json_field = False\n    has_native_json_field = False\n    has_native_uuid_field = False\n    allow_sliced_subqueries_with_in = False\n    can_introspect_autofield = True\n    can_introspect_small_integer_field = True\n    can_return_columns_from_insert = True\n    can_return_id_from_insert = True\n    can_use_chunked_reads = False\n    for_update_after_from = True\n    greatest_least_ignores_nulls = True\n    has_real_datatype = True\n    has_select_for_update = True\n    has_select_for_update_nowait = True\n    has_select_for_update_skip_locked = True\n    has_zoneinfo_database = False\n    ignores_table_name_case = True\n    ignores_quoted_identifier_case = True\n    requires_literal_defaults = True\n    requires_sqlparse_for_splitting = False\n    supports_boolean_expr_in_select_clause = False\n    supports_deferrable_unique_constraints = False\n    supports_ignore_conflicts = False\n    supports_index_on_text_field = False\n    supports_paramstyle_pyformat = False\n    supports_regex_backreferencing = True\n    supports_sequence_reset = False\n    supports_subqueries_in_group_by = False\n    supports_tablespaces = True\n    supports_temporal_subtraction = True\n    supports_timezones = False\n    supports_transactions = True\n    uses_savepoints = True\n    supports_order_by_nulls_modifier = False\n    supports_order_by_is_nulls = False\n    order_by_nulls_first = True\n\n    @cached_property\n    def has_bulk_insert(self):\n        return self.connection.sql_server_version > 2005\n\n    @cached_property\n    def supports_nullable_unique_constraints(self):\n        return self.connection.sql_server_version > 2005\n\n    @cached_property\n    def supports_partially_nullable_unique_constraints(self):\n        return self.connection.sql_server_version > 2005\n\n    @cached_property\n    def supports_partial_indexes(self):\n        return self.connection.sql_server_version > 2005\n\n    @cached_property\n    def supports_functions_in_partial_indexes(self):\n        return self.connection.sql_server_version > 2005\n\n    @cached_property\n    def introspected_field_types(self):\n        return {\n            **super().introspected_field_types,\n            'GenericIPAddressField': 'CharField',\n            'PositiveBigIntegerField': 'BigIntegerField'\n        }\n"
  },
  {
    "path": "sql_server/pyodbc/functions.py",
    "content": "from django import VERSION\nfrom django.db.models import BooleanField\nfrom django.db.models.functions import Cast\nfrom django.db.models.functions.math import ATan2, Log, Ln, Mod, Round\nfrom django.db.models.expressions import Case, Exists, OrderBy, When\nfrom django.db.models.lookups import Lookup\n\nDJANGO3 = VERSION[0] >= 3\n\n\nclass TryCast(Cast):\n    function = 'TRY_CAST'\n\n\ndef sqlserver_as_sql(self, compiler, connection, template=None, **extra_context):\n    template = template or self.template\n    if connection.features.supports_order_by_nulls_modifier:\n        if self.nulls_last:\n            template = '%s NULLS LAST' % template\n        elif self.nulls_first:\n            template = '%s NULLS FIRST' % template\n    else:\n        if self.nulls_last and not (\n            self.descending and connection.features.order_by_nulls_first\n        ) and connection.features.supports_order_by_is_nulls:\n            template = '%%(expression)s IS NULL, %s' % template\n        elif self.nulls_first and not (\n            not self.descending and connection.features.order_by_nulls_first\n        ) and connection.features.supports_order_by_is_nulls:\n            template = '%%(expression)s IS NOT NULL, %s' % template\n    connection.ops.check_expression_support(self)\n    expression_sql, params = compiler.compile(self.expression)\n    placeholders = {\n        'expression': expression_sql,\n        'ordering': 'DESC' if self.descending else 'ASC',\n        **extra_context,\n    }\n    template = template or self.template\n    params *= template.count('%(expression)s')\n    return (template % placeholders).rstrip(), params\n\n\ndef sqlserver_atan2(self, compiler, connection, **extra_context):\n    return self.as_sql(compiler, connection, function='ATN2', **extra_context)\n\n\ndef sqlserver_log(self, compiler, connection, **extra_context):\n    clone = self.copy()\n    clone.set_source_expressions(self.get_source_expressions()[::-1])\n    return clone.as_sql(compiler, connection, **extra_context)\n\n\ndef sqlserver_ln(self, compiler, connection, **extra_context):\n    return self.as_sql(compiler, connection, function='LOG', **extra_context)\n\n\ndef sqlserver_mod(self, compiler, connection, **extra_context):\n    return self.as_sql(compiler, connection, template='%(expressions)s', arg_joiner='%%', **extra_context)\n\n\ndef sqlserver_round(self, compiler, connection, **extra_context):\n    return self.as_sql(compiler, connection, template='%(function)s(%(expressions)s, 0)', **extra_context)\n\n\ndef sqlserver_exists(self, compiler, connection, template=None, **extra_context):\n    # MS SQL doesn't allow EXISTS() in the SELECT list, so wrap it with a\n    # CASE WHEN expression. Change the template since the When expression\n    # requires a left hand side (column) to compare against.\n    sql, params = self.as_sql(compiler, connection, template, **extra_context)\n    sql = 'CASE WHEN {} THEN 1 ELSE 0 END'.format(sql)\n    return sql, params\n\n\ndef sqlserver_lookup(self, compiler, connection):\n    # MSSQL doesn't allow EXISTS() to be compared to another expression\n    # unless it's wrapped in a CASE WHEN.\n    wrapped = False\n    exprs = []\n    for expr in (self.lhs, self.rhs):\n        if isinstance(expr, Exists):\n            expr = Case(When(expr, then=True), default=False, output_field=BooleanField())\n            wrapped = True\n        exprs.append(expr)\n    lookup = type(self)(*exprs) if wrapped else self\n    return lookup.as_sql(compiler, connection)\n\n\ndef sqlserver_orderby(self, compiler, connection):\n    # MSSQL doesn't allow ORDER BY EXISTS() unless it's wrapped in\n    # a CASE WHEN.\n\n    template = None\n    if self.nulls_last:\n        template = 'CASE WHEN %(expression)s IS NULL THEN 1 ELSE 0 END, %(expression)s %(ordering)s'\n    if self.nulls_first:\n        template = 'CASE WHEN %(expression)s IS NULL THEN 0 ELSE 1 END, %(expression)s %(ordering)s'\n\n    if isinstance(self.expression, Exists):\n        copy = self.copy()\n        copy.expression = Case(\n            When(self.expression, then=True),\n            default=False,\n            output_field=BooleanField(),\n        )\n        return copy.as_sql(compiler, connection, template=template)\n    return self.as_sql(compiler, connection, template=template)\n\n\nATan2.as_microsoft = sqlserver_atan2\nLog.as_microsoft = sqlserver_log\nLn.as_microsoft = sqlserver_ln\nMod.as_microsoft = sqlserver_mod\nRound.as_microsoft = sqlserver_round\n\nif DJANGO3:\n    Lookup.as_microsoft = sqlserver_lookup\nelse:\n    Exists.as_microsoft = sqlserver_exists\n\nOrderBy.as_microsoft = sqlserver_orderby\nOrderBy.as_sql = sqlserver_as_sql\n"
  },
  {
    "path": "sql_server/pyodbc/introspection.py",
    "content": "import pyodbc as Database\nfrom collections import namedtuple\n\nfrom django.db.backends.base.introspection import (\n    BaseDatabaseIntrospection, TableInfo,\n)\nfrom django.db.models.indexes import Index\n\nSQL_AUTOFIELD = -777555\nSQL_BIGAUTOFIELD = -777444\n\nFieldInfo = namedtuple('FieldInfo', 'name type_code display_size internal_size precision scale null_ok default')\n\n\nclass DatabaseIntrospection(BaseDatabaseIntrospection):\n    # Map type codes to Django Field types.\n    data_types_reverse = {\n        SQL_AUTOFIELD: 'AutoField',\n        SQL_BIGAUTOFIELD: 'BigAutoField',\n        Database.SQL_BIGINT: 'BigIntegerField',\n        # Database.SQL_BINARY:            ,\n        Database.SQL_BIT: 'BooleanField',\n        Database.SQL_CHAR: 'CharField',\n        Database.SQL_DECIMAL: 'DecimalField',\n        Database.SQL_DOUBLE: 'FloatField',\n        Database.SQL_FLOAT: 'FloatField',\n        Database.SQL_GUID: 'TextField',\n        Database.SQL_INTEGER: 'IntegerField',\n        Database.SQL_LONGVARBINARY: 'BinaryField',\n        # Database.SQL_LONGVARCHAR:       ,\n        Database.SQL_NUMERIC: 'DecimalField',\n        Database.SQL_REAL: 'FloatField',\n        Database.SQL_SMALLINT: 'SmallIntegerField',\n        Database.SQL_SS_TIME2: 'TimeField',\n        Database.SQL_TINYINT: 'SmallIntegerField',\n        Database.SQL_TYPE_DATE: 'DateField',\n        Database.SQL_TYPE_TIME: 'TimeField',\n        Database.SQL_TYPE_TIMESTAMP: 'DateTimeField',\n        Database.SQL_VARBINARY: 'BinaryField',\n        Database.SQL_VARCHAR: 'TextField',\n        Database.SQL_WCHAR: 'CharField',\n        Database.SQL_WLONGVARCHAR: 'TextField',\n        Database.SQL_WVARCHAR: 'TextField',\n    }\n\n    ignored_tables = []\n\n    def get_field_type(self, data_type, description):\n        field_type = super().get_field_type(data_type, description)\n        # the max nvarchar length is described as 0 or 2**30-1\n        # (it depends on the driver)\n        size = description.internal_size\n        if field_type == 'CharField':\n            if size == 0 or size >= 2**30 - 1:\n                field_type = \"TextField\"\n        elif field_type == 'TextField':\n            if size > 0 and size < 2**30 - 1:\n                field_type = 'CharField'\n        return field_type\n\n    def get_table_list(self, cursor):\n        \"\"\"\n        Returns a list of table and view names in the current database.\n        \"\"\"\n        sql = 'SELECT TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = SCHEMA_NAME()'\n        cursor.execute(sql)\n        types = {'BASE TABLE': 't', 'VIEW': 'v'}\n        return [TableInfo(row[0], types.get(row[1]))\n                for row in cursor.fetchall()\n                if row[0] not in self.ignored_tables]\n\n    def _is_auto_field(self, cursor, table_name, column_name):\n        \"\"\"\n        Checks whether column is Identity\n        \"\"\"\n        # COLUMNPROPERTY: http://msdn2.microsoft.com/en-us/library/ms174968.aspx\n\n        # from django.db import connection\n        # cursor.execute(\"SELECT COLUMNPROPERTY(OBJECT_ID(%s), %s, 'IsIdentity')\",\n        #                 (connection.ops.quote_name(table_name), column_name))\n        cursor.execute(\"SELECT COLUMNPROPERTY(OBJECT_ID(%s), %s, 'IsIdentity')\",\n                       (self.connection.ops.quote_name(table_name), column_name))\n        return cursor.fetchall()[0][0]\n\n    def get_table_description(self, cursor, table_name, identity_check=True):\n        \"\"\"Returns a description of the table, with DB-API cursor.description interface.\n\n        The 'auto_check' parameter has been added to the function argspec.\n        If set to True, the function will check each of the table's fields for the\n        IDENTITY property (the IDENTITY property is the MSSQL equivalent to an AutoField).\n\n        When an integer field is found with an IDENTITY property, it is given a custom field number\n        of SQL_AUTOFIELD, which maps to the 'AutoField' value in the DATA_TYPES_REVERSE dict.\n\n        When a bigint field is found with an IDENTITY property, it is given a custom field number\n        of SQL_BIGAUTOFIELD, which maps to the 'BigAutoField' value in the DATA_TYPES_REVERSE dict.\n        \"\"\"\n\n        # map pyodbc's cursor.columns to db-api cursor description\n        columns = [[c[3], c[4], None, c[6], c[6], c[8], c[10], c[12]] for c in cursor.columns(table=table_name)]\n        items = []\n        for column in columns:\n            if identity_check and self._is_auto_field(cursor, table_name, column[0]):\n                if column[1] == Database.SQL_BIGINT:\n                    column[1] = SQL_BIGAUTOFIELD\n                else:\n                    column[1] = SQL_AUTOFIELD\n            if column[1] == Database.SQL_WVARCHAR and column[3] < 4000:\n                column[1] = Database.SQL_WCHAR\n            items.append(FieldInfo(*column))\n        return items\n\n    def get_sequences(self, cursor, table_name, table_fields=()):\n        cursor.execute(\"\"\"\n            SELECT c.name FROM sys.columns c\n            INNER JOIN sys.tables t ON c.object_id = t.object_id\n            WHERE t.schema_id = SCHEMA_ID() AND t.name = %s AND c.is_identity = 1\"\"\",\n                       [table_name])\n        # SQL Server allows only one identity column per table\n        # https://docs.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property\n        row = cursor.fetchone()\n        return [{'table': table_name, 'column': row[0]}] if row else []\n\n    def get_relations(self, cursor, table_name):\n        \"\"\"\n        Returns a dictionary of {field_name: (field_name_other_table, other_table)}\n        representing all relationships to the given table.\n        \"\"\"\n        # CONSTRAINT_COLUMN_USAGE: http://msdn2.microsoft.com/en-us/library/ms174431.aspx\n        # CONSTRAINT_TABLE_USAGE:  http://msdn2.microsoft.com/en-us/library/ms179883.aspx\n        # REFERENTIAL_CONSTRAINTS: http://msdn2.microsoft.com/en-us/library/ms179987.aspx\n        # TABLE_CONSTRAINTS:       http://msdn2.microsoft.com/en-us/library/ms181757.aspx\n\n        sql = \"\"\"\nSELECT e.COLUMN_NAME AS column_name,\n  c.TABLE_NAME AS referenced_table_name,\n  d.COLUMN_NAME AS referenced_column_name\nFROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a\nINNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS b\n  ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME AND a.TABLE_SCHEMA = b.CONSTRAINT_SCHEMA\nINNER JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS c\n  ON b.UNIQUE_CONSTRAINT_NAME = c.CONSTRAINT_NAME AND b.CONSTRAINT_SCHEMA = c.CONSTRAINT_SCHEMA\nINNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS d\n  ON c.CONSTRAINT_NAME = d.CONSTRAINT_NAME AND c.CONSTRAINT_SCHEMA = d.CONSTRAINT_SCHEMA\nINNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS e\n  ON a.CONSTRAINT_NAME = e.CONSTRAINT_NAME AND a.TABLE_SCHEMA = e.TABLE_SCHEMA\nWHERE a.TABLE_SCHEMA = SCHEMA_NAME() AND a.TABLE_NAME = %s AND a.CONSTRAINT_TYPE = 'FOREIGN KEY'\"\"\"\n        cursor.execute(sql, (table_name,))\n        return dict([[item[0], (item[2], item[1])] for item in cursor.fetchall()])\n\n    def get_key_columns(self, cursor, table_name):\n        \"\"\"\n        Returns a list of (column_name, referenced_table_name, referenced_column_name) for all\n        key columns in given table.\n        \"\"\"\n        key_columns = []\n        cursor.execute(\"\"\"\n            SELECT c.name AS column_name, rt.name AS referenced_table_name, rc.name AS referenced_column_name\n            FROM sys.foreign_key_columns fk\n            INNER JOIN sys.tables t ON t.object_id = fk.parent_object_id\n            INNER JOIN sys.columns c ON c.object_id = t.object_id AND c.column_id = fk.parent_column_id\n            INNER JOIN sys.tables rt ON rt.object_id = fk.referenced_object_id\n            INNER JOIN sys.columns rc ON rc.object_id = rt.object_id AND rc.column_id = fk.referenced_column_id\n            WHERE t.schema_id = SCHEMA_ID() AND t.name = %s\"\"\", [table_name])\n        key_columns.extend([tuple(row) for row in cursor.fetchall()])\n        return key_columns\n\n    def get_constraints(self, cursor, table_name):\n        \"\"\"\n        Retrieves any constraints or keys (unique, pk, fk, check, index)\n        across one or more columns.\n\n        Returns a dict mapping constraint names to their attributes,\n        where attributes is a dict with keys:\n         * columns: List of columns this covers\n         * primary_key: True if primary key, False otherwise\n         * unique: True if this is a unique constraint, False otherwise\n         * foreign_key: (table, column) of target, or None\n         * check: True if check constraint, False otherwise\n         * index: True if index, False otherwise.\n         * orders: The order (ASC/DESC) defined for the columns of indexes\n         * type: The type of the index (btree, hash, etc.)\n        \"\"\"\n        constraints = {}\n        # Loop over the key table, collecting things as constraints\n        # This will get PKs, FKs, and uniques, but not CHECK\n        cursor.execute(\"\"\"\n            SELECT\n                kc.constraint_name,\n                kc.column_name,\n                tc.constraint_type,\n                fk.referenced_table_name,\n                fk.referenced_column_name\n            FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kc\n            INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc ON\n                kc.table_schema = tc.table_schema AND\n                kc.table_name = tc.table_name AND\n                kc.constraint_name = tc.constraint_name\n            LEFT OUTER JOIN (\n                SELECT\n                    ps.name AS table_schema,\n                    pt.name AS table_name,\n                    pc.name AS column_name,\n                    rt.name AS referenced_table_name,\n                    rc.name AS referenced_column_name\n                FROM\n                    sys.foreign_key_columns fkc\n                INNER JOIN sys.tables pt ON\n                    fkc.parent_object_id = pt.object_id\n                INNER JOIN sys.schemas ps ON\n                    pt.schema_id = ps.schema_id\n                INNER JOIN sys.columns pc ON\n                    fkc.parent_object_id = pc.object_id AND\n                    fkc.parent_column_id = pc.column_id\n                INNER JOIN sys.tables rt ON\n                    fkc.referenced_object_id = rt.object_id\n                INNER JOIN sys.schemas rs ON\n                    rt.schema_id = rs.schema_id\n                INNER JOIN sys.columns rc ON\n                    fkc.referenced_object_id = rc.object_id AND\n                    fkc.referenced_column_id = rc.column_id\n            ) fk ON\n                kc.table_schema = fk.table_schema AND\n                kc.table_name = fk.table_name AND\n                kc.column_name = fk.column_name\n            WHERE\n                kc.table_schema = SCHEMA_NAME() AND\n                kc.table_name = %s\n            ORDER BY\n                kc.constraint_name ASC,\n                kc.ordinal_position ASC\n        \"\"\", [table_name])\n        for constraint, column, kind, ref_table, ref_column in cursor.fetchall():\n            # If we're the first column, make the record\n            if constraint not in constraints:\n                constraints[constraint] = {\n                    \"columns\": [],\n                    \"primary_key\": kind.lower() == \"primary key\",\n                    \"unique\": kind.lower() in [\"primary key\", \"unique\"],\n                    \"foreign_key\": (ref_table, ref_column) if kind.lower() == \"foreign key\" else None,\n                    \"check\": False,\n                    \"index\": False,\n                }\n            # Record the details\n            constraints[constraint]['columns'].append(column)\n        # Now get CHECK constraint columns\n        cursor.execute(\"\"\"\n            SELECT kc.constraint_name, kc.column_name\n            FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS kc\n            JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS c ON\n                kc.table_schema = c.table_schema AND\n                kc.table_name = c.table_name AND\n                kc.constraint_name = c.constraint_name\n            WHERE\n                c.constraint_type = 'CHECK' AND\n                kc.table_schema = SCHEMA_NAME() AND\n                kc.table_name = %s\n        \"\"\", [table_name])\n        for constraint, column in cursor.fetchall():\n            # If we're the first column, make the record\n            if constraint not in constraints:\n                constraints[constraint] = {\n                    \"columns\": [],\n                    \"primary_key\": False,\n                    \"unique\": False,\n                    \"foreign_key\": None,\n                    \"check\": True,\n                    \"index\": False,\n                }\n            # Record the details\n            constraints[constraint]['columns'].append(column)\n        # Now get indexes\n        cursor.execute(\"\"\"\n            SELECT\n                i.name AS index_name,\n                i.is_unique,\n                i.is_primary_key,\n                i.type,\n                i.type_desc,\n                ic.is_descending_key,\n                c.name AS column_name\n            FROM\n                sys.tables AS t\n            INNER JOIN sys.schemas AS s ON\n                t.schema_id = s.schema_id\n            INNER JOIN sys.indexes AS i ON\n                t.object_id = i.object_id\n            INNER JOIN sys.index_columns AS ic ON\n                i.object_id = ic.object_id AND\n                i.index_id = ic.index_id\n            INNER JOIN sys.columns AS c ON\n                ic.object_id = c.object_id AND\n                ic.column_id = c.column_id\n            WHERE\n                t.schema_id = SCHEMA_ID() AND\n                t.name = %s\n            ORDER BY\n                i.index_id ASC,\n                ic.index_column_id ASC\n        \"\"\", [table_name])\n        indexes = {}\n        for index, unique, primary, type_, desc, order, column in cursor.fetchall():\n            if index not in indexes:\n                indexes[index] = {\n                    \"columns\": [],\n                    \"primary_key\": primary,\n                    \"unique\": unique,\n                    \"foreign_key\": None,\n                    \"check\": False,\n                    \"index\": True,\n                    \"orders\": [],\n                    \"type\": Index.suffix if type_ in (1, 2) else desc.lower(),\n                }\n            indexes[index][\"columns\"].append(column)\n            indexes[index][\"orders\"].append(\"DESC\" if order == 1 else \"ASC\")\n        for index, constraint in indexes.items():\n            if index not in constraints:\n                constraints[index] = constraint\n        return constraints\n"
  },
  {
    "path": "sql_server/pyodbc/management/__init__.py",
    "content": ""
  },
  {
    "path": "sql_server/pyodbc/management/commands/__init__.py",
    "content": ""
  },
  {
    "path": "sql_server/pyodbc/management/commands/install_regex_clr.py",
    "content": "# Add regex support in SQLServer\n# Code taken from django-mssql (see https://bitbucket.org/Manfre/django-mssql)\n\nfrom django.core.management.base import BaseCommand\nfrom django.db import connection\n\n\nclass Command(BaseCommand):\n    help = \"Installs the regex_clr.dll assembly with the database\"\n\n    requires_model_validation = False\n\n    args = 'database_name'\n\n    def add_arguments(self, parser):\n        parser.add_argument('database_name')\n\n    def handle(self, *args, **options):\n        database_name = options['database_name']\n        if not database_name:\n            self.print_help('manage.py', 'install_regex_clr')\n            return\n\n        connection.creation.install_regex_clr(database_name)\n        print('Installed regex_clr to database %s' % database_name)\n"
  },
  {
    "path": "sql_server/pyodbc/operations.py",
    "content": "import datetime\nimport uuid\nimport warnings\nimport django\n\nfrom django.conf import settings\nfrom django.db.backends.base.operations import BaseDatabaseOperations\nfrom django.db.models import Exists, ExpressionWrapper\nfrom django.db.models.expressions import RawSQL\nfrom django.db.models.sql.where import WhereNode\nfrom django.utils import timezone\nfrom django.utils.encoding import force_str\n\nimport pytz\n\n\nclass DatabaseOperations(BaseDatabaseOperations):\n    compiler_module = 'sql_server.pyodbc.compiler'\n\n    cast_char_field_without_max_length = 'nvarchar(max)'\n\n    def _convert_field_to_tz(self, field_name, tzname):\n        if settings.USE_TZ and not tzname == 'UTC':\n            offset = self._get_utcoffset(tzname)\n            field_name = 'DATEADD(second, %d, %s)' % (offset, field_name)\n        return field_name\n\n    def _get_utcoffset(self, tzname):\n        \"\"\"\n        Returns UTC offset for given time zone in seconds\n        \"\"\"\n        # SQL Server has no built-in support for tz database, see:\n        # http://blogs.msdn.com/b/sqlprogrammability/archive/2008/03/18/using-time-zone-data-in-sql-server-2008.aspx\n        zone = pytz.timezone(tzname)\n        # no way to take DST into account at this point\n        now = datetime.datetime.now()\n        delta = zone.localize(now, is_dst=False).utcoffset()\n        return delta.days * 86400 + delta.seconds\n\n    def bulk_batch_size(self, fields, objs):\n        \"\"\"\n        Returns the maximum allowed batch size for the backend. The fields\n        are the fields going to be inserted in the batch, the objs contains\n        all the objects to be inserted.\n        \"\"\"\n        objs_len, fields_len, max_row_values = len(objs), len(fields), 1000\n        if (objs_len * fields_len) <= max_row_values:\n            size = objs_len\n        else:\n            size = max_row_values // fields_len\n        return size\n\n    def bulk_insert_sql(self, fields, placeholder_rows):\n        placeholder_rows_sql = (\", \".join(row) for row in placeholder_rows)\n        values_sql = \", \".join(\"(%s)\" % sql for sql in placeholder_rows_sql)\n        return \"VALUES \" + values_sql\n\n    def cache_key_culling_sql(self):\n        \"\"\"\n        Returns a SQL query that retrieves the first cache key greater than the\n        smallest.\n\n        This is used by the 'db' cache backend to determine where to start\n        culling.\n        \"\"\"\n        return \"SELECT cache_key FROM (SELECT cache_key, \" \\\n               \"ROW_NUMBER() OVER (ORDER BY cache_key) AS rn FROM %s\" \\\n               \") cache WHERE rn = %%s + 1\"\n\n    def combine_duration_expression(self, connector, sub_expressions):\n        lhs, rhs = sub_expressions\n        sign = ' * -1' if connector == '-' else ''\n        if lhs.startswith('DATEADD'):\n            col, sql = rhs, lhs\n        else:\n            col, sql = lhs, rhs\n        params = [sign for _ in range(sql.count('DATEADD'))]\n        params.append(col)\n        return sql % tuple(params)\n\n    def combine_expression(self, connector, sub_expressions):\n        \"\"\"\n        SQL Server requires special cases for some operators in query expressions\n        \"\"\"\n        if connector == '^':\n            return 'POWER(%s)' % ','.join(sub_expressions)\n        elif connector == '<<':\n            return '%s * (2 * %s)' % tuple(sub_expressions)\n        elif connector == '>>':\n            return '%s / (2 * %s)' % tuple(sub_expressions)\n        return super().combine_expression(connector, sub_expressions)\n\n    def convert_datetimefield_value(self, value, expression, connection):\n        if value is not None:\n            if settings.USE_TZ:\n                value = timezone.make_aware(value, self.connection.timezone)\n        return value\n\n    def convert_floatfield_value(self, value, expression, connection):\n        if value is not None:\n            value = float(value)\n        return value\n\n    def convert_uuidfield_value(self, value, expression, connection):\n        if value is not None:\n            value = uuid.UUID(value)\n        return value\n\n    def convert_booleanfield_value(self, value, expression, connection):\n        return bool(value) if value in (0, 1) else value\n\n    def date_extract_sql(self, lookup_type, field_name):\n        if lookup_type == 'week_day':\n            return \"DATEPART(weekday, %s)\" % field_name\n        elif lookup_type == 'week':\n            return \"DATEPART(iso_week, %s)\" % field_name\n        elif lookup_type == 'iso_year':\n            return \"YEAR(DATEADD(day, 26 - DATEPART(isoww, %s), %s))\" % (field_name, field_name)\n        else:\n            return \"DATEPART(%s, %s)\" % (lookup_type, field_name)\n\n    def date_interval_sql(self, timedelta):\n        \"\"\"\n        implements the interval functionality for expressions\n        \"\"\"\n        sec = timedelta.seconds + timedelta.days * 86400\n        sql = 'DATEADD(second, %d%%s, CAST(%%s AS datetime2))' % sec\n        if timedelta.microseconds:\n            sql = 'DATEADD(microsecond, %d%%s, CAST(%s AS datetime2))' % (timedelta.microseconds, sql)\n        return sql\n\n    def date_trunc_sql(self, lookup_type, field_name):\n        CONVERT_YEAR = 'CONVERT(varchar, DATEPART(year, %s))' % field_name\n        CONVERT_QUARTER = 'CONVERT(varchar, 1+((DATEPART(quarter, %s)-1)*3))' % field_name\n        CONVERT_MONTH = 'CONVERT(varchar, DATEPART(month, %s))' % field_name\n\n        if lookup_type == 'year':\n            return \"CONVERT(datetime2, %s + '/01/01')\" % CONVERT_YEAR\n        if lookup_type == 'quarter':\n            return \"CONVERT(datetime2, %s + '/' + %s + '/01')\" % (CONVERT_YEAR, CONVERT_QUARTER)\n        if lookup_type == 'month':\n            return \"CONVERT(datetime2, %s + '/' + %s + '/01')\" % (CONVERT_YEAR, CONVERT_MONTH)\n        if lookup_type == 'week':\n            CONVERT = \"CONVERT(datetime2, CONVERT(varchar(12), %s, 112))\" % field_name\n            return \"DATEADD(DAY, (DATEPART(weekday, %s) + 5) %%%% 7 * -1, %s)\" % (CONVERT, field_name)\n        if lookup_type == 'day':\n            return \"CONVERT(datetime2, CONVERT(varchar(12), %s, 112))\" % field_name\n\n    def datetime_cast_date_sql(self, field_name, tzname):\n        field_name = self._convert_field_to_tz(field_name, tzname)\n        sql = 'CAST(%s AS date)' % field_name\n        return sql\n\n    def datetime_cast_time_sql(self, field_name, tzname):\n        field_name = self._convert_field_to_tz(field_name, tzname)\n        sql = 'CAST(%s AS time)' % field_name\n        return sql\n\n    def datetime_extract_sql(self, lookup_type, field_name, tzname):\n        field_name = self._convert_field_to_tz(field_name, tzname)\n        return self.date_extract_sql(lookup_type, field_name)\n\n    def datetime_trunc_sql(self, lookup_type, field_name, tzname):\n        field_name = self._convert_field_to_tz(field_name, tzname)\n        sql = ''\n        if lookup_type in ('year', 'quarter', 'month', 'week', 'day'):\n            sql = self.date_trunc_sql(lookup_type, field_name)\n        elif lookup_type == 'hour':\n            sql = \"CONVERT(datetime2, SUBSTRING(CONVERT(varchar, %s, 20), 0, 14) + ':00:00')\" % field_name\n        elif lookup_type == 'minute':\n            sql = \"CONVERT(datetime2, SUBSTRING(CONVERT(varchar, %s, 20), 0, 17) + ':00')\" % field_name\n        elif lookup_type == 'second':\n            sql = \"CONVERT(datetime2, CONVERT(varchar, %s, 20))\" % field_name\n        return sql\n\n    def for_update_sql(self, nowait=False, skip_locked=False, of=()):\n        if skip_locked:\n            return 'WITH (ROWLOCK, UPDLOCK, READPAST)'\n        elif nowait:\n            return 'WITH (NOWAIT, ROWLOCK, UPDLOCK)'\n        else:\n            return 'WITH (ROWLOCK, UPDLOCK)'\n\n    def format_for_duration_arithmetic(self, sql):\n        if sql == '%s':\n            # use DATEADD only once because Django prepares only one parameter for this\n            fmt = 'DATEADD(second, %s / 1000000%%s, CAST(%%s AS datetime2))'\n            sql = '%%s'\n        else:\n            # use DATEADD twice to avoid arithmetic overflow for number part\n            MICROSECOND = \"DATEADD(microsecond, %s %%%%%%%% 1000000%%s, CAST(%%s AS datetime2))\"\n            fmt = 'DATEADD(second, %s / 1000000%%s, {})'.format(MICROSECOND)\n            sql = (sql, sql)\n        return fmt % sql\n\n    def fulltext_search_sql(self, field_name):\n        \"\"\"\n        Returns the SQL WHERE clause to use in order to perform a full-text\n        search of the given field_name. Note that the resulting string should\n        contain a '%s' placeholder for the value being searched against.\n        \"\"\"\n        return 'CONTAINS(%s, %%s)' % field_name\n\n    def get_db_converters(self, expression):\n        converters = super().get_db_converters(expression)\n        internal_type = expression.output_field.get_internal_type()\n        if internal_type == 'DateTimeField':\n            converters.append(self.convert_datetimefield_value)\n        elif internal_type == 'FloatField':\n            converters.append(self.convert_floatfield_value)\n        elif internal_type == 'UUIDField':\n            converters.append(self.convert_uuidfield_value)\n        elif internal_type in ('BooleanField', 'NullBooleanField'):\n            converters.append(self.convert_booleanfield_value)\n        return converters\n\n    def last_insert_id(self, cursor, table_name, pk_name):\n        \"\"\"\n        Given a cursor object that has just performed an INSERT statement into\n        a table that has an auto-incrementing ID, returns the newly created ID.\n\n        This method also receives the table name and the name of the primary-key\n        column.\n        \"\"\"\n        # TODO: Check how the `last_insert_id` is being used in the upper layers\n        #       in context of multithreaded access, compare with other backends\n\n        # IDENT_CURRENT:  http://msdn2.microsoft.com/en-us/library/ms175098.aspx\n        # SCOPE_IDENTITY: http://msdn2.microsoft.com/en-us/library/ms190315.aspx\n        # @@IDENTITY:     http://msdn2.microsoft.com/en-us/library/ms187342.aspx\n\n        # IDENT_CURRENT is not limited by scope and session; it is limited to\n        # a specified table. IDENT_CURRENT returns the value generated for\n        # a specific table in any session and any scope.\n        # SCOPE_IDENTITY and @@IDENTITY return the last identity values that\n        # are generated in any table in the current session. However,\n        # SCOPE_IDENTITY returns values inserted only within the current scope;\n        # @@IDENTITY is not limited to a specific scope.\n\n        table_name = self.quote_name(table_name)\n        cursor.execute(\"SELECT CAST(IDENT_CURRENT(%s) AS int)\", [table_name])\n        return cursor.fetchone()[0]\n\n    def lookup_cast(self, lookup_type, internal_type=None):\n        if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith'):\n            return \"UPPER(%s)\"\n        return \"%s\"\n\n    def max_name_length(self):\n        return 128\n\n    def no_limit_value(self):\n        return None\n\n    def prepare_sql_script(self, sql, _allow_fallback=False):\n        return [sql]\n\n    def quote_name(self, name):\n        \"\"\"\n        Returns a quoted version of the given table, index or column name. Does\n        not quote the given name if it's already been quoted.\n        \"\"\"\n        if name.startswith('[') and name.endswith(']'):\n            return name  # Quoting once is enough.\n        return '[%s]' % name\n\n    def random_function_sql(self):\n        \"\"\"\n        Returns a SQL expression that returns a random value.\n        \"\"\"\n        return \"RAND()\"\n\n    def regex_lookup(self, lookup_type):\n        \"\"\"\n        Returns the string to use in a query when performing regular expression\n        lookups (using \"regex\" or \"iregex\"). The resulting string should\n        contain a '%s' placeholder for the column being searched against.\n\n        If the feature is not supported (or part of it is not supported), a\n        NotImplementedError exception can be raised.\n        \"\"\"\n        match_option = {'iregex': 0, 'regex': 1}[lookup_type]\n        return \"dbo.REGEXP_LIKE(%%s, %%s, %s)=1\" % (match_option,)\n\n    def limit_offset_sql(self, low_mark, high_mark):\n        \"\"\"Return LIMIT/OFFSET SQL clause.\"\"\"\n        limit, offset = self._get_limit_offset_params(low_mark, high_mark)\n        return '%s%s' % (\n            (' OFFSET %d ROWS' % offset) if offset else '',\n            (' FETCH FIRST %d ROWS ONLY' % limit) if limit else '',\n        )\n\n    def last_executed_query(self, cursor, sql, params):\n        \"\"\"\n        Returns a string of the query last executed by the given cursor, with\n        placeholders replaced with actual values.\n\n        `sql` is the raw query containing placeholders, and `params` is the\n        sequence of parameters. These are used by default, but this method\n        exists for database backends to provide a better implementation\n        according to their own quoting schemes.\n        \"\"\"\n        return super().last_executed_query(cursor, cursor.last_sql, cursor.last_params)\n\n    def savepoint_create_sql(self, sid):\n        \"\"\"\n        Returns the SQL for starting a new savepoint. Only required if the\n        \"uses_savepoints\" feature is True. The \"sid\" parameter is a string\n        for the savepoint id.\n        \"\"\"\n        return \"SAVE TRANSACTION %s\" % sid\n\n    def savepoint_rollback_sql(self, sid):\n        \"\"\"\n        Returns the SQL for rolling back the given savepoint.\n        \"\"\"\n        return \"ROLLBACK TRANSACTION %s\" % sid\n\n    def _build_sequences(self, sequences, cursor):\n        seqs = []\n        for seq in sequences:\n            cursor.execute(\"SELECT COUNT(*) FROM %s\" % self.quote_name(seq[\"table\"]))\n            rowcnt = cursor.fetchone()[0]\n            elem = {}\n            if rowcnt:\n                elem['start_id'] = 0\n            else:\n                elem['start_id'] = 1\n            elem.update(seq)\n            seqs.append(elem)\n        return seqs\n\n    def _sql_flush_new(self, style, tables, *, reset_sequences=False, allow_cascade=False):\n        if reset_sequences:\n            return [\n                sequence\n                for sequence in self.connection.introspection.sequence_list()\n            ]\n\n        return []\n\n    def _sql_flush_old(self, style, tables, sequences, allow_cascade=False):\n        return sequences\n\n    def sql_flush(self, style, tables, *args, **kwargs):\n        \"\"\"\n        Returns a list of SQL statements required to remove all data from\n        the given database tables (without actually removing the tables\n        themselves).\n\n        The returned value also includes SQL statements required to reset DB\n        sequences passed in :param sequences:.\n\n        The `style` argument is a Style object as returned by either\n        color_style() or no_style() in django.core.management.color.\n\n        The `allow_cascade` argument determines whether truncation may cascade\n        to tables with foreign keys pointing the tables being truncated.\n        \"\"\"\n\n        if not tables:\n            return []\n\n        if django.VERSION >= (3, 1):\n            sequences = self._sql_flush_new(style, tables, *args, **kwargs)\n        else:\n            sequences = self._sql_flush_old(style, tables, *args, **kwargs)\n\n        from django.db import connections\n        cursor = connections[self.connection.alias].cursor()\n\n        seqs = self._build_sequences(sequences, cursor)\n\n        COLUMNS = \"TABLE_NAME, CONSTRAINT_NAME\"\n        WHERE = \"CONSTRAINT_TYPE not in ('PRIMARY KEY','UNIQUE')\"\n        cursor.execute(\n            \"SELECT {} FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE {}\".format(COLUMNS, WHERE))\n        fks = cursor.fetchall()\n        sql_list = ['ALTER TABLE %s NOCHECK CONSTRAINT %s;' %\n                    (self.quote_name(fk[0]), self.quote_name(fk[1])) for fk in fks]\n        sql_list.extend(['%s %s %s;' % (style.SQL_KEYWORD('DELETE'), style.SQL_KEYWORD('FROM'),\n                                        style.SQL_FIELD(self.quote_name(table))) for table in tables])\n\n        if self.connection.to_azure_sql_db and self.connection.sql_server_version < 2014:\n            warnings.warn(\"Resetting identity columns is not supported \"\n                          \"on this versios of Azure SQL Database.\",\n                          RuntimeWarning)\n        else:\n            # Then reset the counters on each table.\n            sql_list.extend(['%s %s (%s, %s, %s) %s %s;' % (\n                style.SQL_KEYWORD('DBCC'),\n                style.SQL_KEYWORD('CHECKIDENT'),\n                style.SQL_FIELD(self.quote_name(seq[\"table\"])),\n                style.SQL_KEYWORD('RESEED'),\n                style.SQL_FIELD('%d' % seq['start_id']),\n                style.SQL_KEYWORD('WITH'),\n                style.SQL_KEYWORD('NO_INFOMSGS'),\n            ) for seq in seqs])\n\n        sql_list.extend(['ALTER TABLE %s CHECK CONSTRAINT %s;' %\n                         (self.quote_name(fk[0]), self.quote_name(fk[1])) for fk in fks])\n        return sql_list\n\n    def start_transaction_sql(self):\n        \"\"\"\n        Returns the SQL statement required to start a transaction.\n        \"\"\"\n        return \"BEGIN TRANSACTION\"\n\n    def subtract_temporals(self, internal_type, lhs, rhs):\n        lhs_sql, lhs_params = lhs\n        rhs_sql, rhs_params = rhs\n        if internal_type == 'DateField':\n            sql = \"CAST(DATEDIFF(day, %(rhs)s, %(lhs)s) AS bigint) * 86400 * 1000000\"\n            params = rhs_params + lhs_params\n        else:\n            SECOND = \"DATEDIFF(second, %(rhs)s, %(lhs)s)\"\n            MICROSECOND = \"DATEPART(microsecond, %(lhs)s) - DATEPART(microsecond, %(rhs)s)\"\n            sql = \"CAST({} AS bigint) * 1000000 + {}\".format(SECOND, MICROSECOND)\n            params = rhs_params + lhs_params * 2 + rhs_params\n        return sql % {'lhs': lhs_sql, 'rhs': rhs_sql}, params\n\n    def tablespace_sql(self, tablespace, inline=False):\n        \"\"\"\n        Returns the SQL that will be appended to tables or rows to define\n        a tablespace. Returns '' if the backend doesn't use tablespaces.\n        \"\"\"\n        return \"ON %s\" % self.quote_name(tablespace)\n\n    def prep_for_like_query(self, x):\n        \"\"\"Prepares a value for use in a LIKE query.\"\"\"\n        # http://msdn2.microsoft.com/en-us/library/ms179859.aspx\n        return force_str(x).replace('\\\\', '\\\\\\\\').replace('[', '[[]').replace('%', '[%]').replace('_', '[_]')\n\n    def prep_for_iexact_query(self, x):\n        \"\"\"\n        Same as prep_for_like_query(), but called for \"iexact\" matches, which\n        need not necessarily be implemented using \"LIKE\" in the backend.\n        \"\"\"\n        return x\n\n    def adapt_datetimefield_value(self, value):\n        \"\"\"\n        Transforms a datetime value to an object compatible with what is expected\n        by the backend driver for datetime columns.\n        \"\"\"\n        if value is None:\n            return None\n        if settings.USE_TZ and timezone.is_aware(value):\n            # pyodbc donesn't support datetimeoffset\n            value = value.astimezone(self.connection.timezone).replace(tzinfo=None)\n        return value\n\n    def time_trunc_sql(self, lookup_type, field_name):\n        # if self.connection.sql_server_version >= 2012:\n        #    fields = {\n        #        'hour': 'DATEPART(hour, %s)' % field_name,\n        #        'minute': 'DATEPART(minute, %s)' % field_name if lookup_type != 'hour' else '0',\n        #        'second': 'DATEPART(second, %s)' % field_name if lookup_type == 'second' else '0',\n        #    }\n        #    sql = 'TIMEFROMPARTS(%(hour)s, %(minute)s, %(second)s, 0, 0)' % fields\n        if lookup_type == 'hour':\n            sql = \"CONVERT(time, SUBSTRING(CONVERT(varchar, %s, 114), 0, 3) + ':00:00')\" % field_name\n        elif lookup_type == 'minute':\n            sql = \"CONVERT(time, SUBSTRING(CONVERT(varchar, %s, 114), 0, 6) + ':00')\" % field_name\n        elif lookup_type == 'second':\n            sql = \"CONVERT(time, SUBSTRING(CONVERT(varchar, %s, 114), 0, 9))\" % field_name\n        return sql\n\n    def conditional_expression_supported_in_where_clause(self, expression):\n        \"\"\"\n        Following \"Moved conditional expression wrapping to the Exact lookup\" in django 3.1\n        https://github.com/django/django/commit/37e6c5b79bd0529a3c85b8c478e4002fd33a2a1d\n        \"\"\"\n        if django.VERSION >= (3, 1):\n            if isinstance(expression, (Exists, WhereNode)):\n                return True\n            if isinstance(expression, ExpressionWrapper) and expression.conditional:\n                return self.conditional_expression_supported_in_where_clause(expression.expression)\n            if isinstance(expression, RawSQL) and expression.conditional:\n                return True\n            return False\n        return True\n"
  },
  {
    "path": "sql_server/pyodbc/schema.py",
    "content": "import binascii\nimport datetime\nimport django\n\nfrom django.db.backends.base.schema import (\n    BaseDatabaseSchemaEditor,\n    _is_relevant_relation,\n    _related_non_m2m_objects,\n    logger,\n)\nfrom django.db.backends.ddl_references import (\n    Columns,\n    IndexName,\n    Statement as DjStatement,\n    Table,\n)\nfrom django.db.models import Index\nfrom django.db.models.fields import AutoField, BigAutoField\nfrom django.db.transaction import TransactionManagementError\nfrom django.utils.encoding import force_str\n\n\nclass Statement(DjStatement):\n    def __hash__(self):\n        return hash((self.template, str(self.parts['name'])))\n\n    def __eq__(self, other):\n        return self.template == other.template and str(self.parts['name']) == str(other.parts['name'])\n\n\nclass DatabaseSchemaEditor(BaseDatabaseSchemaEditor):\n\n    _sql_check_constraint = \" CONSTRAINT %(name)s CHECK (%(check)s)\"\n    _sql_select_default_constraint_name = \"SELECT\" \\\n                                          \" d.name \" \\\n                                          \"FROM sys.default_constraints d \" \\\n                                          \"INNER JOIN sys.tables t ON\" \\\n                                          \" d.parent_object_id = t.object_id \" \\\n                                          \"INNER JOIN sys.columns c ON\" \\\n                                          \" d.parent_object_id = c.object_id AND\" \\\n                                          \" d.parent_column_id = c.column_id \" \\\n                                          \"INNER JOIN sys.schemas s ON\" \\\n                                          \" t.schema_id = s.schema_id \" \\\n                                          \"WHERE\" \\\n                                          \" t.name = %(table)s AND\" \\\n                                          \" c.name = %(column)s\"\n    _sql_select_foreign_key_constraints = \"SELECT\" \\\n                                          \" po.name AS table_name,\" \\\n                                          \" co.name AS constraint_name \" \\\n                                          \"FROM sys.foreign_key_columns fkc \" \\\n                                          \"INNER JOIN sys.objects co ON\" \\\n                                          \" fkc.constraint_object_id = co.object_id \" \\\n                                          \"INNER JOIN sys.tables po ON\" \\\n                                          \" fkc.parent_object_id = po.object_id \" \\\n                                          \"INNER JOIN sys.tables ro ON\" \\\n                                          \" fkc.referenced_object_id = ro.object_id \" \\\n                                          \"WHERE ro.name = %(table)s\"\n    sql_alter_column_default = \"ADD DEFAULT %(default)s FOR %(column)s\"\n    sql_alter_column_no_default = \"DROP CONSTRAINT %(column)s\"\n    sql_alter_column_not_null = \"ALTER COLUMN %(column)s %(type)s NOT NULL\"\n    sql_alter_column_null = \"ALTER COLUMN %(column)s %(type)s NULL\"\n    sql_alter_column_type = \"ALTER COLUMN %(column)s %(type)s\"\n    sql_create_column = \"ALTER TABLE %(table)s ADD %(column)s %(definition)s\"\n    sql_delete_column = \"ALTER TABLE %(table)s DROP COLUMN %(column)s\"\n    sql_delete_index = \"DROP INDEX %(name)s ON %(table)s\"\n    sql_delete_table = \"DROP TABLE %(table)s\"\n    sql_rename_column = \"EXEC sp_rename '%(table)s.%(old_column)s', %(new_column)s, 'COLUMN'\"\n    sql_rename_table = \"EXEC sp_rename %(old_table)s, %(new_table)s\"\n    sql_create_unique_null = \"CREATE UNIQUE INDEX %(name)s ON %(table)s(%(columns)s) \" \\\n                             \"WHERE %(columns)s IS NOT NULL\"\n\n    def _alter_column_default_sql(self, model, old_field, new_field, drop=False):\n        \"\"\"\n        Hook to specialize column default alteration.\n\n        Return a (sql, params) fragment to add or drop (depending on the drop\n        argument) a default to new_field's column.\n        \"\"\"\n        new_default = self.effective_default(new_field)\n        default = '%s'\n        params = [new_default]\n        column = self.quote_name(new_field.column)\n\n        if drop:\n            params = []\n            # SQL Server requires the name of the default constraint\n            result = self.execute(\n                self._sql_select_default_constraint_name % {\n                    \"table\": self.quote_value(model._meta.db_table),\n                    \"column\": self.quote_value(new_field.column),\n                },\n                has_result=True\n            )\n            if result:\n                for row in result:\n                    column = self.quote_name(next(iter(row)))\n        elif self.connection.features.requires_literal_defaults:\n            # Some databases (Oracle) can't take defaults as a parameter\n            # If this is the case, the SchemaEditor for that database should\n            # implement prepare_default().\n            default = self.prepare_default(new_default)\n            params = []\n\n        new_db_params = new_field.db_parameters(connection=self.connection)\n        sql = self.sql_alter_column_no_default if drop else self.sql_alter_column_default\n        return (\n            sql % {\n                'column': column,\n                'type': new_db_params['type'],\n                'default': default,\n            },\n            params,\n        )\n\n    def _alter_column_null_sql(self, model, old_field, new_field):\n        \"\"\"\n        Hook to specialize column null alteration.\n\n        Return a (sql, params) fragment to set a column to null or non-null\n        as required by new_field, or None if no changes are required.\n        \"\"\"\n        if (self.connection.features.interprets_empty_strings_as_nulls and\n                new_field.get_internal_type() in (\"CharField\", \"TextField\")):\n            # The field is nullable in the database anyway, leave it alone.\n            return\n        else:\n            new_db_params = new_field.db_parameters(connection=self.connection)\n            sql = self.sql_alter_column_null if new_field.null else self.sql_alter_column_not_null\n            return (\n                sql % {\n                    'column': self.quote_name(new_field.column),\n                    'type': new_db_params['type'],\n                },\n                [],\n            )\n\n    def _alter_column_type_sql(self, model, old_field, new_field, new_type):\n        new_type = self._set_field_new_type_null_status(old_field, new_type)\n        return super()._alter_column_type_sql(model, old_field, new_field, new_type)\n\n    def alter_unique_together(self, model, old_unique_together, new_unique_together):\n        \"\"\"\n        Deal with a model changing its unique_together. The input\n        unique_togethers must be doubly-nested, not the single-nested\n        [\"foo\", \"bar\"] format.\n        \"\"\"\n        olds = {tuple(fields) for fields in old_unique_together}\n        news = {tuple(fields) for fields in new_unique_together}\n        # Deleted uniques\n        for fields in olds.difference(news):\n            self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_index)\n        # Created uniques\n        for fields in news.difference(olds):\n            columns = [model._meta.get_field(field).column for field in fields]\n            condition = ' AND '.join([\"[%s] IS NOT NULL\" % col for col in columns])\n            sql = self._create_unique_sql(model, columns, condition=condition)\n            self.execute(sql)\n\n    def _model_indexes_sql(self, model):\n        \"\"\"\n        Return a list of all index SQL statements (field indexes,\n        index_together, Meta.indexes) for the specified model.\n        \"\"\"\n        if not model._meta.managed or model._meta.proxy or model._meta.swapped:\n            return []\n        output = []\n        for field in model._meta.local_fields:\n            output.extend(self._field_indexes_sql(model, field))\n\n        for field_names in model._meta.index_together:\n            fields = [model._meta.get_field(field) for field in field_names]\n            output.append(self._create_index_sql(model, fields, suffix=\"_idx\"))\n\n        for field_names in model._meta.unique_together:\n            columns = [model._meta.get_field(field).column for field in field_names]\n            condition = ' AND '.join([\"[%s] IS NOT NULL\" % col for col in columns])\n            sql = self._create_unique_sql(model, columns, condition=condition)\n            output.append(sql)\n\n        for index in model._meta.indexes:\n            output.append(index.create_sql(model, self))\n        return output\n\n    def _alter_many_to_many(self, model, old_field, new_field, strict):\n        \"\"\"Alter M2Ms to repoint their to= endpoints.\"\"\"\n\n        for idx in self._constraint_names(old_field.remote_field.through, index=True, unique=True):\n            self.execute(self.sql_delete_index % {'name': idx, 'table': old_field.remote_field.through._meta.db_table})\n\n        return super()._alter_many_to_many(model, old_field, new_field, strict)\n\n    def _db_table_constraint_names(self, db_table, column_names=None, unique=None,\n                                   primary_key=None, index=None, foreign_key=None,\n                                   check=None, type_=None, exclude=None):\n        \"\"\"Return all constraint names matching the columns and conditions.\"\"\"\n        if column_names is not None:\n            column_names = [\n                self.connection.introspection.identifier_converter(name)\n                for name in column_names\n            ]\n        with self.connection.cursor() as cursor:\n            constraints = self.connection.introspection.get_constraints(cursor, db_table)\n        result = []\n        for name, infodict in constraints.items():\n            if column_names is None or column_names == infodict['columns']:\n                if unique is not None and infodict['unique'] != unique:\n                    continue\n                if primary_key is not None and infodict['primary_key'] != primary_key:\n                    continue\n                if index is not None and infodict['index'] != index:\n                    continue\n                if check is not None and infodict['check'] != check:\n                    continue\n                if foreign_key is not None and not infodict['foreign_key']:\n                    continue\n                if type_ is not None and infodict['type'] != type_:\n                    continue\n                if not exclude or name not in exclude:\n                    result.append(name)\n        return result\n\n    def _db_table_delete_constraint_sql(self, template, db_table, name):\n        return Statement(\n            template,\n            table=Table(db_table, self.quote_name),\n            name=self.quote_name(name),\n        )\n\n    def alter_db_table(self, model, old_db_table, new_db_table):\n        index_names = self._db_table_constraint_names(old_db_table, index=True)\n        for index_name in index_names:\n            self.execute(self._db_table_delete_constraint_sql(self.sql_delete_index, old_db_table, index_name))\n\n        index_names = self._db_table_constraint_names(new_db_table, index=True)\n        for index_name in index_names:\n            self.execute(self._db_table_delete_constraint_sql(self.sql_delete_index, new_db_table, index_name))\n\n        return super().alter_db_table(model, old_db_table, new_db_table)\n\n    def _alter_field(self, model, old_field, new_field, old_type, new_type,\n                     old_db_params, new_db_params, strict=False):\n        \"\"\"Actually perform a \"physical\" (non-ManyToMany) field update.\"\"\"\n\n        # the backend doesn't support altering from/to (Big)AutoField\n        # because of the limited capability of SQL Server to edit IDENTITY property\n        for t in (AutoField, BigAutoField):\n            if isinstance(old_field, t) or isinstance(new_field, t):\n                raise NotImplementedError(\"the backend doesn't support altering from/to %s.\" % t.__name__)\n        # Drop any FK constraints, we'll remake them later\n        fks_dropped = set()\n        if old_field.remote_field and old_field.db_constraint:\n            # Drop index, SQL Server requires explicit deletion\n            if not hasattr(new_field, 'db_constraint') or not new_field.db_constraint:\n                index_names = self._constraint_names(model, [old_field.column], index=True)\n                for index_name in index_names:\n                    self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name))\n\n            fk_names = self._constraint_names(model, [old_field.column], foreign_key=True)\n            if strict and len(fk_names) != 1:\n                raise ValueError(\"Found wrong number (%s) of foreign key constraints for %s.%s\" % (\n                    len(fk_names),\n                    model._meta.db_table,\n                    old_field.column,\n                ))\n            for fk_name in fk_names:\n                fks_dropped.add((old_field.column,))\n                self.execute(self._delete_constraint_sql(self.sql_delete_fk, model, fk_name))\n        # Has unique been removed?\n        if old_field.unique and (not new_field.unique or self._field_became_primary_key(old_field, new_field)):\n            # Find the unique constraint for this field\n            constraint_names = self._constraint_names(model, [old_field.column], unique=True, primary_key=False)\n            if strict and len(constraint_names) != 1:\n                raise ValueError(\"Found wrong number (%s) of unique constraints for %s.%s\" % (\n                    len(constraint_names),\n                    model._meta.db_table,\n                    old_field.column,\n                ))\n            for constraint_name in constraint_names:\n                self.execute(self._delete_constraint_sql(self.sql_delete_unique, model, constraint_name))\n        # Drop incoming FK constraints if the field is a primary key or unique,\n        # which might be a to_field target, and things are going to change.\n        drop_foreign_keys = (\n            (\n                (old_field.primary_key and new_field.primary_key) or\n                (old_field.unique and new_field.unique)\n            ) and old_type != new_type\n        )\n        if drop_foreign_keys:\n            # '_meta.related_field' also contains M2M reverse fields, these\n            # will be filtered out\n            for _old_rel, new_rel in _related_non_m2m_objects(old_field, new_field):\n                rel_fk_names = self._constraint_names(\n                    new_rel.related_model, [new_rel.field.column], foreign_key=True\n                )\n                for fk_name in rel_fk_names:\n                    self.execute(self._delete_constraint_sql(self.sql_delete_fk, new_rel.related_model, fk_name))\n        # Removed an index? (no strict check, as multiple indexes are possible)\n        # Remove indexes if db_index switched to False or a unique constraint\n        # will now be used in lieu of an index. The following lines from the\n        # truth table show all True cases; the rest are False:\n        #\n        # old_field.db_index | old_field.unique | new_field.db_index | new_field.unique\n        # ------------------------------------------------------------------------------\n        # True               | False            | False              | False\n        # True               | False            | False              | True\n        # True               | False            | True               | True\n        if (old_field.db_index and not old_field.unique and (not new_field.db_index or new_field.unique)) or (\n                # Drop indexes on nvarchar columns that are changing to a different type\n                # SQL Server requires explicit deletion\n                (old_field.db_index or old_field.unique) and (\n                    (old_type.startswith('nvarchar') and not new_type.startswith('nvarchar'))\n                )):\n            # Find the index for this field\n            meta_index_names = {index.name for index in model._meta.indexes}\n            # Retrieve only BTREE indexes since this is what's created with\n            # db_index=True.\n            index_names = self._constraint_names(model, [old_field.column], index=True, type_=Index.suffix)\n            for index_name in index_names:\n                if index_name not in meta_index_names:\n                    # The only way to check if an index was created with\n                    # db_index=True or with Index(['field'], name='foo')\n                    # is to look at its name (refs #28053).\n                    self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name))\n        # Change check constraints?\n        if (old_db_params['check'] != new_db_params['check'] and old_db_params['check']) or (\n            # SQL Server requires explicit deletion befor altering column type with the same constraint\n            old_db_params['check'] == new_db_params['check'] and old_db_params['check'] and\n            old_db_params['type'] != new_db_params['type']\n        ):\n            constraint_names = self._constraint_names(model, [old_field.column], check=True)\n            if strict and len(constraint_names) != 1:\n                raise ValueError(\"Found wrong number (%s) of check constraints for %s.%s\" % (\n                    len(constraint_names),\n                    model._meta.db_table,\n                    old_field.column,\n                ))\n            for constraint_name in constraint_names:\n                self.execute(self._delete_constraint_sql(self.sql_delete_check, model, constraint_name))\n        # Have they renamed the column?\n        if old_field.column != new_field.column:\n            # remove old indices\n            self._delete_indexes(model, old_field, new_field)\n\n            self.execute(self._rename_field_sql(model._meta.db_table, old_field, new_field, new_type))\n            # Rename all references to the renamed column.\n            for sql in self.deferred_sql:\n                if isinstance(sql, DjStatement):\n                    sql.rename_column_references(model._meta.db_table, old_field.column, new_field.column)\n\n        # Next, start accumulating actions to do\n        actions = []\n        null_actions = []\n        post_actions = []\n        # Type change?\n        if old_type != new_type:\n            fragment, other_actions = self._alter_column_type_sql(model, old_field, new_field, new_type)\n            actions.append(fragment)\n            post_actions.extend(other_actions)\n            # Drop unique constraint, SQL Server requires explicit deletion\n            self._delete_unique_constraints(model, old_field, new_field, strict)\n            # Drop indexes, SQL Server requires explicit deletion\n            self._delete_indexes(model, old_field, new_field)\n        # When changing a column NULL constraint to NOT NULL with a given\n        # default value, we need to perform 4 steps:\n        #  1. Add a default for new incoming writes\n        #  2. Update existing NULL rows with new default\n        #  3. Replace NULL constraint with NOT NULL\n        #  4. Drop the default again.\n        # Default change?\n        old_default = self.effective_default(old_field)\n        new_default = self.effective_default(new_field)\n        needs_database_default = (\n            old_field.null and\n            not new_field.null and\n            old_default != new_default and\n            new_default is not None and\n            not self.skip_default(new_field)\n        )\n        if needs_database_default:\n            actions.append(self._alter_column_default_sql(model, old_field, new_field))\n        # Nullability change?\n        if old_field.null != new_field.null:\n            fragment = self._alter_column_null_sql(model, old_field, new_field)\n            if fragment:\n                null_actions.append(fragment)\n                if not new_field.null:\n                    # Drop unique constraint, SQL Server requires explicit deletion\n                    self._delete_unique_constraints(model, old_field, new_field, strict)\n                    # Drop indexes, SQL Server requires explicit deletion\n                    self._delete_indexes(model, old_field, new_field)\n        # Only if we have a default and there is a change from NULL to NOT NULL\n        four_way_default_alteration = (\n            new_field.has_default() and\n            (old_field.null and not new_field.null)\n        )\n        if actions or null_actions:\n            if not four_way_default_alteration:\n                # If we don't have to do a 4-way default alteration we can\n                # directly run a (NOT) NULL alteration\n                actions = actions + null_actions\n            # Combine actions together if we can (e.g. postgres)\n            if self.connection.features.supports_combined_alters and actions:\n                sql, params = tuple(zip(*actions))\n                actions = [(\", \".join(sql), sum(params, []))]\n            # Apply those actions\n            for sql, params in actions:\n                self._delete_indexes(model, old_field, new_field)\n                self.execute(\n                    self.sql_alter_column % {\n                        \"table\": self.quote_name(model._meta.db_table),\n                        \"changes\": sql,\n                    },\n                    params,\n                )\n            if four_way_default_alteration:\n                # Update existing rows with default value\n                self.execute(\n                    self.sql_update_with_default % {\n                        \"table\": self.quote_name(model._meta.db_table),\n                        \"column\": self.quote_name(new_field.column),\n                        \"default\": \"%s\",\n                    },\n                    [new_default],\n                )\n                # Since we didn't run a NOT NULL change before we need to do it\n                # now\n                for sql, params in null_actions:\n                    self.execute(\n                        self.sql_alter_column % {\n                            \"table\": self.quote_name(model._meta.db_table),\n                            \"changes\": sql,\n                        },\n                        params,\n                    )\n        if post_actions:\n            for sql, params in post_actions:\n                self.execute(sql, params)\n        # If primary_key changed to False, delete the primary key constraint.\n        if old_field.primary_key and not new_field.primary_key:\n            self._delete_primary_key(model, strict)\n        # Added a unique?\n        if self._unique_should_be_added(old_field, new_field):\n            if (self.connection.features.supports_nullable_unique_constraints and\n                    not new_field.many_to_many and new_field.null):\n\n                self.execute(\n                    self._create_index_sql(\n                        model, [new_field], sql=self.sql_create_unique_null, suffix=\"_uniq\"\n                    )\n                )\n            else:\n                self.execute(self._create_unique_sql(model, [new_field.column]))\n        # Added an index?\n        # constraint will no longer be used in lieu of an index. The following\n        # lines from the truth table show all True cases; the rest are False:\n        #\n        # old_field.db_index | old_field.unique | new_field.db_index | new_field.unique\n        # ------------------------------------------------------------------------------\n        # False              | False            | True               | False\n        # False              | True             | True               | False\n        # True               | True             | True               | False\n        if (not old_field.db_index or old_field.unique) and new_field.db_index and not new_field.unique:\n            self.execute(self._create_index_sql(model, [new_field]))\n\n        # Restore indexes & unique constraints deleted above, SQL Server requires explicit restoration\n        if (old_type != new_type or (old_field.null and not new_field.null)) and (\n            old_field.column == new_field.column\n        ):\n            # Restore unique constraints\n            # Note: if nullable they are implemented via an explicit filtered UNIQUE INDEX (not CONSTRAINT)\n            # in order to get ANSI-compliant NULL behaviour (i.e. NULL != NULL, multiple are allowed)\n            if old_field.unique and new_field.unique:\n                if new_field.null:\n                    self.execute(\n                        self._create_index_sql(\n                            model, [old_field], sql=self.sql_create_unique_null, suffix=\"_uniq\"\n                        )\n                    )\n                else:\n                    self.execute(self._create_unique_sql(model, columns=[old_field.column]))\n            else:\n                for fields in model._meta.unique_together:\n                    columns = [model._meta.get_field(field).column for field in fields]\n                    if old_field.column in columns:\n                        condition = ' AND '.join([\"[%s] IS NOT NULL\" % col for col in columns])\n                        self.execute(self._create_unique_sql(model, columns, condition=condition))\n            # Restore indexes\n            index_columns = []\n            if old_field.db_index and new_field.db_index:\n                index_columns.append([old_field])\n            else:\n                for fields in model._meta.index_together:\n                    columns = [model._meta.get_field(field) for field in fields]\n                    if old_field.column in [c.column for c in columns]:\n                        index_columns.append(columns)\n            if index_columns:\n                for columns in index_columns:\n                    self.execute(self._create_index_sql(model, columns, suffix='_idx'))\n        # Type alteration on primary key? Then we need to alter the column\n        # referring to us.\n        rels_to_update = []\n        if old_field.primary_key and new_field.primary_key and old_type != new_type:\n            rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))\n        # Changed to become primary key?\n        if self._field_became_primary_key(old_field, new_field):\n            # Make the new one\n            self.execute(\n                self.sql_create_pk % {\n                    \"table\": self.quote_name(model._meta.db_table),\n                    \"name\": self.quote_name(\n                        self._create_index_name(model._meta.db_table, [new_field.column], suffix=\"_pk\")\n                    ),\n                    \"columns\": self.quote_name(new_field.column),\n                }\n            )\n            # Update all referencing columns\n            rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))\n        # Handle our type alters on the other end of rels from the PK stuff above\n        for old_rel, new_rel in rels_to_update:\n            rel_db_params = new_rel.field.db_parameters(connection=self.connection)\n            rel_type = rel_db_params['type']\n            fragment, other_actions = self._alter_column_type_sql(\n                new_rel.related_model, old_rel.field, new_rel.field, rel_type\n            )\n            self.execute(\n                self.sql_alter_column % {\n                    \"table\": self.quote_name(new_rel.related_model._meta.db_table),\n                    \"changes\": fragment[0],\n                },\n                fragment[1],\n            )\n            for sql, params in other_actions:\n                self.execute(sql, params)\n        # Does it have a foreign key?\n        if (new_field.remote_field and\n                (fks_dropped or not old_field.remote_field or not old_field.db_constraint) and\n                new_field.db_constraint):\n            self.execute(self._create_fk_sql(model, new_field, \"_fk_%(to_table)s_%(to_column)s\"))\n        # Rebuild FKs that pointed to us if we previously had to drop them\n        if drop_foreign_keys:\n            for rel in new_field.model._meta.related_objects:\n                if _is_relevant_relation(rel, new_field) and rel.field.db_constraint:\n                    self.execute(self._create_fk_sql(rel.related_model, rel.field, \"_fk\"))\n        # Does it have check constraints we need to add?\n        if (old_db_params['check'] != new_db_params['check'] and new_db_params['check']) or (\n            # SQL Server requires explicit creation after altering column type with the same constraint\n            old_db_params['check'] == new_db_params['check'] and new_db_params['check'] and\n            old_db_params['type'] != new_db_params['type']\n        ):\n            self.execute(\n                self.sql_create_check % {\n                    \"table\": self.quote_name(model._meta.db_table),\n                    \"name\": self.quote_name(\n                        self._create_index_name(model._meta.db_table, [new_field.column], suffix=\"_check\")\n                    ),\n                    \"column\": self.quote_name(new_field.column),\n                    \"check\": new_db_params['check'],\n                }\n            )\n        # Drop the default if we need to\n        # (Django usually does not use in-database defaults)\n        if needs_database_default:\n            changes_sql, params = self._alter_column_default_sql(model, old_field, new_field, drop=True)\n            sql = self.sql_alter_column % {\n                \"table\": self.quote_name(model._meta.db_table),\n                \"changes\": changes_sql,\n            }\n            self.execute(sql, params)\n\n        # Reset connection if required\n        if self.connection.features.connection_persists_old_columns:\n            self.connection.close()\n\n    def _delete_indexes(self, model, old_field, new_field):\n        index_columns = []\n        if old_field.db_index and new_field.db_index:\n            index_columns.append([old_field.column])\n        for fields in model._meta.index_together:\n            columns = [model._meta.get_field(field).column for field in fields]\n            if old_field.column in columns:\n                index_columns.append(columns)\n\n        for fields in model._meta.unique_together:\n            columns = [model._meta.get_field(field).column for field in fields]\n            if old_field.column in columns:\n                index_columns.append(columns)\n        if index_columns:\n            for columns in index_columns:\n                index_names = self._constraint_names(model, columns, index=True)\n                for index_name in index_names:\n                    self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name))\n\n    def _delete_unique_constraints(self, model, old_field, new_field, strict=False):\n        unique_columns = []\n        if old_field.unique and new_field.unique:\n            unique_columns.append([old_field.column])\n        if unique_columns:\n            for columns in unique_columns:\n                constraint_names_normal = self._constraint_names(model, columns, unique=True, index=False)\n                constraint_names_index = self._constraint_names(model, columns, unique=True, index=True)\n                constraint_names = constraint_names_normal + constraint_names_index\n                if strict and len(constraint_names) != 1:\n                    raise ValueError(\"Found wrong number (%s) of unique constraints for %s.%s\" % (\n                        len(constraint_names),\n                        model._meta.db_table,\n                        old_field.column,\n                    ))\n                for constraint_name in constraint_names_normal:\n                    self.execute(self._delete_constraint_sql(self.sql_delete_unique, model, constraint_name))\n                # Unique indexes which are not table constraints must be deleted using the appropriate SQL.\n                # These may exist for example to enforce ANSI-compliant unique constraints on nullable columns.\n                for index_name in constraint_names_index:\n                    self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name))\n\n    def _rename_field_sql(self, table, old_field, new_field, new_type):\n        new_type = self._set_field_new_type_null_status(old_field, new_type)\n        return super()._rename_field_sql(table, old_field, new_field, new_type)\n\n    def _set_field_new_type_null_status(self, field, new_type):\n        \"\"\"\n        Keep the null property of the old field. If it has changed, it will be\n        handled separately.\n        \"\"\"\n        if field.null:\n            new_type += \" NULL\"\n        else:\n            new_type += \" NOT NULL\"\n        return new_type\n\n    def add_field(self, model, field):\n        \"\"\"\n        Create a field on a model. Usually involves adding a column, but may\n        involve adding a table instead (for M2M fields).\n        \"\"\"\n        # Special-case implicit M2M tables\n        if field.many_to_many and field.remote_field.through._meta.auto_created:\n            return self.create_model(field.remote_field.through)\n        # Get the column's definition\n        definition, params = self.column_sql(model, field, include_default=True)\n        # It might not actually have a column behind it\n        if definition is None:\n            return\n\n        if (self.connection.features.supports_nullable_unique_constraints and\n                not field.many_to_many and field.null and field.unique):\n\n            definition = definition.replace(' UNIQUE', '')\n            self.deferred_sql.append(self._create_index_sql(\n                model, [field], sql=self.sql_create_unique_null, suffix=\"_uniq\"\n            ))\n\n        # Check constraints can go on the column SQL here\n        db_params = field.db_parameters(connection=self.connection)\n        if db_params['check']:\n            definition += \" CHECK (%s)\" % db_params['check']\n        # Build the SQL and run it\n        sql = self.sql_create_column % {\n            \"table\": self.quote_name(model._meta.db_table),\n            \"column\": self.quote_name(field.column),\n            \"definition\": definition,\n        }\n        self.execute(sql, params)\n        # Drop the default if we need to\n        # (Django usually does not use in-database defaults)\n        if not self.skip_default(field) and self.effective_default(field) is not None:\n            changes_sql, params = self._alter_column_default_sql(model, None, field, drop=True)\n            sql = self.sql_alter_column % {\n                \"table\": self.quote_name(model._meta.db_table),\n                \"changes\": changes_sql,\n            }\n            self.execute(sql, params)\n        # Add an index, if required\n        self.deferred_sql.extend(self._field_indexes_sql(model, field))\n        # Add any FK constraints later\n        if field.remote_field and self.connection.features.supports_foreign_keys and field.db_constraint:\n            self.deferred_sql.append(self._create_fk_sql(model, field, \"_fk_%(to_table)s_%(to_column)s\"))\n        # Reset connection if required\n        if self.connection.features.connection_persists_old_columns:\n            self.connection.close()\n\n    def _create_unique_sql(self, model, columns, name=None, condition=None, deferrable=None):\n        if (deferrable and not getattr(self.connection.features, 'supports_deferrable_unique_constraints', False)):\n            return None\n\n        def create_unique_name(*args, **kwargs):\n            return self.quote_name(self._create_index_name(*args, **kwargs))\n\n        table = Table(model._meta.db_table, self.quote_name)\n        if name is None:\n            name = IndexName(model._meta.db_table, columns, '_uniq', create_unique_name)\n        else:\n            name = self.quote_name(name)\n        columns = Columns(table, columns, self.quote_name)\n        statement_args = {\n            \"deferrable\": self._deferrable_constraint_sql(deferrable)\n        } if django.VERSION >= (3, 1) else {}\n\n        if condition:\n            return Statement(\n                self.sql_create_unique_index,\n                table=table,\n                name=name,\n                columns=columns,\n                condition=' WHERE ' + condition,\n                **statement_args\n            ) if self.connection.features.supports_partial_indexes else None\n        else:\n            return Statement(\n                self.sql_create_unique,\n                table=table,\n                name=name,\n                columns=columns,\n                **statement_args\n            )\n\n    def _create_index_sql(self, model, fields, *, name=None, suffix='', using='',\n                          db_tablespace=None, col_suffixes=(), sql=None, opclasses=(),\n                          condition=None):\n        \"\"\"\n        Return the SQL statement to create the index for one or several fields.\n        `sql` can be specified if the syntax differs from the standard (GIS\n        indexes, ...).\n        \"\"\"\n        tablespace_sql = self._get_index_tablespace_sql(model, fields, db_tablespace=db_tablespace)\n        columns = [field.column for field in fields]\n        sql_create_index = sql or self.sql_create_index\n        table = model._meta.db_table\n\n        def create_index_name(*args, **kwargs):\n            nonlocal name\n            if name is None:\n                name = self._create_index_name(*args, **kwargs)\n            return self.quote_name(name)\n\n        return Statement(\n            sql_create_index,\n            table=Table(table, self.quote_name),\n            name=IndexName(table, columns, suffix, create_index_name),\n            using=using,\n            columns=self._index_columns(table, columns, col_suffixes, opclasses),\n            extra=tablespace_sql,\n            condition=(' WHERE ' + condition) if condition else '',\n        )\n\n    def create_model(self, model):\n        \"\"\"\n        Takes a model and creates a table for it in the database.\n        Will also create any accompanying indexes or unique constraints.\n        \"\"\"\n        # Create column SQL, add FK deferreds if needed\n        column_sqls = []\n        params = []\n        for field in model._meta.local_fields:\n            # SQL\n            definition, extra_params = self.column_sql(model, field)\n            if definition is None:\n                continue\n\n            if (self.connection.features.supports_nullable_unique_constraints and\n                    not field.many_to_many and field.null and field.unique):\n\n                definition = definition.replace(' UNIQUE', '')\n                self.deferred_sql.append(self._create_index_sql(\n                    model, [field], sql=self.sql_create_unique_null, suffix=\"_uniq\"\n                ))\n\n            # Check constraints can go on the column SQL here\n            db_params = field.db_parameters(connection=self.connection)\n            if db_params['check']:\n                # SQL Server requires a name for the check constraint\n                definition += self._sql_check_constraint % {\n                    \"name\": self._create_index_name(model._meta.db_table, [field.column], suffix=\"_check\"),\n                    \"check\": db_params['check']\n                }\n            # Autoincrement SQL (for backends with inline variant)\n            col_type_suffix = field.db_type_suffix(connection=self.connection)\n            if col_type_suffix:\n                definition += \" %s\" % col_type_suffix\n            params.extend(extra_params)\n            # FK\n            if field.remote_field and field.db_constraint:\n                to_table = field.remote_field.model._meta.db_table\n                to_column = field.remote_field.model._meta.get_field(field.remote_field.field_name).column\n                if self.sql_create_inline_fk:\n                    definition += \" \" + self.sql_create_inline_fk % {\n                        \"to_table\": self.quote_name(to_table),\n                        \"to_column\": self.quote_name(to_column),\n                    }\n                elif self.connection.features.supports_foreign_keys:\n                    self.deferred_sql.append(self._create_fk_sql(model, field, \"_fk_%(to_table)s_%(to_column)s\"))\n            # Add the SQL to our big list\n            column_sqls.append(\"%s %s\" % (\n                self.quote_name(field.column),\n                definition,\n            ))\n            # Autoincrement SQL (for backends with post table definition variant)\n            if field.get_internal_type() in (\"AutoField\", \"BigAutoField\"):\n                autoinc_sql = self.connection.ops.autoinc_sql(model._meta.db_table, field.column)\n                if autoinc_sql:\n                    self.deferred_sql.extend(autoinc_sql)\n\n        # Add any unique_togethers (always deferred, as some fields might be\n        # created afterwards, like geometry fields with some backends)\n        for fields in model._meta.unique_together:\n            columns = [model._meta.get_field(field).column for field in fields]\n            condition = ' AND '.join([\"[%s] IS NOT NULL\" % col for col in columns])\n            self.deferred_sql.append(self._create_unique_sql(model, columns, condition=condition))\n\n        # Make the table\n        sql = self.sql_create_table % {\n            \"table\": self.quote_name(model._meta.db_table),\n            \"definition\": \", \".join(column_sqls)\n        }\n        if model._meta.db_tablespace:\n            tablespace_sql = self.connection.ops.tablespace_sql(model._meta.db_tablespace)\n            if tablespace_sql:\n                sql += ' ' + tablespace_sql\n        # Prevent using [] as params, in the case a literal '%' is used in the definition\n        self.execute(sql, params or None)\n\n        # Add any field index and index_together's (deferred as SQLite3 _remake_table needs it)\n        self.deferred_sql.extend(self._model_indexes_sql(model))\n        self.deferred_sql = list(set(self.deferred_sql))\n\n        # Make M2M tables\n        for field in model._meta.local_many_to_many:\n            if field.remote_field.through._meta.auto_created:\n                self.create_model(field.remote_field.through)\n\n    def delete_model(self, model):\n        \"\"\"\n        Deletes a model from the database.\n        \"\"\"\n        # Delete the foreign key constraints\n        result = self.execute(\n            self._sql_select_foreign_key_constraints % {\n                \"table\": self.quote_value(model._meta.db_table),\n            },\n            has_result=True\n        )\n        if result:\n            for table, constraint in result:\n                sql = self.sql_alter_column % {\n                    \"table\": self.quote_name(table),\n                    \"changes\": self.sql_alter_column_no_default % {\n                        \"column\": self.quote_name(constraint),\n                    }\n                }\n                self.execute(sql)\n\n        # Delete the table\n        super().delete_model(model)\n        # Remove all deferred statements referencing the deleted table.\n        for sql in list(self.deferred_sql):\n            if isinstance(sql, Statement) and sql.references_table(model._meta.db_table):\n                self.deferred_sql.remove(sql)\n\n    def execute(self, sql, params=(), has_result=False):\n        \"\"\"\n        Executes the given SQL statement, with optional parameters.\n        \"\"\"\n        result = None\n        # Don't perform the transactional DDL check if SQL is being collected\n        # as it's not going to be executed anyway.\n        if not self.collect_sql and self.connection.in_atomic_block and not self.connection.features.can_rollback_ddl:\n            raise TransactionManagementError(\n                \"Executing DDL statements while in a transaction on databases \"\n                \"that can't perform a rollback is prohibited.\"\n            )\n        # Account for non-string statement objects.\n        sql = str(sql)\n        # Log the command we're running, then run it\n        logger.debug(\"%s; (params %r)\", sql, params, extra={'params': params, 'sql': sql})\n        if self.collect_sql:\n            ending = \"\" if sql.endswith(\";\") else \";\"\n            if params is not None:\n                self.collected_sql.append((sql % tuple(map(self.quote_value, params))) + ending)\n            else:\n                self.collected_sql.append(sql + ending)\n        else:\n            cursor = self.connection.cursor()\n            cursor.execute(sql, params)\n            if has_result:\n                result = cursor.fetchall()\n            # the cursor can be closed only when the driver supports opening\n            # multiple cursors on a connection because the migration command\n            # has already opened a cursor outside this method\n            if self.connection.supports_mars:\n                cursor.close()\n        return result\n\n    def prepare_default(self, value):\n        return self.quote_value(value)\n\n    def quote_value(self, value):\n        \"\"\"\n        Returns a quoted version of the value so it's safe to use in an SQL\n        string. This is not safe against injection from user code; it is\n        intended only for use in making SQL scripts or preparing default values\n        for particularly tricky backends (defaults are not user-defined, though,\n        so this is safe).\n        \"\"\"\n        if isinstance(value, (datetime.datetime, datetime.date, datetime.time)):\n            return \"'%s'\" % value\n        elif isinstance(value, str):\n            return \"'%s'\" % value.replace(\"'\", \"''\")\n        elif isinstance(value, (bytes, bytearray, memoryview)):\n            return \"0x%s\" % force_str(binascii.hexlify(value))\n        elif isinstance(value, bool):\n            return \"1\" if value else \"0\"\n        else:\n            return str(value)\n\n    def remove_field(self, model, field):\n        \"\"\"\n        Removes a field from a model. Usually involves deleting a column,\n        but for M2Ms may involve deleting a table.\n        \"\"\"\n        # Special-case implicit M2M tables\n        if field.many_to_many and field.remote_field.through._meta.auto_created:\n            return self.delete_model(field.remote_field.through)\n        # It might not actually have a column behind it\n        if field.db_parameters(connection=self.connection)['type'] is None:\n            return\n        # Drop any FK constraints, SQL Server requires explicit deletion\n        with self.connection.cursor() as cursor:\n            constraints = self.connection.introspection.get_constraints(cursor, model._meta.db_table)\n        for name, infodict in constraints.items():\n            if field.column in infodict['columns'] and infodict['foreign_key']:\n                self.execute(self._delete_constraint_sql(self.sql_delete_fk, model, name))\n        # Drop any indexes, SQL Server requires explicit deletion\n        for name, infodict in constraints.items():\n            if field.column in infodict['columns'] and infodict['index']:\n                self.execute(self.sql_delete_index % {\n                    \"table\": self.quote_name(model._meta.db_table),\n                    \"name\": self.quote_name(name),\n                })\n        # Drop primary key constraint, SQL Server requires explicit deletion\n        for name, infodict in constraints.items():\n            if field.column in infodict['columns'] and infodict['primary_key']:\n                self.execute(self.sql_delete_pk % {\n                    \"table\": self.quote_name(model._meta.db_table),\n                    \"name\": self.quote_name(name),\n                })\n        # Drop check constraints, SQL Server requires explicit deletion\n        for name, infodict in constraints.items():\n            if field.column in infodict['columns'] and infodict['check']:\n                self.execute(self.sql_delete_check % {\n                    \"table\": self.quote_name(model._meta.db_table),\n                    \"name\": self.quote_name(name),\n                })\n        # Drop unique constraints, SQL Server requires explicit deletion\n        for name, infodict in constraints.items():\n            if (field.column in infodict['columns'] and infodict['unique'] and\n                    not infodict['primary_key'] and not infodict['index']):\n                self.execute(self.sql_delete_unique % {\n                    \"table\": self.quote_name(model._meta.db_table),\n                    \"name\": self.quote_name(name),\n                })\n        # Delete the column\n        sql = self.sql_delete_column % {\n            \"table\": self.quote_name(model._meta.db_table),\n            \"column\": self.quote_name(field.column),\n        }\n        self.execute(sql)\n        # Reset connection if required\n        if self.connection.features.connection_persists_old_columns:\n            self.connection.close()\n        # Remove all deferred statements referencing the deleted column.\n        for sql in list(self.deferred_sql):\n            if isinstance(sql, Statement) and sql.references_column(model._meta.db_table, field.column):\n                self.deferred_sql.remove(sql)\n"
  },
  {
    "path": "test.sh",
    "content": "# TODO:\n#\n# * m2m_through_regress\n# * many_to_one_null\n\nset -e\n\nDJANGO_VERSION=\"$(python -m django --version)\"\n\ncd django\ngit fetch -q --depth=1 origin +refs/tags/*:refs/tags/*\ngit checkout -q $DJANGO_VERSION\npip install -q -r tests/requirements/py3.txt\n\npython tests/runtests.py --settings=testapp.settings --noinput --keepdb \\\n    aggregation \\\n    aggregation_regress \\\n    annotations \\\n    backends \\\n    basic \\\n    bulk_create \\\n    constraints \\\n    custom_columns \\\n    custom_lookups \\\n    custom_managers \\\n    custom_methods \\\n    custom_migration_operations \\\n    custom_pk \\\n    datatypes \\\n    dates \\\n    datetimes \\\n    db_functions \\\n    db_typecasts \\\n    db_utils \\\n    dbshell \\\n    defer \\\n    defer_regress \\\n    delete \\\n    delete_regress \\\n    distinct_on_fields \\\n    empty \\\n    expressions \\\n    expressions_case \\\n    expressions_window \\\n    extra_regress \\\n    field_deconstruction \\\n    field_defaults \\\n    field_subclassing \\\n    filtered_relation \\\n    fixtures \\\n    fixtures_model_package \\\n    fixtures_regress \\\n    force_insert_update \\\n    foreign_object \\\n    from_db_value \\\n    generic_relations \\\n    generic_relations_regress \\\n    get_earliest_or_latest \\\n    get_object_or_404 \\\n    get_or_create \\\n    indexes \\\n    inspectdb \\\n    introspection \\\n    invalid_models_tests \\\n    known_related_objects \\\n    lookup \\\n    m2m_and_m2o \\\n    m2m_intermediary \\\n    m2m_multiple \\\n    m2m_recursive \\\n    m2m_regress \\\n    m2m_signals \\\n    m2m_through \\\n    m2o_recursive \\\n    managers_regress \\\n    many_to_many \\\n    many_to_one \\\n    max_lengths \\\n    migrate_signals \\\n    model_fields \\\n    model_indexes \\\n    model_options \\\n    mutually_referential \\\n    nested_foreign_keys \\\n    null_fk \\\n    null_fk_ordering \\\n    null_queries \\\n    one_to_one \\\n    or_lookups \\\n    order_with_respect_to \\\n    ordering \\\n    pagination \\\n    prefetch_related \\\n    queries \\\n    queryset_pickle \\\n    raw_query \\\n    reverse_lookup \\\n    save_delete_hooks \\\n    schema \\\n    select_for_update \\\n    select_related \\\n    select_related_onetoone \\\n    select_related_regress \\\n    transaction_hooks \\\n    transactions \\\n    update \\\n    update_only_fields\n"
  },
  {
    "path": "testapp/__init__.py",
    "content": ""
  },
  {
    "path": "testapp/migrations/0001_initial.py",
    "content": "# Generated by Django 2.2.8.dev20191112211527 on 2019-11-15 01:38\n\nimport uuid\n\nfrom django.db import migrations, models\nimport django\n\n\nclass Migration(migrations.Migration):\n\n    initial = True\n\n    dependencies = [\n    ]\n\n    operations = [\n        migrations.CreateModel(\n            name='Author',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('name', models.CharField(max_length=100)),\n            ],\n        ),\n        migrations.CreateModel(\n            name='Editor',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('name', models.CharField(max_length=100)),\n            ],\n        ),\n        migrations.CreateModel(\n            name='Post',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('title', models.CharField(max_length=255, verbose_name='title')),\n            ],\n        ),\n        migrations.AddField(\n            model_name='post',\n            name='alt_editor',\n            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='testapp.Editor'),\n        ),\n        migrations.AddField(\n            model_name='post',\n            name='author',\n            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='testapp.Author'),\n        ),\n        migrations.AlterUniqueTogether(\n            name='post',\n            unique_together={('author', 'title', 'alt_editor')},\n        ),\n        migrations.CreateModel(\n            name='Comment',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='testapp.Post')),\n                ('text', models.TextField(verbose_name='text')),\n                ('created_at', models.DateTimeField(default=django.utils.timezone.now)),\n            ],\n        ),\n        migrations.CreateModel(\n            name='UUIDModel',\n            fields=[\n                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),\n            ],\n        ),\n    ]\n"
  },
  {
    "path": "testapp/migrations/0002_test_unique_nullable_part1.py",
    "content": "from django.db import migrations, models\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        ('testapp', '0001_initial'),\n    ]\n\n    operations = [\n        # Issue #38 test prep\n        # Create with a field that is unique *and* nullable so it is implemented with a filtered unique index.\n        migrations.CreateModel(\n            name='TestUniqueNullableModel',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('test_field', models.CharField(max_length=100, null=True, unique=True)),\n            ],\n        ),\n    ]\n"
  },
  {
    "path": "testapp/migrations/0003_test_unique_nullable_part2.py",
    "content": "from django.db import migrations, models\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        ('testapp', '0002_test_unique_nullable_part1'),\n    ]\n\n    operations = [\n        # Issue #38 test\n        # Now remove the null=True to check this transition is correctly handled.\n        migrations.AlterField(\n            model_name='testuniquenullablemodel',\n            name='test_field',\n            field=models.CharField(default='', max_length=100, unique=True),\n            preserve_default=False,\n        ),\n    ]\n"
  },
  {
    "path": "testapp/migrations/0004_test_issue45_unique_type_change_part1.py",
    "content": "from django.db import migrations, models\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        ('testapp', '0003_test_unique_nullable_part2'),\n    ]\n\n    # Issue #45 test prep\n    operations = [\n        # for case 1:\n        migrations.AddField(\n            model_name='testuniquenullablemodel',\n            name='x',\n            field=models.CharField(max_length=10, null=True, unique=True),\n        ),\n\n        # for case 2:\n        migrations.CreateModel(\n            name='TestNullableUniqueTogetherModel',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('a', models.CharField(max_length=50, null=True)),\n                ('b', models.CharField(max_length=50)),\n                ('c', models.CharField(max_length=50)),\n            ],\n            options={\n                'unique_together': {('a', 'b')},\n            },\n        ),\n    ]\n"
  },
  {
    "path": "testapp/migrations/0005_test_issue45_unique_type_change_part2.py",
    "content": "from django.db import migrations, models\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        ('testapp', '0004_test_issue45_unique_type_change_part1'),\n    ]\n\n    # Issue #45 test\n    operations = [\n        # Case 1: changing max_length changes the column type - the filtered UNIQUE INDEX which implements\n        # the nullable unique constraint, should be correctly reinstated after this change of column type\n        # (see also the specific unit test which checks that multiple rows with NULL are allowed)\n        migrations.AlterField(\n            model_name='testuniquenullablemodel',\n            name='x',\n            field=models.CharField(max_length=11, null=True, unique=True),\n        ),\n\n        # Case 2: the filtered UNIQUE INDEX implementing the partially nullable `unique_together` constraint\n        # should be correctly reinstated after this column type change\n        migrations.AlterField(\n            model_name='testnullableuniquetogethermodel',\n            name='a',\n            field=models.CharField(max_length=51, null=True),\n        ),\n        # ...similarly adding another field to the `unique_together` should preserve the constraint correctly\n        migrations.AlterUniqueTogether(\n            name='testnullableuniquetogethermodel',\n            unique_together={('a', 'b', 'c')},\n        ),\n    ]\n"
  },
  {
    "path": "testapp/migrations/0006_test_remove_onetoone_field_part1.py",
    "content": "# Generated by Django 3.0.4 on 2020-04-20 14:59\r\n\r\nfrom django.db import migrations, models\r\nimport django.db.models.deletion\r\n\r\n\r\nclass Migration(migrations.Migration):\r\n\r\n    dependencies = [\r\n        ('testapp', '0005_test_issue45_unique_type_change_part2'),\r\n    ]\r\n\r\n    operations = [\r\n        migrations.CreateModel(\r\n            name='TestRemoveOneToOneFieldModel',\r\n            fields=[\r\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\r\n                ('a', models.CharField(max_length=50)),\r\n                ('b', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='testapp.TestRemoveOneToOneFieldModel')),\r\n            ],\r\n        ),\r\n    ]\r\n"
  },
  {
    "path": "testapp/migrations/0007_test_remove_onetoone_field_part2.py",
    "content": "# Generated by Django 3.0.4 on 2020-04-20 14:59\r\n\r\nfrom django.db import migrations\r\n\r\n\r\nclass Migration(migrations.Migration):\r\n\r\n    dependencies = [\r\n        ('testapp', '0006_test_remove_onetoone_field_part1'),\r\n    ]\r\n\r\n    operations = [\r\n        migrations.RemoveField(\r\n            model_name='testremoveonetoonefieldmodel',\r\n            name='b',\r\n        ),\r\n    ]\r\n"
  },
  {
    "path": "testapp/migrations/__init__.py",
    "content": ""
  },
  {
    "path": "testapp/models.py",
    "content": "import uuid\n\nfrom django.db import models\nfrom django.utils import timezone\n\n\nclass Author(models.Model):\n    name = models.CharField(max_length=100)\n\n\nclass Editor(models.Model):\n    name = models.CharField(max_length=100)\n\n\nclass Post(models.Model):\n    title = models.CharField('title', max_length=255)\n    author = models.ForeignKey(Author, models.CASCADE)\n    # Optional secondary author\n    alt_editor = models.ForeignKey(Editor, models.SET_NULL, blank=True, null=True)\n\n    class Meta:\n        unique_together = (\n            ('author', 'title', 'alt_editor'),\n        )\n\n    def __str__(self):\n        return self.title\n\n\nclass Comment(models.Model):\n    post = models.ForeignKey(Post, on_delete=models.CASCADE)\n    text = models.TextField('text')\n    created_at = models.DateTimeField(default=timezone.now)\n\n    def __str__(self):\n        return self.text\n\n\nclass UUIDModel(models.Model):\n    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)\n\n    def __str__(self):\n        return self.pk\n\n\nclass TestUniqueNullableModel(models.Model):\n    # Issue #38:\n    # This field started off as unique=True *and* null=True so it is implemented with a filtered unique index\n    # Then it is made non-nullable by a subsequent migration, to check this is correctly handled (the index\n    # should be dropped, then a normal unique constraint should be added, now that the column is not nullable)\n    test_field = models.CharField(max_length=100, unique=True)\n\n    # Issue #45 (case 1)\n    # Field used for testing changing the 'type' of a field that's both unique & nullable\n    x = models.CharField(max_length=11, null=True, unique=True)\n\n\nclass TestNullableUniqueTogetherModel(models.Model):\n    class Meta:\n        unique_together = (('a', 'b', 'c'),)\n\n    # Issue #45 (case 2)\n    # Fields used for testing changing the 'type of a field that is in a `unique_together`\n    a = models.CharField(max_length=51, null=True)\n    b = models.CharField(max_length=50)\n    c = models.CharField(max_length=50)\n\n\nclass TestRemoveOneToOneFieldModel(models.Model):\n    # Fields used for testing removing OneToOne field. Verifies that delete_unique do not try to remove indexes\n    # thats already is removed.\n    # b = models.OneToOneField('self', on_delete=models.SET_NULL, null=True)\n    a = models.CharField(max_length=50)\n"
  },
  {
    "path": "testapp/runner.py",
    "content": "from unittest import skip\nfrom django.test.runner import DiscoverRunner\nfrom django.conf import settings\n\n\nEXCLUDED_TESTS = getattr(settings, 'EXCLUDED_TESTS', [])\n\n\nclass ExcludeTestSuiteRunner(DiscoverRunner):\n    def build_suite(self, *args, **kwargs):\n        suite = super().build_suite(*args, **kwargs)\n        for case in suite:\n            cls = case.__class__\n            for attr in dir(cls):\n                if not attr.startswith('test_'):\n                    continue\n                fullname = f'{cls.__module__}.{cls.__name__}.{attr}'\n                if len(list(filter(fullname.startswith, EXCLUDED_TESTS))):\n                    setattr(cls, attr, skip('Does not work on MSSQL')(getattr(cls, attr)))\n\n        return suite\n"
  },
  {
    "path": "testapp/settings.py",
    "content": "import dj_database_url\n\nDATABASES = {\n    'default': dj_database_url.config(default='sqlite:///db.sqlite'),\n    'other': dj_database_url.config(env='DATABASE_URL_OTHER', default='sqlite:///db.sqlite'),\n}\n\nINSTALLED_APPS = (\n    'django.contrib.contenttypes',\n    'django.contrib.staticfiles',\n    'django.contrib.auth',\n    'sql_server.pyodbc',\n    'testapp',\n)\n\n\nTEST_RUNNER = 'testapp.runner.ExcludeTestSuiteRunner'\nEXCLUDED_TESTS = (\n    'aggregation.tests.AggregateTestCase.test_aggregation_subquery_annotation_exists',\n    'aggregation.tests.AggregateTestCase.test_aggregation_subquery_annotation_values_collision',\n    'aggregation.tests.AggregateTestCase.test_count_star',\n    'aggregation.tests.AggregateTestCase.test_distinct_on_aggregate',\n    'aggregation.tests.AggregateTestCase.test_expression_on_aggregation',\n    'aggregation_regress.tests.AggregationTests.test_annotated_conditional_aggregate',\n    'aggregation_regress.tests.AggregationTests.test_annotation_with_value',\n    'aggregation_regress.tests.AggregationTests.test_more_more',\n    'aggregation_regress.tests.AggregationTests.test_more_more_more',\n    'aggregation_regress.tests.AggregationTests.test_ticket_11293',\n    'aggregation_regress.tests.AggregationTests.test_values_list_annotation_args_ordering',\n    'annotations.tests.NonAggregateAnnotationTestCase.test_annotate_exists',\n    'annotations.tests.NonAggregateAnnotationTestCase.test_combined_expression_annotation_with_aggregation',\n    'backends.tests.BackendTestCase.test_queries',\n    'backends.tests.BackendTestCase.test_unicode_password',\n    'backends.tests.FkConstraintsTests.test_disable_constraint_checks_context_manager',\n    'backends.tests.FkConstraintsTests.test_disable_constraint_checks_manually',\n    'backends.tests.LastExecutedQueryTest.test_last_executed_query',\n    'bulk_create.tests.BulkCreateTests.test_bulk_insert_nullable_fields',\n    'constraints.tests.CheckConstraintTests.test_abstract_name',\n    'constraints.tests.CheckConstraintTests.test_database_constraint',\n    'constraints.tests.CheckConstraintTests.test_database_constraint_expression',\n    'constraints.tests.CheckConstraintTests.test_database_constraint_expressionwrapper',\n    'constraints.tests.CheckConstraintTests.test_name',\n    'constraints.tests.UniqueConstraintTests.test_database_constraint',\n    'constraints.tests.UniqueConstraintTests.test_database_constraint_with_condition',\n    'constraints.tests.UniqueConstraintTests.test_name',\n    'custom_lookups.tests.BilateralTransformTests.test_transform_order_by',\n    'datatypes.tests.DataTypesTestCase.test_error_on_timezone',\n    'datetimes.tests.DateTimesTests.test_datetimes_ambiguous_and_invalid_times',\n    'datetimes.tests.DateTimesTests.test_datetimes_returns_available_dates_for_given_scope_and_given_field',\n    'datetimes.tests.DateTimesTests.test_related_model_traverse',\n    'db_functions.comparison.test_cast.CastTests.test_cast_to_integer',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_func',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_iso_weekday_func',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_exact_lookup',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_greaterthan_lookup',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_lessthan_lookup',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_func',\n    'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_week_func',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_func',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_func_with_timezone',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_iso_weekday_func',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_year_exact_lookup',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_year_greaterthan_lookup',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_year_lessthan_lookup',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_ambiguous_and_invalid_times',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_func_with_timezone',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_none',\n    'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_week_func',\n    'db_functions.math.test_degrees.DegreesTests.test_integer',\n    'db_functions.math.test_mod.ModTests.test_float',\n    'db_functions.math.test_power.PowerTests.test_integer',\n    'db_functions.math.test_radians.RadiansTests.test_integer',\n    'db_functions.text.test_md5',\n    'db_functions.text.test_pad.PadTests.test_pad',\n    'db_functions.text.test_replace.ReplaceTests.test_case_sensitive',\n    'db_functions.text.test_sha1',\n    'db_functions.text.test_sha224',\n    'db_functions.text.test_sha256',\n    'db_functions.text.test_sha384',\n    'db_functions.text.test_sha512',\n    'dbshell.tests.DbshellCommandTestCase.test_command_missing',\n    'defer_regress.tests.DeferRegressionTest.test_ticket_23270',\n    'delete.tests.DeletionTests.test_only_referenced_fields_selected',\n    'expressions.tests.BasicExpressionsTests.test_case_in_filter_if_boolean_output_field',\n    'expressions.tests.BasicExpressionsTests.test_filtering_on_annotate_that_uses_q',\n    'expressions.tests.BasicExpressionsTests.test_order_by_exists',\n    'expressions.tests.BasicExpressionsTests.test_subquery_in_filter',\n    'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_right_shift_operator',\n    'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor',\n    'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null',\n    'expressions.tests.ExpressionOperatorTests.test_righthand_power',\n    'expressions.tests.FTimeDeltaTests.test_date_subquery_subtraction',\n    'expressions.tests.FTimeDeltaTests.test_datetime_subquery_subtraction',\n    'expressions.tests.FTimeDeltaTests.test_datetime_subtraction_microseconds',\n    'expressions.tests.FTimeDeltaTests.test_duration_with_datetime_microseconds',\n    'expressions.tests.FTimeDeltaTests.test_invalid_operator',\n    'expressions.tests.FTimeDeltaTests.test_time_subquery_subtraction',\n    'expressions.tests.IterableLookupInnerExpressionsTests.test_expressions_in_lookups_join_choice',\n    'expressions_case.tests.CaseExpressionTests.test_annotate_with_in_clause',\n    'fixtures_regress.tests.TestFixtures.test_loaddata_raises_error_when_fixture_has_invalid_foreign_key',\n    'fixtures_regress.tests.TestFixtures.test_loaddata_with_m2m_to_self',\n    'fixtures_regress.tests.TestFixtures.test_loaddata_with_valid_fixture_dirs',\n    'fixtures_regress.tests.TestFixtures.test_loaddata_works_when_fixture_has_forward_refs',\n    'fixtures_regress.tests.TestFixtures.test_path_containing_dots',\n    'fixtures_regress.tests.TestFixtures.test_pg_sequence_resetting_checks',\n    'fixtures_regress.tests.TestFixtures.test_pretty_print_xml',\n    'fixtures_regress.tests.TestFixtures.test_proxy_model_included',\n    'fixtures_regress.tests.TestFixtures.test_relative_path',\n    'fixtures_regress.tests.TestFixtures.test_relative_path_in_fixture_dirs',\n    'fixtures_regress.tests.TestFixtures.test_ticket_20820',\n    'fixtures_regress.tests.TestFixtures.test_ticket_22421',\n    'get_or_create.tests.UpdateOrCreateTransactionTests.test_creation_in_transaction',\n    'indexes.tests.PartialIndexTests.test_multiple_conditions',\n    'indexes.tests.SchemaIndexesNotPostgreSQLTests.test_create_index_ignores_opclasses',\n    'inspectdb.tests.InspectDBTestCase.test_introspection_errors',\n    'introspection.tests.IntrospectionTests.test_get_constraints',\n    'introspection.tests.IntrospectionTests.test_get_table_description_types',\n    'introspection.tests.IntrospectionTests.test_smallautofield',\n    'invalid_models_tests.test_ordinary_fields.TextFieldTests.test_max_length_warning',\n    'migrate_signals.tests.MigrateSignalTests.test_migrations_only',\n    'model_fields.test_integerfield.PositiveBigIntegerFieldTests',\n    'model_fields.test_jsonfield',\n    'model_indexes.tests.IndexesTests.test_db_tablespace',\n    'ordering.tests.OrderingTests.test_deprecated_values_annotate',\n    'ordering.tests.OrderingTests.test_order_by_fk_attname',\n    'ordering.tests.OrderingTests.test_order_by_pk',\n    'ordering.tests.OrderingTests.test_orders_nulls_first_on_filtered_subquery',\n    'prefetch_related.tests.GenericRelationTests.test_prefetch_GFK_nonint_pk',\n    'queries.test_bulk_update.BulkUpdateNoteTests.test_set_field_to_null',\n    'queries.test_bulk_update.BulkUpdateTests.test_json_field',\n    'queries.test_db_returning',\n    'queries.test_qs_combinators.QuerySetSetOperationTests.test_limits',\n    'queries.test_qs_combinators.QuerySetSetOperationTests.test_ordering_by_f_expression_and_alias',\n    'schema.tests.SchemaTests.test_add_foreign_key_quoted_db_table',\n    'schema.tests.SchemaTests.test_alter_auto_field_quoted_db_column',\n    'schema.tests.SchemaTests.test_alter_auto_field_to_char_field',\n    'schema.tests.SchemaTests.test_alter_auto_field_to_integer_field',\n    'schema.tests.SchemaTests.test_alter_autofield_pk_to_bigautofield_pk_sequence_owner',\n    'schema.tests.SchemaTests.test_alter_autofield_pk_to_smallautofield_pk_sequence_owner',\n    'schema.tests.SchemaTests.test_alter_implicit_id_to_explicit',\n    'schema.tests.SchemaTests.test_alter_int_pk_to_autofield_pk',\n    'schema.tests.SchemaTests.test_alter_int_pk_to_bigautofield_pk',\n    'schema.tests.SchemaTests.test_alter_pk_with_self_referential_field',\n    'schema.tests.SchemaTests.test_alter_primary_key_quoted_db_table',\n    'schema.tests.SchemaTests.test_alter_smallint_pk_to_smallautofield_pk',\n    'schema.tests.SchemaTests.test_char_field_pk_to_auto_field',\n    'schema.tests.SchemaTests.test_inline_fk',\n    'schema.tests.SchemaTests.test_no_db_constraint_added_during_primary_key_change',\n    'schema.tests.SchemaTests.test_remove_field_check_does_not_remove_meta_constraints',\n    'schema.tests.SchemaTests.test_remove_field_unique_does_not_remove_meta_constraints',\n    'schema.tests.SchemaTests.test_remove_unique_together_does_not_remove_meta_constraints',\n    'schema.tests.SchemaTests.test_text_field_with_db_index',\n    'schema.tests.SchemaTests.test_unique_and_reverse_m2m',\n    'schema.tests.SchemaTests.test_unique_no_unnecessary_fk_drops',\n    'schema.tests.SchemaTests.test_unique_together_with_fk',\n    'schema.tests.SchemaTests.test_unique_together_with_fk_with_existing_index',\n    'select_for_update.tests.SelectForUpdateTests.test_for_update_after_from',\n)\n\nSECRET_KEY = \"django_tests_secret_key\"\n\n# Use a fast hasher to speed up tests.\nPASSWORD_HASHERS = [\n    'django.contrib.auth.hashers.MD5PasswordHasher',\n]\n"
  },
  {
    "path": "testapp/tests/__init__.py",
    "content": ""
  },
  {
    "path": "testapp/tests/test_constraints.py",
    "content": "from django.db.utils import IntegrityError\nfrom django.test import TestCase, skipUnlessDBFeature\n\nfrom ..models import (\n    Author, Editor, Post,\n    TestUniqueNullableModel, TestNullableUniqueTogetherModel,\n)\n\n\n@skipUnlessDBFeature('supports_nullable_unique_constraints')\nclass TestNullableUniqueColumn(TestCase):\n    def test_multiple_nulls(self):\n        # Issue #45 (case 1) - after field `x` has had its type changed, the filtered UNIQUE\n        # INDEX which is implementing the nullable unique constraint should still be correctly\n        # in place - i.e. allowing multiple NULLs but still enforcing uniqueness of non-NULLs\n\n        # Allowed\n        TestUniqueNullableModel.objects.create(x=None, test_field='randomness')\n        TestUniqueNullableModel.objects.create(x=None, test_field='doesntmatter')\n\n        # Disallowed\n        TestUniqueNullableModel.objects.create(x=\"foo\", test_field='irrelevant')\n        with self.assertRaises(IntegrityError):\n            TestUniqueNullableModel.objects.create(x=\"foo\", test_field='nonsense')\n\n\n@skipUnlessDBFeature('supports_partially_nullable_unique_constraints')\nclass TestPartiallyNullableUniqueTogether(TestCase):\n    def test_partially_nullable(self):\n        # Check basic behaviour of `unique_together` where at least 1 of the columns is nullable\n\n        # It should be possible to have 2 rows both with NULL `alt_editor`\n        author = Author.objects.create(name=\"author\")\n        Post.objects.create(title=\"foo\", author=author)\n        Post.objects.create(title=\"foo\", author=author)\n\n        # But `unique_together` is still enforced for non-NULL values\n        editor = Editor.objects.create(name=\"editor\")\n        Post.objects.create(title=\"foo\", author=author, alt_editor=editor)\n        with self.assertRaises(IntegrityError):\n            Post.objects.create(title=\"foo\", author=author, alt_editor=editor)\n\n    def test_after_type_change(self):\n        # Issue #45 (case 2) - after one of the fields in the `unique_together` has had its\n        # type changed in a migration, the constraint should still be correctly enforced\n\n        # Multiple rows with a=NULL are considered different\n        TestNullableUniqueTogetherModel.objects.create(a=None, b='bbb', c='ccc')\n        TestNullableUniqueTogetherModel.objects.create(a=None, b='bbb', c='ccc')\n\n        # Uniqueness still enforced for non-NULL values\n        TestNullableUniqueTogetherModel.objects.create(a='aaa', b='bbb', c='ccc')\n        with self.assertRaises(IntegrityError):\n            TestNullableUniqueTogetherModel.objects.create(a='aaa', b='bbb', c='ccc')\n"
  },
  {
    "path": "testapp/tests/test_expressions.py",
    "content": "from unittest import skipUnless\n\nfrom django import VERSION\nfrom django.db.models import IntegerField\nfrom django.db.models.expressions import Case, Exists, OuterRef, Subquery, Value, When\nfrom django.test import TestCase\n\nfrom ..models import Author, Comment, Post\n\nDJANGO3 = VERSION[0] >= 3\n\n\nclass TestSubquery(TestCase):\n    def setUp(self):\n        self.author = Author.objects.create(name=\"author\")\n        self.post = Post.objects.create(title=\"foo\", author=self.author)\n\n    def test_with_count(self):\n        newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')\n        Post.objects.annotate(\n            post_exists=Subquery(newest.values('text')[:1])\n        ).filter(post_exists=True).count()\n\n\nclass TestExists(TestCase):\n    def setUp(self):\n        self.author = Author.objects.create(name=\"author\")\n        self.post = Post.objects.create(title=\"foo\", author=self.author)\n\n    def test_with_count(self):\n        Post.objects.annotate(\n            post_exists=Exists(Post.objects.all())\n        ).filter(post_exists=True).count()\n\n    @skipUnless(DJANGO3, \"Django 3 specific tests\")\n    def test_with_case_when(self):\n        author = Author.objects.annotate(\n            has_post=Case(\n                When(Exists(Post.objects.filter(author=OuterRef('pk')).values('pk')), then=Value(1)),\n                default=Value(0),\n                output_field=IntegerField(),\n            )\n        ).get()\n        self.assertEqual(author.has_post, 1)\n\n    @skipUnless(DJANGO3, \"Django 3 specific tests\")\n    def test_order_by_exists(self):\n        author_without_posts = Author.objects.create(name=\"other author\")\n        authors_by_posts = Author.objects.order_by(Exists(Post.objects.filter(author=OuterRef('pk'))).desc())\n        self.assertSequenceEqual(authors_by_posts, [self.author, author_without_posts])\n\n        authors_by_posts = Author.objects.order_by(Exists(Post.objects.filter(author=OuterRef('pk'))).asc())\n        self.assertSequenceEqual(authors_by_posts, [author_without_posts, self.author])\n"
  },
  {
    "path": "testapp/tests/test_fields.py",
    "content": "from django.test import TestCase\n\nfrom ..models import UUIDModel\n\n\nclass TestUUIDField(TestCase):\n    def test_create(self):\n        UUIDModel.objects.create()\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist =\n       {py36,py37}-django22,\n       {py36,py37,py38}-django30,\n       {py36,py37,py38}-django31,\n\n[testenv]\npassenv =\n    DATABASE_URL\n    DATABASE_URL_OTHER\n\nwhitelist_externals =\n    /bin/bash\n\ncommands =\n    python manage.py test --keepdb\n    python manage.py install_regex_clr test_default\n    bash test.sh\n\ndeps =\n    django22: django==2.2.*\n    django30: django>=3.0a1,<3.1\n    django31: django>=3.1,<3.2\n    dj-database-url==0.5.0\n"
  }
]