Received: from maia.hub.org (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id 83FFB6325C4 for ; Tue, 9 Mar 2010 04:04:41 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 21542-01-6 for ; Tue, 9 Mar 2010 08:04:30 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mout.perfora.net (mout.perfora.net [74.208.4.194]) by mail.postgresql.org (Postfix) with ESMTP id 7E3C8635E57 for ; Tue, 9 Mar 2010 04:02:28 -0400 (AST) Received: from [192.168.223.100] (cpe-74-75-231-235.maine.res.rr.com [74.75.231.235]) by mrelay.perfora.net (node=mrus3) with ESMTP (Nemesis) id 0M8NFi-1NSaM83acc-00vy0r; Tue, 09 Mar 2010 03:02:26 -0500 Subject: Re: Querying the same column and table across schemas From: "John A. Sullivan III" To: Bob Lunney Cc: pgsql-admin@postgresql.org In-Reply-To: <1267828791.15754.53.camel@Family.pacifera.com> References: <576643.83333.qm@web39701.mail.mud.yahoo.com> <1267828791.15754.53.camel@Family.pacifera.com> Content-Type: text/plain Date: Tue, 09 Mar 2010 03:02:19 -0500 Message-Id: <1268121739.4459.4.camel@Family.pacifera.com> Mime-Version: 1.0 X-Mailer: Evolution 2.22.3.1 Content-Transfer-Encoding: 7bit X-Provags-ID: V01U2FsdGVkX19pKLOLq7zDqkaObjuWOR3cGytm6aTWq4WinZV unm4GxPRbjiGqoe6QTASw/la1e7XSOUFFzF/0hPqd5gtt2SShA MlP5mSST1xp7f5kFMh5A0Fm5U5tfLPbumXJ8ek+P4Y= X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-2.599 tagged_above=-10 required=5 tests=BAYES_00=-2.599 X-Spam-Level: X-Archive-Number: 201003/60 X-Sequence-Number: 33859 On Fri, 2010-03-05 at 17:39 -0500, John A. Sullivan III wrote: > On Fri, 2010-03-05 at 14:13 -0800, Bob Lunney wrote: > > > > --- On Fri, 3/5/10, John A. Sullivan III wrote: > > > > > From: John A. Sullivan III > > > Subject: [ADMIN] Querying the same column and table across schemas > > > To: pgsql-admin@postgresql.org > > > Date: Friday, March 5, 2010, 2:44 PM > > > Hello, all. I'm working on a > > > project using the X2Go terminal server > > > project (www.x2go.org). They record session data in a > > > postgresql > > > database. Our environment is a little more secure > > > than typical and we > > > do not want it possible for one user to see another's > > > session data. We > > > thus have divided the session database into schemas each > > > with an > > > identical set of tables. Each user only writes and > > > reads from their > > > schema. > > > > > > However, we need to query all schemas as if they were > > > one. Is there a > > > way to do that? > > > > > > In other words, if we were a single schema database, we > > > could do > > > > > > select session_id from sessions; > > > > > > to list all sessions. How can we accomplish the same > > > thing to list all > > > the sessions across all the schemas in a single query? > > > > > > I'm trying to avoid making a thousand call like > > > > > > select user1.session_id from user1.sessions; > > > > > > when I could do it in a single query especially since the > > > database is > > > remote and secured with SSL. > > > > > > Thanks - John > > > > > > > John, > > > > How about creating a central admin schema and putting a trigger on all the sessions tables to write changes to the central admin schema's session table? The function could belong to the admin role and run with definer's security. > > > > Bob > > > > > > > > > That sounds ideal and perhaps lower overhead than rerunning the view > build query every time I query the view but, being a database ignoramus, > it is quite beyond my skills :-( If I can scrape up the time, I'll do > some research on triggers and functions. I have used functions before > but never triggers. Thanks - John > > After thinking about it quite a while, the advantages seemed to be so great for doing this considering we are anticipating hundreds of schemas, we jumped in and gave it a try. The following seems to be working find after creating a postgres schema, the needed sessions table inside that schema, and adding plpgsql language to the cluster: CREATE OR REPLACE FUNCTION public.syncschema() RETURNS trigger AS ' DECLARE old_path TEXT; BEGIN -- Save old search_path; notice we must qualify current_setting -- to ensure we invoke the right function old_path := pg_catalog.current_setting(''search_path''); -- Set a secure search_path: trusted schemas, then pg_temp. -- We set is_local = true so that the old value will be restored -- in event of an error before we reach the function end. PERFORM pg_catalog.set_config(''search_path'', ''postgres, pg_temp'', true); IF tg_op = ''INSERT'' THEN insert into postgres.sessions (session_id,display,uname,server,client,status,init_time,last_time,cookie,agent_pid,gr_port,sound_port,fs_port) values (new.session_id,new.display,new.uname,new.server,new.client,new.status,new.init_time,new.last_time,new.cookie,new.agent_pid,new.gr_port,new.sound_port,new.fs_port); ELSEIF tg_op = ''DELETE'' THEN delete from postgres.sessions where session_id=old.session_id; ELSEIF tg_op = ''UPDATE'' THEN update postgres.sessions set display=new.display,uname=new.uname,server=new.server,client=new.client,status=new.status,init_time=new.init_time,last_time=new.last_time,cookie=new.cookie,agent_pid=new.agent_pid,gr_port=new.gr_port,sound_port=new.sound_port,fs_port=new.fs_port where session_id=old.session_id; END IF; -- Restore the search_path of the caller PERFORM pg_catalog.set_config(''search_path'', old_path, true); RETURN NULL; END ' LANGUAGE plpgsql SECURITY DEFINER; CREATE TRIGGER syncschema AFTER INSERT OR DELETE OR UPDATE ON .sessions FOR EACH ROW EXECUTE PROCEDURE public.syncschema(); Thanks very much - John