Cannot insert to table with authenticated role policy in Supabase - supabase

I'm trying to insert a row in my table which has RLS enabled and the Enable insert for authenticated users only policy added.
Unfortunately, I cannot insert even though I'm correctly login.
Steps to reproduce:
Create submissions table
create table submission (
stuff text
);
Enable RLS
alter table submissions
enable row level security
Add Policy
CREATE POLICY "Enable insert for authenticated users only" ON public.submissions FOR INSERT WITH CHECK (auth.role() = 'authenticated');
On client, I log in using magic links (the object is correctly added in localstorage so I know I'm log in)
I try to insert
const { data, error } = await supabase
.from("submissions")
.insert({ stuff: 'hello' });
The Authorization Bearer <Jwt> is present in http call.
But I got error
{
"hint":null,
"message":"new row violates row-level security policy for table \"submissions\"",
"code":"42501",
"details":null
}
What am I doing wrong here?

I found what was wrong.
The thing is, the default behaviour of supabase.insert returns the row we just inserted, in other words it selects it (reads it) from the table. As I didn't added a Policy to read the table, it failed.
So two solutions:
Add a new Policy to be able to SELECT from that table
Add { returning: "minimal" } to the supabase.insert so it does not send the row back

Yep -- I ran into the same thing the first time I tried to add a RLS policy that only allowed INSERT and not SELECT (for letting users log info to a table.)
We've discussed making { returning: "minimal" } the default for insert, update, and delete, but I don't think that will happen.
It's just something to be aware of (and it is in the documentation, but easy to miss.)

Related

Insert Into from another table causing Can't update 'table' in stored function/trigger because it is already used by statement which invoked

I'm pretty new to SQL so if you can keep it as as simple as possible that would be appreciated.
Currently trying to add all the contact IDs from the contact table (civicrm_contacts) to a new custom field table which is a button to show/hide a contact from the main website. At the moment whenever I run my query I get back the following:
"SQL Error [1442] [HY000]: Can't update table 'civicrm_contact' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
My query is going something like this:
INSERT INTO civicrm_value_appears_on_we_69 (entity_id)
SELECT cc.id
FROM civicrm_contact cc
WHERE contact_type='Organization'
There are 3 columns in total for the 'civicrm_value_appears_on_we_69': 'ID', 'entity_id', and 'appears_on_website_45' which is a 0 or 1 for the button value. All I want is to insert the contact IDs for all the Organisation contacts, I don't mind about nulls for now as long as it makes the rows.
I've looked up a bit about the error and I'm unsure why it's happening. As far as I can gather this errors happpens when you're using a trigger that using the same table as you're inserting into/from. I'm not using a trigger at the moment, or perhaps I have this wrong.
Any suggestions?

How to write trigger in oracle to check for one specific condiition

I have one table name as user_count_details. There are total 3 columns in this table.
msisdn=Which uniquely defines row for one specific user
user_count= Which stores the count of user.
last_Txn_id= Which stores the last transfer id of txn which user has performed.
The user_count column of this table user_count_details is gets updated with every transaction performed by the user.
But here the logic of my system is
select sum(user_count ) from user_count_details
will always gives us the 0 and it is considered as the system is in stable state and everything is fine.
Now i want to write trigger which will check first when new request to update user_count come ,will hamper the sum(user_count )=0 or not and if it hampers that msisdn details will be captured in separate update table.
Based on your last comments, check if this works. Replace the other_table_name as per your scenario.
CREATE TRIGGER trgCheck_user_sum
BEFORE INSERT
ON user_count_details FOR EACH ROW
BEGIN
IF (select sum(user_count) from user_count_details) > 0 THEN
insert into other_table_name(msisdn) values(new.msisdn)
END IF
END

SQLite: how to enable counting number of rows modified from trigger

is there any way to enable counting of rows that trigger modified in SQLite?
I know it is disabled https://www.sqlite.org/c3ref/changes.html and i understand why, but can i enable it somehow?
CREATE TABLE Users_data (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Deleted BOOLEAN DEFAULT (0),
Name STRING
);
CREATE VIEW Users AS
SELECT Id, Name
FROM Users_data
WHERE Deleted = 0;
CREATE TRIGGER UsersDelete2UsersData
INSTEAD OF DELETE
ON Users
FOR EACH ROW
BEGIN
UPDATE Users_data SET Deleted = 1 WHERE Id = OLD.Id;
END;
-- etc for insert & update
then delete from Users where Name like 'foo' /* doesnt even need 'Id = 1' */; works fine, but numbers of modified rows is, as documentation say, always zero.
(I cant modify my DAL to automatically add "where Deleted = 0", so backup plan is to have table Users_deleted and 'on delete' trigger on Users table without any view, but then i have to keep tracking FKs (for example, what to do when someone delete from FK table) and so on...)
Edit: Returned number is used for checking on database concurrency.
Edit2: To be more clear: As i say, I can not modify my DAL (Entity Framework 6), so the preferred answer should operate as follow pseudo code: int affectedRow = query("delete from Users where Name like 'foo';").Execute();
Its all about SQLite "trigger on view" behavior.
Use sqlite3_total_changes() instead:
This function returns the total number of rows inserted, modified or deleted by all INSERT, UPDATE or DELETE statements completed since the database connection was opened, including those executed as part of trigger programs.
Its imposible in sqlite3 (in 2015).
Basically I was looking for instead of trigger on view (as in question) with return function, which is not supported in sqlite.
By the way, postgresql (and i believe some others full db servers) can do it.

Which strategy would be better related to the use of NEXTVAL and CURRVAL in Oracle?

I am developing a Online Registration System using JSP and Oracle where I need to give every successful registrant a unique registration number sequentially. For this I want to adopt the NEXTVAL facility of Oracle, but I am in a dilemma for which policy I would adopt.
Policy 1: First I will store the NEXTVAL of a sequence in the following way.
select seq_form.nextval slno from dual;
Then I will store the slno into a variable say
int slno;
Now I will use the slno for in the insert query when the user finally submits the form, like
insert into members(registration_no, name,...) values(slno, name, ...);
Here the registration_no is primary key.
Policy 2: In my second policy, I will run the insert the query first
insert into members(registration_no, name,...) values(seq_form.nextval, name, ...);
fetch the last inserted ID like
select seq_form.currval slno from dual;
And then store the same in some variable say
int slno;
And use the same to show it to the registrant. Now I can't come to a conclusion which is better in terms of safety and efficiency. Here, I must make it clear that, in both the cases, my intension is to give the user a unique sequential number after successful submission of the form and by safety I meant to say that the user should get the ID respect to his/her own web session. Please help me.
I suggest you do it slightly differently:
Create a BEFORE INSERT trigger on your MEMBERS table. Set REGISTRATION_NO column to SEQ_FORM.NEXTVAL in the trigger:
CREATE OR REPLACE TRIGGER MEMBERS_BI
BEFORE INSERT ON MEMBERS
FOR EACH ROW
BEGIN
:NEW.REGISTRATION_NO := SEQ_FORM.NEXTVAL;
END MEMBERS_BI;
Do NOT put REGISTRATION_NO into the column list in your INSERT statement - it will be set by the trigger so there's no need to supply any value for it:
Use the RETURNING clause as part of the INSERT statement to get back the value put into REGISTRATION_NO by the trigger:
INSERT INTO MEMBERS (NAME, ...)
VALUES ('Fred', ...)
RETURNING REGISTRATION_NO INTO some_parameter
If you are using oracle 12, you can use identity column.
Then use RETURNING to get auto-generated value back.
Go with the policy 2. Because you cant always be sure that the insert query will be successful. If the insert fails, your oracle sequence has been rolled forward and you lose a sequence.
it is a better idea to insert and then later fetch it into a variable.

oracle select and concurrent insert :: To check email availability

We have simple case, We have a table with column emailId i.e. unique.....using oracle DB
Question#1
Multiple concurrent user can check if some email id is available or not. Like 2 user that same time check availability of: abc#test.com
session1: select emailid from user_table;
//If not present allow user to complete rest of the process & insert info
session2: select emailid from user_table;
Now both session will get that this email id (abc#test.com) is available & both try to insert, I know one of them will get error upon insertion BUT how we can make sure only 1 user get availability & other get not available upon select ??
Question#2
Also in case both sessions inserted the same value, then first will succeed, is there ways that 2nd session update that row instead of throwing error. Like we have another column for timestamp & want that 2nd session instead of throwing error simple update the timestamp column ?
As this is a rather abstract question, here are only some general guidelines:
To deal with concurrent insert in a table, you need an unique index, and be prepared in your code to deal with ORA-00001 error unique constraint violated. Never rely only on check before insert(unless you have somehow exclusive access to your table -- and even if so ... as of myself, I would add an unique index: doesn't cost much and make me sleep better)
Oracle has a MERGE statement that allows you update or insert based on a condition. This operation is sometimes called an upsert. By using that keywork you should be able to find more informationsSee Oracle: how to UPSERT (update or insert into a table?) for example.
Now for, some thoughts about you specific case (maybe):
The only way for the system to work as you suggested, would be to make some kind of reservation when you check for availability (i.e.: immediately insert the row, instead of just select). And then update the row when the user confirm. But that means: (1) you will have to somehow deal with never-confirmed reservations (2) that doesn't dispense you to have an unique index, and to deal with ORA-00001.

Resources