# Path: psqlextra/expressions.py
# class ExcludedCol(expressions.Expression):
#     """References a column in PostgreSQL's special EXCLUDED column, which is
#     used in upserts to refer to the data about to be inserted/updated.
# 
#     See: https://www.postgresql.org/docs/9.5/sql-insert.html#SQL-ON-CONFLICT
#     """
# 
#     def __init__(self, name: str):
#         self.name = name
# 
#     def as_sql(self, compiler, connection):
#         quoted_name = connection.ops.quote_name(self.name)
#         return f"EXCLUDED.{quoted_name}", tuple()
# 
# Path: psqlextra/fields/hstore_field.py
# class HStoreField(DjangoHStoreField):
#     """Improved version of Django's :see:HStoreField that adds support for
#     database-level constraints.
# 
#     Notes:
#         - For the implementation of uniqueness, see the
#           custom database back-end.
#     """
# 
#     def __init__(
#         self,
#         *args,
#         uniqueness: Optional[List[Union[str, Tuple[str, ...]]]] = None,
#         required: Optional[List[str]] = None,
#         **kwargs
#     ):
#         """Initializes a new instance of :see:HStoreField.
# 
#         Arguments:
#             uniqueness:
#                 List of keys to enforce as unique. Use tuples
#                 to enforce multiple keys together to be unique.
# 
#             required:
#                 List of keys that should be enforced as required.
#         """
# 
#         super(HStoreField, self).__init__(*args, **kwargs)
# 
#         self.uniqueness = uniqueness
#         self.required = required
# 
#     def get_prep_value(self, value):
#         """Override the base class so it doesn't cast all values to strings.
# 
#         psqlextra supports expressions in hstore fields, so casting all
#         values to strings is a bad idea.
#         """
# 
#         value = Field.get_prep_value(self, value)
# 
#         if isinstance(value, dict):
#             prep_value = {}
#             for key, val in value.items():
#                 if isinstance(val, Expression):
#                     prep_value[key] = val
#                 elif val is not None:
#                     prep_value[key] = str(val)
#                 else:
#                     prep_value[key] = val
# 
#             value = prep_value
# 
#         if isinstance(value, list):
#             value = [str(item) for item in value]
# 
#         return value
# 
#     def deconstruct(self):
#         """Gets the values to pass to :see:__init__ when re-creating this
#         object."""
# 
#         name, path, args, kwargs = super(HStoreField, self).deconstruct()
# 
#         if self.uniqueness is not None:
#             kwargs["uniqueness"] = self.uniqueness
# 
#         if self.required is not None:
#             kwargs["required"] = self.required
# 
#         return name, path, args, kwargs
# 
# Path: tests/fake_model.py
# def get_fake_model(fields=None, model_base=PostgresModel, meta_options={}):
#     """Defines a fake model and creates it in the database."""
# 
#     model = define_fake_model(fields, model_base, meta_options)
# 
#     with connection.schema_editor() as schema_editor:
#         schema_editor.create_model(model)
# 
#     return model


import django
import pytest
from django.db import models
from django.db.models import Q
from django.db.models.expressions import CombinedExpression, Value
from psqlextra.expressions import ExcludedCol
from psqlextra.fields import HStoreField
from .fake_model import get_fake_model
        rows=[
            dict(first_name="Swen", last_name="Test"),
            dict(first_name="Henk", last_name="Kooij"),
        ],
    )

    row_a.refresh_from_db()
    assert row_a.last_name == "Test"

    row_b.refresh_from_db()
    assert row_b.last_name == "Kooij"


def test_upsert_bulk_no_rows():
    """Tests whether bulk_upsert doesn't crash when specifying no rows or a
    falsy value."""

    model = get_fake_model(
        {"name": models.CharField(max_length=255, null=True, unique=True)}
    )

    model.objects.bulk_upsert(conflict_target=["name"], rows=[])

    model.objects.bulk_upsert(conflict_target=["name"], rows=None)


def test_bulk_upsert_return_models():
    """Tests whether models are returned instead of dictionaries when
    specifying the return_model=True argument."""


# Path: psqlextra/expressions.py
# class ExcludedCol(expressions.Expression):
#     """References a column in PostgreSQL's special EXCLUDED column, which is
#     used in upserts to refer to the data about to be inserted/updated.
# 
#     See: https://www.postgresql.org/docs/9.5/sql-insert.html#SQL-ON-CONFLICT
#     """
# 
#     def __init__(self, name: str):
#         self.name = name
# 
#     def as_sql(self, compiler, connection):
#         quoted_name = connection.ops.quote_name(self.name)
#         return f"EXCLUDED.{quoted_name}", tuple()
# 
# Path: psqlextra/fields/hstore_field.py
# class HStoreField(DjangoHStoreField):
#     """Improved version of Django's :see:HStoreField that adds support for
#     database-level constraints.
# 
#     Notes:
#         - For the implementation of uniqueness, see the
#           custom database back-end.
#     """
# 
#     def __init__(
#         self,
#         *args,
#         uniqueness: Optional[List[Union[str, Tuple[str, ...]]]] = None,
#         required: Optional[List[str]] = None,
#         **kwargs
#     ):
#         """Initializes a new instance of :see:HStoreField.
# 
#         Arguments:
#             uniqueness:
#                 List of keys to enforce as unique. Use tuples
#                 to enforce multiple keys together to be unique.
# 
#             required:
#                 List of keys that should be enforced as required.
#         """
# 
#         super(HStoreField, self).__init__(*args, **kwargs)
# 
#         self.uniqueness = uniqueness
#         self.required = required
# 
#     def get_prep_value(self, value):
#         """Override the base class so it doesn't cast all values to strings.
# 
#         psqlextra supports expressions in hstore fields, so casting all
#         values to strings is a bad idea.
#         """
# 
#         value = Field.get_prep_value(self, value)
# 
#         if isinstance(value, dict):
#             prep_value = {}
#             for key, val in value.items():
#                 if isinstance(val, Expression):
#                     prep_value[key] = val
#                 elif val is not None:
#                     prep_value[key] = str(val)
#                 else:
#                     prep_value[key] = val
# 
#             value = prep_value
# 
#         if isinstance(value, list):
#             value = [str(item) for item in value]
# 
#         return value
# 
#     def deconstruct(self):
#         """Gets the values to pass to :see:__init__ when re-creating this
#         object."""
# 
#         name, path, args, kwargs = super(HStoreField, self).deconstruct()
# 
#         if self.uniqueness is not None:
#             kwargs["uniqueness"] = self.uniqueness
# 
#         if self.required is not None:
#             kwargs["required"] = self.required
# 
#         return name, path, args, kwargs
# 
# Path: tests/fake_model.py
# def get_fake_model(fields=None, model_base=PostgresModel, meta_options={}):
#     """Defines a fake model and creates it in the database."""
# 
#     model = define_fake_model(fields, model_base, meta_options)
# 
#     with connection.schema_editor() as schema_editor:
#         schema_editor.create_model(model)
# 
#     return model


# Path: tests/test_upsert.py
import django
import pytest
from django.db import models
from django.db.models import Q
from django.db.models.expressions import CombinedExpression, Value
from psqlextra.expressions import ExcludedCol
from psqlextra.fields import HStoreField
from .fake_model import get_fake_model

        rows=[
            dict(first_name="Swen", last_name="Test"),
            dict(first_name="Henk", last_name="Kooij"),
        ],
    )

    row_a.refresh_from_db()
    assert row_a.last_name == "Test"

    row_b.refresh_from_db()
    assert row_b.last_name == "Kooij"


def test_upsert_bulk_no_rows():
    """Tests whether bulk_upsert doesn't crash when specifying no rows or a
    falsy value."""

    model = get_fake_model(
        {"name": models.CharField(max_length=255, null=True, unique=True)}
    )

    model.objects.bulk_upsert(conflict_target=["name"], rows=[])

    model.objects.bulk_upsert(conflict_target=["name"], rows=None)


def test_bulk_upsert_return_models():
    """Tests whether models are returned instead of dictionaries when
    specifying the return_model=True argument."""


    model = get_fake_model(