niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » Databases » PostgreSQL
Oracle's Virtual Private Database functionality
Post new topic   Reply to topic Page 1 of 1 [2 Posts] View previous topic :: View next topic
Author Message
Doug Bloebaum
*nix forums beginner


Joined: 09 Mar 2005
Posts: 10

PostPosted: Fri Mar 11, 2005 1:48 pm    Post subject: Oracle's Virtual Private Database functionality Reply with quote

[ Sorry if this appears twice on the list: sent it via a non-subscribed email the first time around. Of course, while waiting for it to appear I figured out a workaround; see the "Late breaking update" at the end. ]

In the spirit of "tell us what you're trying to do..."

I'd like to mimic a subset of Oracle's Virtual Private Database functionality (see http://dba-oracle.com/oracle_news/2004_1_16_vpd_security.htm for an overview) in Postgres: based on some per-connection setting, I'd like a query to return a different set of rows. In VPD, the Oracle engine actually applies a defined predicate (say, country_code='USA') to every query. The idea is that a given set of users can only see rows in a table that match this predicate, while the other rows are invisible to them.

Now for the "how I tried to do it" part...

I thought I was on my way to doing this in Postgres by making use of schemas and search_path:

CREATE USER user1 UNENCRYPTED PASSWORD 'user1';
CREATE SCHEMA AUTHORIZATION user1;

CREATE SCHEMA canada;
GRANT USAGE ON SCHEMA canada TO user1;
CREATE TABLE canada.row_limiter (country_code VARCHAR(3));
INSERT INTO canada.row_limiter VALUES('CAN');
GRANT SELECT ON canada.row_limiter TO user1;

CREATE SCHEMA usa;
GRANT USAGE ON SCHEMA usa TO user1;
CREATE TABLE usa.row_limiter (country_code VARCHAR(3));
INSERT INTO usa.row_limiter VALUES('USA');
GRANT SELECT ON usa.row_limiter TO user1;

\CONNECT - user1

SET SEARCH_PATH TO '$user',canada;

CREATE TABLE my_data (country_code VARCHAR(3), data NUMERIC);
INSERT INTO my_data VALUES('USA',11);
INSERT INTO my_data VALUES('USA',12);
INSERT INTO my_data VALUES('USA',13);

INSERT INTO my_data VALUES('CAN',21);
INSERT INTO my_data VALUES('CAN',22);
INSERT INTO my_data VALUES('CAN',23);

CREATE VIEW my_data_v AS
SELECT md.*
FROM my_data md,
row_limiter rl
WHERE rl.country_code=md.country_code;

SELECT * FROM my_data_v;

-- Looks great - I only see Canadian data!!
-- country_code | data
----------------+------
-- CAN | 21
-- CAN | 22
-- CAN | 23

SET SEARCH_PATH TO '$user',usa;

SELECT * FROM my_data_v;

-- Darn, I still only see Canadian data Sad
-- country_code | data
----------------+------
-- CAN | 21
-- CAN | 22
-- CAN | 23

\d my_data_v

View definition:
SELECT md.country_code, md.data
FROM my_data md, CANADA.row_limiter rl -- <--ah, and here's the reason...
WHERE rl.country_code::text = md.country_code::text;


It's apparent why: the view determines which table it's going to use at view creation time, not at query time, so this method is no good.

Is there a "right way" to accomplish what I'm trying to do?

Late breaking update:

Looks like a function returning SETOF does the trick, so it must not resolve the table early like the view does:

CREATE OR REPLACE FUNCTION my_data_f() RETURNS SETOF my_data AS '
SELECT md.country_code,
md.data
FROM my_data md, row_limiter rl
WHERE rl.country_code = md.country_code;
' LANGUAGE sql;

SET SEARCH_PATH TO '$user',usa;
SELECT * FROM my_data_f();
country_code | data
--------------+------
USA | 11
USA | 12
USA | 13

SET SEARCH_PATH TO '$user',canada;
SELECT * FROM my_data_f();
country_code | data
--------------+------
CAN | 21
CAN | 22
CAN | 23

Can I rely on this behavior? Is this the best way to do what I'm after?2 to accomplish what I'm trying to do?

Late breaking update:

Looks like a function returning SETOF does the trick, so it must not resolve the table early like the view does:

CREATE OR REPLACE FUNCTION my_data_f() RETURNS SETOF my_data AS '
SELECT md.country_code,
md.data
FROM my_data md, row_limiter rl
WHERE rl.country_code = md.country_code;
' LANGUAGE sql;

SET SEARCH_PATH TO '$user',usa;
SELECT * FROM my_data_f();
country_code | data
--------------+------
USA | 11
USA | 12
USA | 13

SET SEARCH_PATH TO '$user',canada;
SE


---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match
Back to top
Qingqing Zhou
*nix forums Guru Wannabe


Joined: 11 Mar 2005
Posts: 101

PostPosted: Sat Mar 12, 2005 5:00 am    Post subject: Re: Oracle's Virtual Private Database functionality Reply with quote

Check out CREATE RULE command,

Regards,
Qingqing

""Doug Bloebaum"" <blabes@myrealbox.com> дÈëÓʼþ
news:1110552518.1f7b963cblabes@myrealbox.com...
Quote:
[ Sorry if this appears twice on the list: sent it via a non-subscribed
email the first time around. Of course, while waiting for it to appear I

figured out a workaround; see the "Late breaking update" at the end. ]
Quote:

In the spirit of "tell us what you're trying to do..."

I'd like to mimic a subset of Oracle's Virtual Private Database
functionality (see

http://dba-oracle.com/oracle_news/2004_1_16_vpd_security.htm for an
overview) in Postgres: based on some per-connection setting, I'd like a
query to return a different set of rows. In VPD, the Oracle engine actually
applies a defined predicate (say, country_code='USA') to every query. The
idea is that a given set of users can only see rows in a table that match
this predicate, while the other rows are invisible to them.
Quote:

Now for the "how I tried to do it" part...

I thought I was on my way to doing this in Postgres by making use of
schemas and search_path:

CREATE USER user1 UNENCRYPTED PASSWORD 'user1';
CREATE SCHEMA AUTHORIZATION user1;

CREATE SCHEMA canada;
GRANT USAGE ON SCHEMA canada TO user1;
CREATE TABLE canada.row_limiter (country_code VARCHAR(3));
INSERT INTO canada.row_limiter VALUES('CAN');
GRANT SELECT ON canada.row_limiter TO user1;

CREATE SCHEMA usa;
GRANT USAGE ON SCHEMA usa TO user1;
CREATE TABLE usa.row_limiter (country_code VARCHAR(3));
INSERT INTO usa.row_limiter VALUES('USA');
GRANT SELECT ON usa.row_limiter TO user1;

\CONNECT - user1

SET SEARCH_PATH TO '$user',canada;

CREATE TABLE my_data (country_code VARCHAR(3), data NUMERIC);
INSERT INTO my_data VALUES('USA',11);
INSERT INTO my_data VALUES('USA',12);
INSERT INTO my_data VALUES('USA',13);

INSERT INTO my_data VALUES('CAN',21);
INSERT INTO my_data VALUES('CAN',22);
INSERT INTO my_data VALUES('CAN',23);

CREATE VIEW my_data_v AS
SELECT md.*
FROM my_data md,
row_limiter rl
WHERE rl.country_code=md.country_code;

SELECT * FROM my_data_v;

-- Looks great - I only see Canadian data!!
-- country_code | data
----------------+------
-- CAN | 21
-- CAN | 22
-- CAN | 23

SET SEARCH_PATH TO '$user',usa;

SELECT * FROM my_data_v;

-- Darn, I still only see Canadian data Sad
-- country_code | data
----------------+------
-- CAN | 21
-- CAN | 22
-- CAN | 23

\d my_data_v

View definition:
SELECT md.country_code, md.data
FROM my_data md, CANADA.row_limiter rl -- <--ah, and here's the
reason...
WHERE rl.country_code::text = md.country_code::text;


It's apparent why: the view determines which table it's going to use at
view creation time, not at query time, so this method is no good.

Is there a "right way" to accomplish what I'm trying to do?

Late breaking update:

Looks like a function returning SETOF does the trick, so it must not
resolve the table early like the view does:

CREATE OR REPLACE FUNCTION my_data_f() RETURNS SETOF my_data AS '
SELECT md.country_code,
md.data
FROM my_data md, row_limiter rl
WHERE rl.country_code = md.country_code;
' LANGUAGE sql;

SET SEARCH_PATH TO '$user',usa;
SELECT * FROM my_data_f();
country_code | data
--------------+------
USA | 11
USA | 12
USA | 13

SET SEARCH_PATH TO '$user',canada;
SELECT * FROM my_data_f();
country_code | data
--------------+------
CAN | 21
CAN | 22
CAN | 23

Can I rely on this behavior? Is this the best way to do what I'm after?2
to accomplish what I'm trying to do?

Late breaking update:

Looks like a function returning SETOF does the trick, so it must not
resolve the table early like the view does:

CREATE OR REPLACE FUNCTION my_data_f() RETURNS SETOF my_data AS '
SELECT md.country_code,
md.data
FROM my_data md, row_limiter rl
WHERE rl.country_code = md.country_code;
' LANGUAGE sql;

SET SEARCH_PATH TO '$user',usa;
SELECT * FROM my_data_f();
country_code | data
--------------+------
USA | 11
USA | 12
USA | 13

SET SEARCH_PATH TO '$user',canada;
SE


---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match




---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faq
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 1 [2 Posts] View previous topic :: View next topic
The time now is Fri Jan 09, 2009 6:36 am | All times are GMT
navigation Forum index » Databases » PostgreSQL
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts Postfix 2.3.8 Virtual problem Blotto Postfix 0 Fri Apr 04, 2008 6:11 am
No new posts Move Oracle 10g database to another location Selt Server 0 Fri Jul 21, 2006 2:14 pm
No new posts database Share Memory Limit (2 GB ) in a Instance is tota... sadanjan@gmail.com IBM DB2 0 Fri Jul 21, 2006 12:57 pm
No new posts A webserver (PHP 5) with a few database server (MySQL) ¥|¥J PHP 2 Fri Jul 21, 2006 1:43 am
No new posts How do I determine if a virtual hostname is actually on m... Brett shell 6 Thu Jul 20, 2006 6:58 pm

Bankruptcy | Debt Consolidation | Loans | Bankruptcy | Debt Consolidation
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.2306s ][ Queries: 16 (0.1183s) ][ GZIP on - Debug on ]