-
Notifications
You must be signed in to change notification settings - Fork 301
Using Postgres functions, like NOW(), in query helpers #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That's a really good use case 😊 I think I would like it to work like below, but that is not supported currently, so I'll see if I can get that into 2.0. const fields = {
name: 'John Doe',
created_at: sql`now()`
}
await sql`
INSERT INTO users ${sql(fields)}
` For now, how about setting |
Awesome! That looks like an intuitive approach to me. I thought about the Thanks! |
Ah yes, there are many other use cases where this usage would be great. Just yesterday I wanted to use a custom type in the same way. Wrt. |
Fyi or for anyone else curious, it's basically just: create or replace function updated_at() returns trigger as
$$
begin
new.updated_at := now();
return new;
end;
$$ language plpgsql;
-- and then use that trigger on your table
create trigger updated_at before update on users for each row execute procedure updated_at() |
Yup, good call on the trigger. Works great! I was worried about losing the timestamp of user edits during db migrations if I used a trigger, but I think I'll introduce a separate column to track user edits if/when I need to. I think there may be a typo in your code tho ( |
Oh, you're right :) The db I'm working on at the moment uses changed_at, so I guess it's in my fingers ;) With regards to migrations you can disable triggers globally during the migration. |
Ahh, cool! I'm still new to triggers, so that's good to know. |
Could you do this with this lib? I am trying to this import postgres from 'postgres'
const sql = postgres()
async function run() {
try {
await sql.begin(async (sql) => {
await sql`
CREATE TABLE public.users (
id serial NOT NULL UNIQUE,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
email text NOT NULL,
password text NOT NULL,
salt text NULL,
PRIMARY KEY (id),
UNIQUE(id),
UNIQUE(email)
);`
await sql`
CREATE OR REPLACE FUNCTION public.set_current_timestamp_updated_at()
RETURNS
TRIGGER AS $$
DECLARE
_new record;
BEGIN
_new := NEW;
_new.updated_at = NOW();
RETURN _new;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER set_public_users_updated_at
BEFORE
UPDATE ON public.users
FOR EACH ROW
EXECUTE PROCEDURE public.set_current_timestamp_updated_at();
COMMENT
ON TRIGGER set_public_users_updated_at ON public.users
IS 'trigger to set value of column updated_at to current timestamp on row update';`
})
} catch (error) {
console.log(error)
} finally {
await sql.end()
}
}
run() But it says - cannot insert multiple commands into a prepared statement. |
I believe you have to divide the second part into |
Thank you very much. Indeed it solves it. await sql`
CREATE TRIGGER set_public_users_updated_at
BEFORE
UPDATE ON public.users
FOR EACH ROW
EXECUTE PROCEDURE public.set_current_timestamp_updated_at();
COMMENT
ON TRIGGER set_public_users_updated_at ON public.users
IS 'trigger to set value of column updated_at to current timestamp on row update';` Error: cannot insert multiple commands into a prepared statement |
OK, I divided into this and it works! await sql`
CREATE TRIGGER set_public_users_updated_at
BEFORE UPDATE ON public.users
FOR EACH ROW EXECUTE PROCEDURE public.set_current_timestamp_updated_at();`
await sql`
COMMENT ON TRIGGER set_public_users_updated_at ON public.users
IS 'trigger to set value of column updated_at to current timestamp on row update';` |
I understand you're planning a fix for this in 2.0, but if anyone needs a slightly hacky fix in the meantime I solved this by just modifying the internal
In my case I needed to upsert a value into a table with a serial primary key which I was able to do with this addValue function and this query.
Perhaps something like this could be used internally, and the interface could be cleaned up by adding some function like |
What about something like: import { call, values } from 'sqlt';
const fields = {
name: 'John Doe',
created_at: sql`now()`,
// OR
//created_at: call('now'),
}
await sql`
INSERT INTO users ${values([fields])}
`
// INSERT INTO users VALUES ($0, now()); I've built a proof of concept around sql tagged template string if you're interested: https://github.com/Minigugus/sqlt/blob/37b13a1cc4dc2eb6b4272117624f786889edc0b8/src/index.test.ts#L126-L139 |
Sorry but what do you mean exactly? It seems to work just fine for me, you just have to make sure the field is NOT present in the object you're saving. Am I missing something? |
Never mind, I was referring to the INSERT, but you were talking about the UPDATE: apologies. |
Another helper I can think of is md5 hash: |
@bas080 Just use the built in PostgreSQL function ;) sql`select md5(${ 'some string })` |
Agreed, but the places where the helpers apply is less because these functions aren't supported. I have had cases where I had quite some properties but couldn't use the helper because one value required md5... I'm fine with typing a bit more |
Ah I see - that makes sense.. With the upcoming api you'll be able to make your own functions like this: const md5 = x => sql`md5(${ x })`
await sql`
select ${ md5('some value') } as hash
` |
Consider the code:
What would I use for
created_at
to sendNOW()
?I know I could probably use the following, but my hope is to keep the SQL compact with the dynamic query helper:
The text was updated successfully, but these errors were encountered: