Muezz
04/16/2022, 9:24 PMrpc
which takes a json doc as an argument and adds not the doc itself but the data from it into a table. For instance, the keys
will be the column names and the values
will be the data that need to be added.tourdownunder
04/16/2022, 11:59 PMjson_populate_recordset
instead of json_populate_record
tourdownunder
04/17/2022, 12:11 AMsql
--drop table db_transactions
CREATE TABLE db_transactions (
t_date timestamptz, -- ':now()
category text, -- ':'random_category'
amount NUMERIC, -- ':120
deb_ac text, -- ':'acc_1'
cred_acc text -- ':'acc_2'
);
create or replace function insert_json(_js json)
returns void
language plpgsql
as $$
begin
INSERT INTO db_transactions
SELECT r.* FROM json_populate_record(NULL::db_transactions, _js) r;
end;
$$;
select insert_json(json_build_object('t_date', now(),'category','random_category','amount',120,'deb_acc','acc_1','cred_acc','acc_2'));
select * from db_transactions dt
I say almost as deb_ac
is null / empty where it was supposed to be acc_1
Something odd going on in this minimum reproducible example on PG 13.3 at least.
sh
t_date |category |amount|deb_ac|cred_acc|
-----------------------------+---------------+------+------+--------+
2022-04-17 10:08:45.676 +1000|random_category| 120| |acc_2 |
tourdownunder
04/17/2022, 12:17 AMdeb_ac
I left off the last c
.
So it now works.
I see it makes sense that any field missing in the json would be ignored. (unless there is a null constraints on the table)Muezz
04/17/2022, 7:53 AMr
in SELECT r.* FROM json_populate_record(NULL::db_transactions, _js) r;
? Like what does it do?
Here select insert_json(json_build_object('t_date', now(),'category','random_category','amount',120,'deb_acc','acc_1','cred_acc','acc_2'));
you are giving comma separated values to this rpc which should build a json. Is there no way to givea json directly? Kinda like this: select insert_json({'t_date':now(),'category':'random_category','amount':120,'deb_acc':'acc_1','cred_acc':'acc_2'});
.
For context, the reason I want to do this is this. My client-side code has a DataModel
and it exclusively works using that model. When it is the time to send data to the backend, this class has a method called toMap()
. This converts it into a json. Because of this DataModel
, the json document's keys are ALWAYS correct column names and values ALWAYS follow the constraints. In normal circumstances, I do this:
dart
addData(DataModel data) {
var response = _databaseService
.insert(
data.toMap(),
)
.execute();
return response;
}
Instead of this, I want to do this:
dart
addData(DataModel data) {
var response = _databaseService
.rpc(
insert_data,
params : {
data.toMap(),
}
)
.execute();
return response;
}
The reason to do this is this will allow me to add rows to more than one table in one go of just one insertion call. Hopefully that makes sense.tourdownunder
04/17/2022, 8:37 PMjson_build_object
is just building json in sql that I used to test the function. It makes sense that you don’t need this as your toMap() is doing that.tourdownunder
04/17/2022, 8:38 PMMuezz
04/17/2022, 8:41 PMrpc
in its current state from my code by giving it a param
like this datamodel.toMap()
and it would work. json_build_object
is only required within sql, right? I just find it a little bit weird. Like why would it accept a json doc from my client-side code but wont accept it within the sql editor.tourdownunder
04/17/2022, 8:44 PMMuezz
04/17/2022, 8:45 PMtourdownunder
04/17/2022, 8:56 PMsql
select insert_json('
{
"t_date": "2021-02-13T12:05:33+11:00","category":"random_category","amount": 120,"deb_acc": "acc_1","cred_acc": "acc_2"
}
');
Though I don't know how to sub the hard coded date and use now() this this syntax.
thats why I just use json_build_object
tourdownunder
04/17/2022, 9:04 PMjs
const { data, error } = await supabase
.from('cities')
.insert([
{ name: 'The Shire', country_id: 554 }
])
as this is effectively json to cols and its using the power of the supabase js client and the postgrest
v9.0 on the server side
https://supabase.com/docs/reference/javascript/insertMuezz
04/17/2022, 9:07 PMinsert
would just add that data to the one table I specify. By using rpc
, I can use the data in the form of json and do some conditional checks on certain field values and insert the appropriate values in the appropriate tables. Does that make sense?Muezz
04/17/2022, 9:08 PMnull value in column "id" of relation "db_transactions" violates not-null constraint
. Why isnt postgres automatically using the default value for id
which is generate_uuid_v4()
tourdownunder
04/17/2022, 9:10 PM{id: null}
you are setting it to null
If you want default to work leave it out of the json object completely.Muezz
04/17/2022, 9:11 PMid
field in it. Shouldnt it use the default value then.tourdownunder
04/17/2022, 9:14 PMtourdownunder
04/17/2022, 9:14 PMI was wrong. This almost works
Muezz
04/17/2022, 9:18 PMsql
create or replace function insert_json(_js json)
returns void
language plpgsql
as $$
begin
INSERT INTO db_transactions
SELECT r.* FROM json_populate_record(NULL::db_transactions, _js) r;
end;
$$;
select insert_json('
{
"t_date": "2021-02-13T12:05:33","category":"random_category","amount": 120,"deb_acc": "acc_1","cred_acc": "acc_2"
}
');
There is nothing to hide here. I am just testing out this functionality at the moment. My table was manually created. It has all these columns and some more: id
which is not nullable and defaults to auto genrated uuid. Other than that, there are two more columns but they are nullable.Muezz
04/17/2022, 9:20 PMppc
is also nullable.tourdownunder
04/17/2022, 9:24 PMsql
INSERT INTO db_transactions(t_date, category,etc)
Muezz
04/17/2022, 9:26 PMparams
instead of just one json doc. I mean the insert
method in my client-side code took a json doc and automatically did what I am trying to brute force right now.tourdownunder
04/17/2022, 9:29 PMtourdownunder
04/17/2022, 9:29 PMMuezz
04/17/2022, 9:33 PMinsert
data from client side using the insert
call and a json doc (like I was doing before). With this insertion, a trigger would call a function which would take the new row and then do what I am trying to do ultimately.tourdownunder
04/17/2022, 9:46 PMjs
const { data, error } = await supabase
.from('cities')
.insert([
{ name: 'The Shire', country_id: 554 }
])
if you needed custom logic you can have a trigger on a table or a view that does it.Muezz
04/17/2022, 9:52 PM