Repository: googleapis/python-spanner-django

Issue:
django-test-suite: many_to_one test_select_related fails due to date_trunc_sql being unimplemented
- [ ] test_select_related (many_to_one)
- [ ] test_object_tools_displayed_no_add_permission (admin_changelist.tests.ChangeListTests)
- [ ] test_computed_list_display_localization (admin_changelist.tests.ChangeListTests)

fail currently with
```shell
======================================================================
ERROR: test_select_related (many_to_one.tests.ManyToOneTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/tests/many_to_one/tests.py", line 331, in test_select_related
    list(Article.objects.select_related().dates('pub_date', 'day')),
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 274, in __iter__
    self._fetch_all()
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 1242, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 182, in __iter__
    for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 1085, in results_iter
    results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 1120, in execute_sql
    sql, params = self.as_sql()
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 474, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 54, in pre_sql_setup
    self.setup_query()
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 45, in setup_query
    self.select, self.klass_info, self.annotation_col_map = self.get_select()
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 254, in get_select
    sql, params = self.compile(col, select_format=True)
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 405, in compile
    sql, params = node.as_sql(self, self.connection)
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/models/functions/datetime.py", line 183, in as_sql
    sql = connection.ops.date_trunc_sql(self.kind, inner_sql)
  File "/Users/emmanuelodeke/Desktop/spanner-orm/django_tests/django/django/db/backends/base/operations.py", line 110, in date_trunc_sql
    raise NotImplementedError('subclasses of BaseDatabaseOperations may require a date_trunc_sql() method.')
NotImplementedError: subclasses of BaseDatabaseOperations may require a date_trunc_sql() method.
```


Discussion:

Resolving patch:
diff --git a/spanner/django/operations.py b/spanner/django/operations.py
--- a/spanner/django/operations.py
+++ b/spanner/django/operations.py
@@ -105,3 +105,12 @@ def datetime_extract_sql(self, lookup_type, field_name, tzname):
         tzname = self.connection.timezone if settings.USE_TZ else 'UTC'
         lookup_type = self.extract_names.get(lookup_type, lookup_type)
         return 'EXTRACT(%s FROM %s AT TIME ZONE "%s")' % (lookup_type, field_name, tzname)
+
+    def date_trunc_sql(self, lookup_type, field_name):
+        # https://cloud.google.com/spanner/docs/functions-and-operators#date_trunc
+        return 'DATE_TRUNC(%s, %s)' % (field_name, lookup_type)
+
+    def datetime_trunc_sql(self, lookup_type, field_name, tzname):
+        # https://cloud.google.com/spanner/docs/functions-and-operators#timestamp_trunc
+        tzname = self.connection.timezone if settings.USE_TZ else 'UTC'
+        return 'TIMESTAMP_TRUNC(%s, %s, "%s")' % (field_name, lookup_type, tzname)


Test patch: