From: Owen Jacobson on
On 2010-06-27 22:51:59 -0400, Carl Banks said:

> On Jun 27, 3:20�pm, Roy Smith <r...(a)panix.com> wrote:
>> In article
>> <14e44c9c-04d9-452d-b544-498adfaf7...(a)d8g2000yqf.googlegroups.com>,
>> �Carl Banks <pavlovevide...(a)gmail.com> wrote:
>>
>>
>>
>>> Seriously, almost every other kind of library uses a binary API. What
>>> makes databases so special that they need a string-command based API?
>>> How about this instead (where this a direct binary interface to the
>>> library):
>>
>>> results = rdb_query(table = model,
>>> � � � � � � � � � � columns = [model.name, model.number])
>>
>>> results = rdb_inner_join(tables = [records,tags],
>>> � � � � � � � � � � � � �joins = [(records.id,tags.record_id)]),
>>> � � � � � � � � � � � � �columns = [record.name, tag.name])
>>
>>> Well, we know the real reason is that C, Java, and friends lack
>>> expressiveness and so constructing a binary query is an ASCII
>>> nightmare. �Still, it hasn't stopped binary APIs in other kinds of
>>> libraries.
>>
>> Well, the answer to that one is simple. �SQL, in the hands of somebody
>> like me, can be used to express a few pathetic joins and what I do with
>> it could probably be handled with the kind of API you're describing. �
>> But, the language has far more expressivity than that, and a
>> domain-specific language is really a good fit for what it can do.
>
> I'm not the biggest expert on SQL ever, but the only thing I can think
> of is expressions. Statements don't express anything very complex,
> and could straightforwardly be represented by function calls. But
> it's a fair point.

Off the top of my head, I can think of a few things that would be
tricky to turn into an API:

* Aggregation (GROUP BY, aggregate functions over arbitrary
expressions, HAVING clauses).
* CASE expressions.
* Subqueries.
* Recursive queries (in DBMSes that support them).
* Window clauses (likewise).
* Set operations between queries (UNION, DIFFERENCE, INTERSECT).
* A surprisingly rich set of JOIN clauses beyond the obvious inner
natural joins.
* Various DBMS-specific locking hints.
* Computed inserts and updates.
* Updates and deletes that include joins.
* RETURNING lists on modification queries.
* Explicit (DBMS-side) cursors.

This is by no means an exhaustive list.

Of course, it's possible to represent all of this via an API rather
than a language, and libraries like SQLAlchemy make a reasonable
attempt�at doing just that. However, not every programming language has
the kind of structural flexibility to do that well: a library similar
to SQLalchemy would be incredibly clunky (if it worked at all) in, say,
Java or C#, and it'd be nearly impossible to pull off in C. Even LDAP,
which is defined more in terms of APIs than languages, forgoes trying
to define a predicate API and uses a domain-specific filtering language
instead.

There's certainly a useful subset of SQL that could be trivially
replaced with an API. Simple by-the-numbers CRUD queries don't exercise
much of SQL's power. In fact, we can do that already: any ORM can
handle that level just fine.

-o

From: Owen Jacobson on
On 2010-06-27 22:51:59 -0400, Carl Banks said:

> On Jun 27, 3:20�pm, Roy Smith <r...(a)panix.com> wrote:
>> In article
>> <14e44c9c-04d9-452d-b544-498adfaf7...(a)d8g2000yqf.googlegroups.com>,
>> �Carl Banks <pavlovevide...(a)gmail.com> wrote:
>>
>>
>>
>>> Seriously, almost every other kind of library uses a binary API. What
>>> makes databases so special that they need a string-command based API?
>>> How about this instead (where this a direct binary interface to the
>>> library):
>>
>>> results = rdb_query(table = model,
>>> � � � � � � � � � � columns = [model.name, model.number])
>>
>>> results = rdb_inner_join(tables = [records,tags],
>>> � � � � � � � � � � � � �joins = [(records.id,tags.record_id)]),
>>> � � � � � � � � � � � � �columns = [record.name, tag.name])
>>
>>> Well, we know the real reason is that C, Java, and friends lack
>>> expressiveness and so constructing a binary query is an ASCII
>>> nightmare. �Still, it hasn't stopped binary APIs in other kinds of
>>> libraries.
>>
>> Well, the answer to that one is simple. �SQL, in the hands of somebody
>> like me, can be used to express a few pathetic joins and what I do with
>> it could probably be handled with the kind of API you're describing. �
>> But, the language has far more expressivity than that, and a
>> domain-specific language is really a good fit for what it can do.
>
> I'm not the biggest expert on SQL ever, but the only thing I can think
> of is expressions. Statements don't express anything very complex,
> and could straightforwardly be represented by function calls. But
> it's a fair point.

