1

Is it possible to have Postgres reject queries which use its proprietary extensions to the SQL language?

e.g. select a::int from b; should throw an error, forcing the use of proper casts as in select cast(a as int) from b;

Perhaps more to the point is the question of whether it is possible to write SQL that is supported by all RDBMS with the same resulting behaviour?

5
  • 5
    DBMS independent SQL simply means your application will run equally slow on all systems (if you find one at all). Why are people so keen on DBMS independent code? You are not making your application independent of the programming language or the web framework either. Commented Dec 29, 2013 at 23:51
  • 5
    @a_horse_with_no_name: I blame ORMs for this (and all sorts of other nonsense): write to the ORMs API and you don't have to care about the underlying database. That attitude is, of course, pure nonsense and confusion. Most app and framework people seem to be frightened by SQL and relational systems because they don't understand them (or it isn't their favorite language), the result is that the most important part of applications -- the data -- ends up hidden away behind opaque layers of ORM nonsense. IMO of course. Commented Dec 30, 2013 at 0:28
  • @muistooshort I don't know.. I prefer ORM code to hand-concatenated sql (...where field1 = '" + myvalue.ToString() + "' and...) wink Commented Dec 30, 2013 at 0:40
  • @thebjorn: where field1 = ? and field2 = ? .... We're not hacking PHP in 1999 anymore, any database interface that doesn't properly support placeholders is dangerously insane and should be shunned. Commented Dec 30, 2013 at 1:43
  • It's usually a user problem, not an interface problem. Commented Dec 30, 2013 at 18:12

3 Answers 3

6

PostgreSQL has no such feature. Even if it did, it wouldn't help you tons because interpretations of the SQL standard vary, support for standard syntax and features vary, and some DBs are relaxed about restrictions that others enforce or have limitations others don't. Syntax is the least of your problems.

The only reliable way to write cross-DB portable SQL is to test that SQL on every target database as part of an automated test suite. And to swear a lot.

In many places the query parser/rewriter transforms the standard "spelling" of a query into the PostgreSQL internal form, which will be emitted on dump/reload. In particular, PostgreSQL doesn't store the raw source code for things like views, check constraint expressions, index expressions, etc. It stores the internal parse tree, and reconstructs the source from that when it's asked to dump or display the object.

For example:

regress=> CREATE TABLE sometable ( x varchar(100) );
CREATE TABLE
regress=> CREATE VIEW someview AS SELECT CAST (x AS integer) FROM sometable;
CREATE VIEW
regress=> SELECT pg_get_viewdef('someview');
           pg_get_viewdef            
-------------------------------------
  SELECT (sometable.x)::integer AS x
    FROM sometable;
(1 row)

It'd be pretty useless anyway, since the standard fails to specify some pretty common and important pieces of functionality and often has rather ambiguous specifications of things it does define. Until recently it didn't define a way to limit the number of rows returned by a query, for example, so every database had its own different syntax (TOP, LIMIT / OFFSET, etc).

Other things the standard specifies are not implemented by most vendors, so using them is pretty pointless. Good luck using the SQL-standard generated and identity columns across all DB vendors.

It'd be quite nice to have a "prefer standard spelling" dump mode, that used CAST instead of ::, etc, but it's really not simple to do because some transformations aren't 1:1 reversible, e.g.:

regress=> CREATE VIEW v AS SELECT '1234' SIMILAR TO '%23%';
CREATE VIEW
regress=> SELECT pg_get_viewdef('v');

 SELECT ('1234'::text ~ similar_escape('%23%'::text, NULL::text));

or:

regress=> CREATE VIEW v2 AS SELECT extract(dow FROM current_date);
CREATE VIEW
regress=> SELECT pg_get_viewdef('v2');

 SELECT date_part('dow'::text, ('now'::text)::date) AS date_part;

so you see that significant changes would need to be made to how PostgreSQL internally represents and works with functions and expressions before what you want would be possible.

Lots of the SQL standard stuff uses funky one-off syntax that PostgreSQL converts into function calls and casts during parsing, so it doesn't have to add special case features every time the SQL committe have another brain-fart and pull some new creative bit of syntax out of ... somewhere. Changing that would require adding tons of new expression node types and general mess, all for no real gain.

Sign up to request clarification or add additional context in comments.

Comments

3

Perhaps more to the point is the question of whether it is possible to write SQL that is supported by all RDBMS with the same resulting behaviour?

No, not even for many simple statments..

select top 10 ...   -- tsql

select ... limit 10  -- everyone else

many more examples exist. Use an orm or something similar if you want to insulate yourself from database choice.

If you do write sql by hand, then trying to follow the SQL standard is always a good choice :-)

4 Comments

ORMs don't insulate you from database-specific behavior unless your queries aren't any more complicated than select * from t where x. GROUP BY and non-aggregated non-grouped columns in the SELECT for example.
@muistooshort sadly that is very often the case, but we can dream can't we..? The stark reality is that changing the database post facto is going to require some serious work, whether that makes it ok to always use the most quirky variants your chosen database provides is another question entirely.
trying to follow the SQL standard I'd like to note that Postgres tries to follow the SQL standard as closely as is practicable, more so than any other database I've seen. Furthermore, the Postgres documentation does an excellent job of describing SQL standard features and notes where Postgres may stray or where you may well want to choose to vary. So, while depending on the standard to provide cross-platform independence is not realistic, Postgres is a good environment for those who want to stick to the standard where feasible.
... And neither of those two example syntaxes work on Oracle, to further prove the point.
1
  1. You could use a tool like Mimer's SQL Validator to validate that queries follow the SQL spec before running them:

    http://developer.mimer.com/validator/parser92/index.tml

  2. You could force users to write queries in HQL or JPQL, which would then get translated in to the correct SQL dialect for your database.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.