Initial Question
In PostgreSQL is there a way to impose a LIMIT
clause to queries automatically?
Suppose I have a table restaurant
:
create table restaurant (
id uuid primary key,
name text,
created_at timestamp)
First, I tried a view:
create view restaurant_limited
as
select *
from restaurant
order by created_at
limit 3;
The problem with that is you can't apply a predicate and have it work, because the predicate gets applied after the LIMIT
.
Next, I considered a rewrite rule. However, as far as I can tell, the rule system allows you to substitute a new query, but it doesn't give you much power to rewrite an existing query.
Next, I considered a trigger, but triggers only seem to apply to DML, not to queries.
I suppose a function or a procedure could do it, but now we're getting out of the realm of a pure SQL interface. Surely there must be some way to do this. Any ideas?
Addendum
The reason I didn't want to apply the predicates first and then apply the LIMIT
is because I wanted it to be general and support a wide variety of query patterns. If users can submit more-or-less any query, then I don't know the predicates ahead of time. Essentially, what I wanted was something whose logical design, if not physical design, would be something like this.
SELECT
query against a given table.LIMIT
clause in that outer query.I could absolutely do this at the SQL console. I could also do it in a middle layer, if the SQL is being generated within a middle layer (e.g., Python or Java). What I was hoping was that there was some way within PostgreSQL to do this automagically.
Of course, the more I think about it, the more I realize this wouldn't be a property of any particular table, like a trigger or a rewrite rule is. In fact, it wouldn't even make sense to apply it to individual relations. It would have to be a re-write rule that would apply to all queries. That sounds nice, and maybe it's available in some extension, but I wouldn't be surprised if there's no native way to do this in PostgreSQL.
As far as I can tell, there is no way to change the meaning of an SQL query in the way you want.
The canonical way to achieve that is by using a cursor:
BEGIN; -- cursors need a transaction
DECLARE c CURSOR FOR SELECT ...;
FETCH 50 FROM c;
COMMIT;
This is a cursor in SQL, but your client API will have a way to declare cursors as well.