Currently, I'm working with Postgraphile and I need to enforce permissions at data/field level.
For example, I have a carmodel table, with my query is something like:
{
carmodel
{
id
name
description
}
}
Well, in this table I have ids (1 = AUDI, 2 = GM, 3 = BMW)
The current user (on roles/claims) has permission only to see (1=AUDI/3=BMW)
There is a way to enforce permissions based on field data? And return only data filtered on the user permissions?
Yes; row-level security can define this declaratively. Something like:
create policy audi_bmw on carmodel for select using (
id in (1, 3)
);
I'm guessing this permission comes from another table though; so it might be more like:
create policy audi_bmw on carmodel for select using (
id in (
select car_model_id
from user_carmodel_permissions
where user_id = current_user_id()
)
);
assuming you already have a current_user_id function, something like:
create function current_user_id() returns int as $$
select nullif(current_setting('jwt.claims.user_id', true), '')::int;
$$ language sql stable;
Check out our row level security cheatsheet.
Related
I would like to select a user by login, but in case if login is empty then select by combination of first and last name. E.g:
select * from user
where login = 'criteria' // or if *login=null* then // where firstName || lastName = 'criteria'
Thanks a lot in advance.
You can use coalesce (or Oracle's nvl) as follows:
select * from user
where ('criterion' = coalesce(login, firstname)
or 'criterion' = coalesce(login, lastname))
Another way:
select * from user
where (login = 'criterion'
or login is null and 'criterion' in (firstname, lastname))
NB: user is a reserved word in Oracle, so I assume in reality you have a different table name. If really it is user, you need to quote it: "USER"
I have two tables: user, user_matching. And I wanna get items from both tables in 1 query. For example, SQL-like query:
select * from user where user.id = (select id from user_matching where id = user_matching_id)
Usually I should use 2 query in NoSQL DB. Now I do it like this:
Get from user_matching user_id
With user_id Get from user
Can I replace it with only 1 query using Tarantool. And How To?
You need to create stored procedure where you combine result of two selection, e.g.:
function select_user_by_matching_id(matching_id)
local id = box.space.user_matching:get{matching_id} # or :select
local user_data = box.space.user:get{id} # or :select
# work with user_data
return user_data
end
After you create this procedure you can call this procedure via Tarantool driver with fetching combined result.
More detail here: http://tarantool.org/doc/book/app/c-lua_tutorial.html?highlight=call
I have these three tables :
RESEARCHER(Re_Id, Re_Name, Re_Address, Re_Phone, Re_HomePhoneNumber,
Re_OfficeNumber, Re_FirstScore, Re_Second_Score)
PUBLICATION(Pub_ID, Pub_Title, Pub_Type, Pub_Publisher, Pub_Year,Pub_Country, Pub_StartingPage, Pub_Number_of_Page, Score1, Score2)
WRITTEN_BY(Re_Id, Pub_ID)
I want to change the authors of the publication “Introduction to Database System” to “Henry Gordon” and “Sarah Parker”.
The problem is in WRITTEN_BY table,I just store the researcher's ID and publication's ID.
My idea is to change the Re_Id in WRITTEN_BY by those names are "Henry Gorgon" , "Sarah Parker" , which are already existed in RESEARCHER table
UPDATE WRITTEN_BY
SET Re_Id = ....( SELECT Re_Id
FROM RESEACHER
WHERE Re_Name = ‘Henry Gordon’ OR Re_Name = ‘Sarah Paker’ )
WHERE Pub_ID IN ( SELECT Pub_ID
FROM PUBLICATION
WHERE Pub_Name = ‘Introduciton to Database system’ );
I have problem in the SET part,so how to write the SQL statement for that requirement?
Here is the sqlfiddle link for my schema : http://sqlfiddle.com/#!9/b9118/1
I'd use something like below query:
DELETE FROM WRITTEN_BY WHERE Pub_ID IN (
SELECT Pub_ID FROM PUBLICATION
WHERE Pub_Title = 'Introduciton to Database system' )
INSERT INTO WRITTEN_BY
SELECT Re_Id,Pub_Id
FROM RESEARCHER CROSS JOIN PUBLICATION
WHERE Re_Name = 'Henry Gordon' OR Re_Name = 'Sarah Paker'
AND Pub_Title like 'Introduciton to Database system'
SELECT * FROM WRITTEN_BY
The idea is to first drop the existing mapping- you should not update it- and the insert a new one.
The reason for delete/insert approach vs update in case of mapping table is justified in favor of delete/insert as most mapping tables contain many-many mapping and usually one-to-many mappings.
Initially we may have a book mapped to say n number of authors where n <>1 then we either add extra rows, or are left with extraneous rows.
See sample fiddle: http://sqlfiddle.com/#!6/a0e72/13
The real deal however is CROSS JOIN. This does not take any ON like other JOINs and is used to produce cartesian product type map.
We are restricting it to get only limited number of rows as per our need by adding suitable WHERE clauses
I have have two schemas with the same table. e.g schema1.adress and schema2.adress.
Both tables are identical.
Layout of table customer:
customerno: integer
name: varchar2(50)
Now I want to get the customers of schema 1 using something like
"select * from customer where schemaname = 1" or
"select * from customer where schemaname = 2"
Is there a mechanism in Oracle that can switch the schema depending on a criteria in a select-statement?
Before you ask: for a new project I have to query legacy schemas. I cannot change the schema, but I can set any permission on the schema / user.
Any ideas?
Thanks for any response,
Sven
You could create a private synonym for the user for the schema.table you want them to access,
create synonym user1.customer for schemaname1.customer;
create synonym user2.customer for schemaname2.customer;
Then your queries would always just be select * from customer;
So you are logged in as the same user both when you want to select from schema1.customer and select from schema2.customer?
A possible way can be something like:
select *
from (
select 'schema1' schema$name, c.* from schema1.customer c
union all
select 'schema2' schema$name, c.* from schema2.customer c
)
where schema$name = 'schema1'
If you can create views, it can be an idea to create a view like:
create or replace view customer_view as
select 'schema1' schema$name, c.* from schema1.customer c
union all
select 'schema2' schema$name, c.* from schema2.customer c
That makes it possible to do:
select *
from customer_view
where schema$name = 'schema1'
Whether you use view or not, Oracle optimizer can in most cases like this push the predicate "where schema$name = 'schema1'" into the UNION ALL and then it recognizes that it does not need to access schema2.customer at all.
I have a database which consists of the following:
** Table 1 **
Id (PK)
Field1
** Table 2 **
Id (PK)
Field2
** Link Table **
Table1Id (FK)
Table2Id (FK)
The problem is, I cannot access Table 2 from Table 1, even though the relationship exists in the database.
For example, the following should be possible:
var Results = from c in DataContext.Table1
where c.Table2.Field2 == "Test"
select c;
However, "c.Table2.Field2" is not available for some reason - all I get for "c.Table2." is the following (among the standard any<>, where<> et al):
RelationshipName
RelationshipSet
SourceRoleName
TargetRoleName
So obviously something is screwy somewhere, but I cannot work out what!
Both tables exist in the Entity Schema, and have a valid relationship between them.
The reason that c.Table2.Field2 is not available is that c.Table2 doesn't have a property called Field2. c.Table2 is a list of entities which have that property, not an instance of that entity. It's not clear what your intention is here, but I think you want:
var Results = from c in DataContext.Table1
where c.Table2.Any(t2 => t2.Field2 == "Test")
select c;