Thread: [GENERAL] Love Your Database project — Thoughts on effectively handling constraints?

I believe a lot of application programmers, particularly but by no means limited to web application developers, have a tragic prejudice against treating their database as anything but a dumb data bucket.

They also often lack awareness of even simple-to-use SQL/Postgres features that would make their lives easier (top of this list would be CTEs and Window Functions).

So I’ve started a project to fix this. I’m initially going to write a series of blog posts demonstrating in principle how a developer can put much/all of their model logic in their database.

I’m starting with constraints. Using Ruby on Rails as my example, a server-side constraint violation shows up in vanilla Rails as an Exception, that looks like this:

PG::CheckViolation: ERROR:  new row for relation "users" violates check constraint "family_name_length"
DETAIL:  Failing row contains (11, foo).

What I need to do is turn this into something similar to the equivalent Rails-side constraint failure, which is a nicely formatted error message on the model object.

The obvious thing would be to parse the error message.

It occurs to me that I might instead do something on the server side. I’d like to get back a more structured error. Perhaps I could use a rule or trigger or stored procedure to structure returning the results.

Here is my iniitial Statement of Purpose blog post:


Even this initial post is starting to get a bit of interest. This feels like something that with a little attention can make a difference. Any thoughts on the project generally, or particularly on effectively handling constraints?
Guyren Howe <guyren@gmail.com> writes:
> I believe a lot of application programmers, particularly but by no means limited to web application developers, have
atragic prejudice against treating their database as anything but a dumb data bucket. 
> They also often lack awareness of even simple-to-use SQL/Postgres features that would make their lives easier (top of
thislist would be CTEs and Window Functions). 

> So I’ve started a project to fix this. I’m initially going to write a series of blog posts demonstrating in principle
howa developer can put much/all of their model logic in their database. 

Cool.  This sounds well worth while.

> I’m starting with constraints. Using Ruby on Rails as my example, a server-side constraint violation shows up in
vanillaRails as an Exception, that looks like this: 

> PG::CheckViolation: ERROR:  new row for relation "users" violates check constraint "family_name_length"
> DETAIL:  Failing row contains (11, foo).

> What I need to do is turn this into something similar to the equivalent Rails-side constraint failure, which is a
nicelyformatted error message on the model object. 

> The obvious thing would be to parse the error message.

Well, that really isn't considered good practice, because your code will
fail on localized error messages.

> It occurs to me that I might instead do something on the server side. I’d like to get back a more structured error.

The server already does deliver more-structured error data, although I confess
that I have no idea how to get at it in Ruby on Rails.  In psql the case
looks about like this:

regression=# create table users (id int, name text, constraint family_name_length check(length(name) > 4));
CREATE TABLE
regression=# insert into users values (11,'foo');
ERROR:  new row for relation "users" violates check constraint "family_name_length"
DETAIL:  Failing row contains (11, foo).
regression=# \errverbose
ERROR:  23514: new row for relation "users" violates check constraint "family_name_length"
DETAIL:  Failing row contains (11, foo).
SCHEMA NAME:  public
TABLE NAME:  users
CONSTRAINT NAME:  family_name_length
LOCATION:  ExecConstraints, execMain.c:1810

The 23514 part is ERRCODE_CHECK_VIOLATION, which evidently corresponds to
"PG::CheckViolation" in the Ruby code, so at least that much is exposed
to you in a reasonable way.  What you want is to get at the error-report
fields shown here as "SCHEMA NAME", "TABLE NAME", "CONSTRAINT NAME".
I don't know if the Ruby client library makes those accessible.

(In the spirit of full disclosure, I should point out that those
fields have only been provided since PG 9.3.  So older installations
may not have the ability to do this in the Right Way.  But still,
you should be evangelizing for doing it the Right Way, no?)

            regards, tom lane


On Dec 16, 2016, at 16:52 , Tom Lane <tgl@sss.pgh.pa.us> wrote:

So I’ve started a project to fix this. I’m initially going to write a series of blog posts demonstrating in principle how a developer can put much/all of their model logic in their database.

Cool.  This sounds well worth while.

Thanks, Tom.

I had a sort of slowly developing epiphany a few years back as I dug deeper into Postgres: it’s not just a database server. The whole rationale for the design of Postgres, which it takes considerably further than any of the other relational databases, is that it should be a “Model Server”. The pluggable languages, data types, FDW and all the rest is there to provide the most efficient possible way to implement your domain model, business logic, etc.

I think folks understood this back in the day, but as architectures shifted, new paradigms arose, and a new generation came along hungry to do their own thing, this perspective has been just completely lost in enormous parts of the software development community. The old wisdom, the whole intent of the RDBMS I think can now be, weirdly, the radical new thing.

I’m just getting started on this. If anyone has any thoughts on what the role of the RDBMS should be in modern software architectures and how that should be communicated, please get in touch so I can make this as good as it can be.
On Fri, Dec 16, 2016 at 3:54 PM, Guyren Howe <guyren@gmail.com> wrote:

> What I need to do is turn this into something similar to the equivalent
> Rails-side constraint failure, which is a nicely formatted error message on
> the model object.

Can you show what the text in such a message looks like?

--
Kevin Grittner
EDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


On Dec 16, 2016, at 16:52 , Tom Lane <tgl@sss.pgh.pa.us> wrote:

The server already does deliver more-structured error data, although I confess
that I have no idea how to get at it in Ruby on Rails.  In psql the case
looks about like this:

Thanks for the advice. I’ve worked out how to get at the same information you showed (it’s available as PG::Result#error_field()). At this point, I just want to show that it is in principle possible to handle PG validations elegantly, so I can write this up and move on to the next thing.

The obvious thing to cover next I think is stored procedures. I think I will cover writing them in PgSQL and ECMAScript. Is there anything I should cover that your average web developer might not know about this that they should? Debugging stored procedures is one thing that comes to mind; I’ll take advice on that or anything else anyone thinks I should share.