Databases and the D Standard Library

Nicholas Wilson via Digitalmars-d digitalmars-d at puremagic.com
Tue Jan 3 01:53:19 PST 2017


On Tuesday, 3 January 2017 at 08:09:54 UTC, Chris Wright wrote:
> On Mon, 02 Jan 2017 21:25:42 -0800, Adam Wilson wrote:
>> As far as I am aware, the only way to meet those requirements 
>> is to use a base-class model. Is there something I am missing?
>
> Templates. Templates everywhere.
>
> Every method in your application that might possibly touch a 
> database, or touch anything that touches a database, and so on, 
> needs to be templated according to what type of database might 
> be used.

That limits you to one DB per compilation or craploads of 
template bloat.

There are a number variables here: the number of DB backends you 
wish to support (b), the number of DB backends you actually use 
at runtime (r), the number of symbols (not quite the word I'm 
looking for but, oh well) you need to represent an abstract 
backend API (s),the number of class types you use to abstract the 
backend (c) and the number of template you use to abstract the 
back end (t).

b is ideally fixed at "all the backends"
r is variable and dependent on the application (e.g. I may only 
care for Postgres, but someone else may wish to support many SQL 
DBs). If r == 1 then a template approach is acceptable.

s is a function of the dissimilarity of the backends you wish to 
support. Breaking the problem up into SQL like, graph-like and 
KV-store is a tradeoff somewhere between having "one DB 
(interface) to rule them all" and one interface for each backend.

c + t = s

What this represents is a tradeoff between compile time dispatch 
and runtime dispatch. As s moves from being all classes to more 
templates + structs (from the "bottom up"), the last layer of 
dynamic dispatch before the static dispatch of the templates 
becomes an algebraic type selection (i.e. check the tag, choose 
the type, and then static dispatch).

I believe the sweet spot for this lies at the point where the 
dissimilarity of similar backends becomes apparent after the 
start of a logical operation. Or put another way the point where 
I know the result that I want and no longer care about any 
implementation details.

As an example using a compute API (sorry I don't know much about 
DBs): launching a kernel represents a single logical operation 
but is in fact many driver calls. If one wishes to abstract the 
compute API then this point becomes the point I would choose.

Finding those points will probably not be easy and may be 
different for different people, but it is worth considering.

</ramble>


More information about the Digitalmars-d mailing list