# Question about adding database-specific functionality to Django ORM

**URL:** <https://forum.djangoproject.com/t/question-about-adding-database-specific-functionality-to-django-orm/2074>\
**Category:** Using Django\
**Created:** [April 21, 2020, 11:39pm UTC](https://forum.djangoproject.com/t/question-about-adding-database-specific-functionality-to-django-orm/2074 "2020-04-21T23:39:44Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![techknowfile](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/techknowfile/32/1100_2.png) [@techknowfile](https://forum.djangoproject.com/u/techknowfile)\
**Post date:** [April 21, 2020, 11:39pm UTC](https://forum.djangoproject.com/t/question-about-adding-database-specific-functionality-to-django-orm/2074/1 "2020-04-21T23:39:44Z")

</div>

I’m in the process of trying to get some level of integration between the Django ORM and Sql Server Temporal Tables. By overriding a 3rd party SQL Server backend, I am now able to create (migrate) temporal tables. Next step is to implement .as\_of() so that I can “time-travel” to a specific state of my models. Ultimately, this means appending something to the effect of  
`FOR SYSTEM_TIME AS OF %s' ;`  
to the select statements, and now my goal is to add this functionality as cleanly as possible. IE, I don’t want to simply make a function in a custom manager that runs cursor.execute – I’d like to be able to be able to use QuerySets and chaining if at all possible. From my understanding, this should be possible by somehow creating a new clause – I just can’t seem to nail down how that’s accomplished

I realize this is a very general question that requires understanding of many different parts of the ORM, but I was hoping someone could point me in the direction of some source code that might shed some light on the proper way to accomplish this.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [April 22, 2020, 1:43pm UTC](https://forum.djangoproject.com/t/question-about-adding-database-specific-functionality-to-django-orm/2074/2 "2020-04-22T13:43:13Z")

</div>

Hi @techknowfile

Welcome to the forum!

Injecting an extra SQL clause is a bit tricky. You need to do it in the SQLCompiler _or_ to rewrite the query after it’s made.

My extension library Django-MySQL uses the latter technique to add MySQL-specific query hints: [https://django-mysql.readthedocs.io/en/latest/queryset\_extensions.html#query-hints](https://django-mysql.readthedocs.io/en/latest/queryset_extensions.html#query-hints) . But I think if I were to recreate it, I’d try the former technique. Additionally it should be doing the rewriting not through monkey-patching cursor.execute, but through [database instrumentation](https://docs.djangoproject.com/en/3.0/topics/db/instrumentation/).

Additionally, temporal tables are an SQL standard feature and supported also in at MariaDB and Oracle (at laest). If you’d like to find or create a ticket to add support for them in Django core, that would be exciting to see.

Thanks,

Adam

---

<div class="post-metadata">

**Author:** ![techknowfile](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/techknowfile/32/1100_2.png) [@techknowfile](https://forum.djangoproject.com/u/techknowfile)\
**Post date:** [April 22, 2020, 10:56pm UTC](https://forum.djangoproject.com/t/question-about-adding-database-specific-functionality-to-django-orm/2074/3 "2020-04-22T22:56:57Z")

</div>

It made my morning to see that you were the one who replied! I probably had the Django-MySQL github open while I was initially writing this post. It was just a glance through, but I saw enough to understand that you were exploiting comments that would later be parsed in order to modify the running sql command (though I didn’t see how that last step gets “hooked” into the process).

I’m going to take another pass through your library to see if I can tease the rest of it apart, and I’ll probably take a swing at getting an idea of how I’d override the sql compiler.

This definitely sounds like it could be a useful feature to have built out for the community. Will consider it for my first post-college open source contribution if I can get some momentum on my own project. [This ticket](https://code.djangoproject.com/ticket/5793) highlighted the first useful feature that I was hoping already existed for adding to the CREATE TABLE clause during migration (needed to add a flag to the meta class to mark the table as temporal). Due to nothing being implemented to allow for this, my current workaround to create a temporal table is very hacky.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [April 23, 2020, 7:32am UTC](https://forum.djangoproject.com/t/question-about-adding-database-specific-functionality-to-django-orm/2074/4 "2020-04-23T07:32:24Z")

</div>

> [@techknowfile](#):
>
> (though I didn’t see how that last step gets “hooked” into the process).

At startup, [it applies monkey patches](https://github.com/adamchainz/django-mysql/blob/2e4bb08488f737306f22b29ff217e2a33823d276/src/django_mysql/apps.py#L16) that [intercept and rewrite queries](https://github.com/adamchainz/django-mysql/blob/2e4bb08488f737306f22b29ff217e2a33823d276/src/django_mysql/monkey_patches.py#L15). As I said, the database instrumentation feature would be a cleaner implementation.

I found a way to make a database instrumentation hook that always applies (rather than as a context manager) [in scout-apm](https://github.com/scoutapp/scout_apm_python/blob/639b7ac6a6a859e17db5c2e6b4d6ce2366ddd7a4/src/scout_apm/django/instruments/sql.py#L31), that I’ll copy over to Django-MySQL some time.

> [@techknowfile](#):
>
> I’m going to take another pass through your library to see if I can tease the rest of it apart, and I’ll probably take a swing at getting an idea of how I’d override the sql compiler.

Yeah that involves a few moving parts, iirc you’ll need to first create a custom database backend through subclassing.

> [@techknowfile](#):
>
> my current workaround to create a temporal table is very hacky.

Idk what way you’ve taken, but the “least hacky” way would be:

1. Create model
2. Create migration to add it
3. Run `sqlmigrate` and `sqlmigrate --backwards` on it to get forwards and reverse SQL for your database
4. Put that SQL into a `RunSQL` operation’s `sql` and `reverse_sql` with the `RunSQL`’s `state_operations` set to contain the intiail `CreateModel`
5. Change `sql` to include the clause for system versioning