Off the top of my head, I can think of a few things that would be
tricky to turn into an API:

* Aggregation (GROUP BY, aggregate functions over arbitrary
expressions, HAVING clauses).
* CASE expressions.
* Subqueries.
* Recursive queries (in DBMSes that support them).
* Window clauses (likewise).
* Set operations between queries (UNION, DIFFERENCE, INTERSECT).
* A surprisingly rich set of JOIN clauses beyond the obvious inner
natural joins.
* Various DBMS-specific locking hints.
* Computed inserts and updates.
* Updates and deletes that include joins.
* RETURNING lists on modification queries.
* Explicit (DBMS-side) cursors.

This is by no means an exhaustive list.

Of course, it's possible to represent all of this via an API rather
than a language, and libraries like SQLAlchemy make a reasonable
attempt�at doing just that. However, not every programming language has
the kind of structural flexibility to do that well: a library similar
to SQLalchemy would be incredibly clunky (if it worked at all) in, say,
Java or C#, and it'd be nearly impossible to pull off in C. Even LDAP,
which is defined more in terms of APIs than languages, forgoes trying
to define a predicate API and uses a domain-specific filtering language
instead.

There's certainly a useful subset of SQL that could be trivially
replaced with an API. Simple by-the-numbers CRUD queries don't exercise
much of SQL's power. In fact, we can do that already: any ORM can
handle that level just fine.

-o

From: Ben Finney on
Carl Banks <pavlovevidence(a)gmail.com> writes:

> On Jun 27, 4:35 pm, Ben Finney <ben+pyt...(a)benfinney.id.au> wrote:
> > Carl Banks <pavlovevide...(a)gmail.com> writes:
> > > Seriously, almost every other kind of library uses a binary API.
> >
> > Except for the huge number that deal with text protocols or languages.
>
> No, not really. Almost all types of libraries have binary APIs,
> including those that deal with text protocols or language. Any
> control with string commands is something that's built on top of the
> binary API.

I don't know what you mean by this.

Are you referring to the operating system's function call API? It's
trivially true that the OS function call API is “binary”, but that
doesn't seem useful for distinguishing; by that definiition, SQL isn't a
“library API” at all. So I assumed you didn't mean that.

Rather, I was taking you to mean the network API used for communicating
with the server; and it's in that context that I'm saying there are a
huge number of text-based network APIs.

If that's not what you mean either, then I need you to explain.

> I'm disappointed, usually when you sit on your reinforced soapbox and
> pretense the air of infinite expertise you at least use reasonable
> logic.

Kindly stop inventing straw men to attack; I deny the position you're
painting for me.

> Also, I was asking about databases. "SQL is a text language" is not
> the answer to the question "Why do RDBs use string commands instead of
> binary APIs"?

To that question, I'd say that SQL isn't a library API, but rather a
network API and a command API, and is thus well implemented with textual
commands.

--
\ “[W]e are still the first generation of users, and for all that |
`\ we may have invented the net, we still don't really get it.” |
_o__) —Douglas Adams |
Ben Finney
From: Carl Banks on
On Jun 27, 8:19 pm, Owen Jacobson <angrybald...(a)gmail.com> wrote:
> On 2010-06-27 22:51:59 -0400, Carl Banks said:
> > On Jun 27, 3:20 pm, Roy Smith <r...(a)panix.com> wrote:
> >> In article
> >> <14e44c9c-04d9-452d-b544-498adfaf7...(a)d8g2000yqf.googlegroups.com>,
> >> Carl Banks <pavlovevide...(a)gmail.com> wrote:
>
> >>> Seriously, almost every other kind of library uses a binary API. What
> >>> makes databases so special that they need a string-command based API?
> >>> How about this instead (where this a direct binary interface to the
> >>> library):
>
> >>> results = rdb_query(table = model,
> >>> columns = [model.name, model.number])
>
> >>> results = rdb_inner_join(tables = [records,tags],
> >>> joins = [(records.id,tags.record_id)]),
> >>> columns = [record.name, tag.name])
>
> >>> Well, we know the real reason is that C, Java, and friends lack
> >>> expressiveness and so constructing a binary query is an ASCII
> >>> nightmare. Still, it hasn't stopped binary APIs in other kinds of
> >>> libraries.
>
> >> Well, the answer to that one is simple. SQL, in the hands of somebody
> >> like me, can be used to express a few pathetic joins and what I do with
> >> it could probably be handled with the kind of API you're describing.
> >> But, the language has far more expressivity than that, and a
> >> domain-specific language is really a good fit for what it can do.
>
> > I'm not the biggest expert on SQL ever, but the only thing I can think
> > of is expressions.  Statements don't express anything very complex,
> > and could straightforwardly be represented by function calls.  But
> > it's a fair point.
>
> Off the top of my head, I can think of a few things that would be
> tricky to turn into an API:
>
>  * Aggregation (GROUP BY, aggregate functions over arbitrary
> expressions, HAVING clauses).
>  * CASE expressions.
>  * Subqueries.
>  * Recursive queries (in DBMSes that support them).
>  * Window clauses (likewise).
>  * Set operations between queries (UNION, DIFFERENCE, INTERSECT).
>  * A surprisingly rich set of JOIN clauses beyond the obvious inner
> natural joins.
>  * Various DBMS-specific locking hints.
>  * Computed inserts and updates.
>  * Updates and deletes that include joins.
>  * RETURNING lists on modification queries.
>  * Explicit (DBMS-side) cursors.
>
> This is by no means an exhaustive list.

I don't know the exact details of all of these, but I'm going to opine
that at least some of these are easily expressible with a function
call API. Perhaps more naturally than with string queries. For
instance, set operations:

query1 = rdb_query(...)
query2 = rdb_query(...)

final_query = rdb_union(query1,query2)

or

final_query = query1 & query2

I'm not sure why GROUP BY couldn't be expressed by a keyword
argument. The complexity of aggregate functions and computed inserts
comes mainly from expressions (which Roy Smith already mentioned), the
actual statements are simple.


> Of course, it's possible to represent all of this via an API rather
> than a language, and libraries like SQLAlchemy make a reasonable
> attempt at doing just that. However, not every programming language has
> the kind of structural flexibility to do that well: a library similar
> to SQLalchemy would be incredibly clunky (if it worked at all) in, say,
> Java or C#, and it'd be nearly impossible to pull off in C.

Yeah, which was kind of my original theory.


Carl Banks
From: Stephen Hansen on
On 6/27/10 7:51 PM, Carl Banks wrote:
> I'm not the biggest expert on SQL ever, but the only thing I can think
> of is expressions. Statements don't express anything very complex,
> and could straightforwardly be represented by function calls.

See, there's really two kinds of SQL out there.

There's the layman's SQL which is pretty straight-forward. Sure, it can
start looking a little complicated if you get multiple clauses in the
WHERE line (and maybe you're ambitious and do a simple inner join), but
its probably still not bad. That can get translated into an API pretty
easily.

Then there's the type of SQL that results in DBA's having jobs-- and
deservedly so. Its *really* a very flexible and powerful language
capable of doing quite a lot to bend, flex, twist, and interleave that
data in the server while building up a result set for you.

I'm honestly only really in the former camp with a toe into the latter
(I use aggregation and windowing functions over some interesting joins
on occasion, but it takes effort). So I can't give a lot of serious
examples to *prove* I'm right.

So I just have to say: based on my experience and admittedly limited
imagination, converting the full expressive power of SQL into a regular
sort of API would be a very, very, very hairy sort of mess. SQLAlchemy
can do the layman's SQL, and can *kind of* do a *little bit* of the
advanced stuff-- but usually, it does the advanced stuff by just making
it very easy for you to shove it out of the way and do SQL directly.

But still: that's the structured part of SQL which belongs in a string.
The data does not. It should be obvious that when a database provides
you a mechanism to pass data in such that it doesn't need sanitization*
at all, that's preferable to actually doing sanitization, even if you're
divinely capable of perfect sanitization and even if sanitization is a
trivial task that a monkey should be able to handle.


--

... Stephen Hansen
... Also: Ixokai
... Mail: me+list/python (AT) ixokai (DOT) io
... Blog: http://meh.ixokai.io/

P.S. *My computer /swears/ sanitization is spelled wrong. Either I'm
high or it's high. Stupid old school mac mini.