Error: cannot insert multiple commands into a prepared statement - postgresql

I am trying to move a row from one table to another.
The problem is that if I put both queries together, I get "error: cannot insert multiple commands into a prepared statement". What can I do?
exports.deletePost = function(id) {
return db.query(`INSERT INTO deletedjobs
SELECT *
FROM jobs
WHERE id = $1;
DELETE FROM jobs WHERE id = $1;`, [id]).then(results => {
console.log("succesfull transfer");
return results.rows[0];
});
};

EDIT: Following Docs v7.0.0, I found out db.multi can execute a multi-query string, you can try this:
db.multi(`INSERT INTO deletedjobs
SELECT *
FROM jobs
WHERE id = $1;DELETE FROM jobs WHERE id = $1`, [id])
Other way I think the better solution is that you should wrap the query into a function for insert-delete at same time, like below:
CREATE FUNCTION moveJob(id character varying) RETURNs void AS
$BODY$
BEGIN
INSERT INTO deletedjobs
SELECT *
FROM jobs
WHERE id = id;
DELETE FROM jobs WHERE id = id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;
And call it as postgresql function in your js:
db.any('select moveJob($1)', [id]);

You can also use a WITH ... AS clause (https://www.postgresql.org/docs/9.1/queries-with.html) to execute both queries in one go. So it could look something like that:
exports.deletePost = function(id) {
return db.query(`
WITH
A AS (SELECT * FROM jobs WHERE id = $1),
B AS (INSERT INTO deletedjobs FROM A),
DELETE FROM jobs WHERE id IN (SELECT id FROM A);
`, [id]).then(results => {
console.log("succesfull transfer");
return results.rows[0];
});
};

Maybe you should not use AND clause, try semicolon ;.
You used select * you should enter columns name, because in later
times you may add a new column, your function does not execute.

Related

default date value to store in a table in snowflake

I created below snowflake procedure and from that procedure I want to
insert default date value into a table. Below is the script.
create or replace procedure test_dt() returns string not null language
javascript //execute as owner
as
$$
try {
var c_dt=`select current_date()`;
snowflake.execute({sqlText:c_dt});
var sql_query = `insert into test_date values (:1)`;
var resultSet = snowflake.execute( {sqlText: sql_query, binds:c_dt});
}
catch(err) {
return err.message;
}
$$;
call test_dt();
while executing the procedure I am getting below error.
"Date 'select current_date()' is not recognized"
Please help me on this.
you are binding the "date" in the second query, to the input sql that "gets the current_date()" and not the actual result, thus it's the same as
insert into test_date values ('select current_date()');
so you ether want to save the result of the first query OR just use the current date aka CURRENT_DATE
insert into test_date values (CURRENT_DATE);
create or replace procedure test_dt() returns string not null language
javascript //execute as owner
as
$$
try {
var sql_query = `insert into test_date values (current_date)`;
var resultSet = snowflake.execute( {sqlText: sql_query});
}
catch(err) {
return err.message;
}
$$;```

Create Postgres with knex.js trigger to update time after updating the table

I have a table with id, username, job, job_id, created_at, and updated_at columns. I used knex.js to create the table and I want the table to capture the time if there are any modifications on the table, for example, if the column job is updated from the frontend, the column updated_at should store the time at which the column was updated.
I am new to Postgres triggers, but I tried to implement this;
const FUNCTION_NAME = 'on_time_update';
CREATE OR REPLACE FUNCTION ${FUNCTION_NAME}()
RETURNS TRIGGER AS
$BODY$
BEGIN
NEW.updated_at = now();
RETURN NEW
END;
$BODY$ LANGUAGE PLPGSQL;
export async function up(knex: Knex): Promise<void> {
await knex.raw(createOnUpdateTrigger('jobs', FUNCTION_NAME));
}
export async function drop(knex: Knex): Promise<void> {
await knex.raw(dropTrigger('jobs', FUNCTION_NAME));
}
using knex, I created a trigger;
createOnUpdateTrigger: (name, table, procedure) => `
CREATE TRIGGER ${name}
BEFORE UPDATE on ${table}
FOR EACH ROW
EXECUTE PROCEDURE ${procedure}();
`
dropTrigger: (name, table) => `
DROP TRIGGER ${name} ON ${table};
`
by doing this, I am able to successfully create the migration, but my column is not being updated and I am not getting errors. I am not sure what am I doing wrong. Any help would be appreciated as I am new to this! Thanks!

Can a return value from a function be named with a specific name for Postgraphile?

I have this function in PostgreSQL:
CREATE FUNCTION it_exists(
email text,
name text
) RETURNS boolean AS $$
DECLARE
_eva1 boolean;
_eva2 boolean;
BEGIN
_eva1 := EXISTS(SELECT * FROM tableA AS A WHERE A.email = $1::citext);
_eva2 := EXISTS(SELECT * FROM tableB AS A WHERE A.name::citext = $2::citext);
RETURN _eva1 OR _eva2;
END;
$$ LANGUAGE plpgsql STRICT SECURITY DEFINER;
It is translated into Postgraphile like this:
mutation MyMutation($email: String!, $name: String!) {
itExists(
input: { email: $email, name: $name }
) {
boolean
}
}
I'd wish to change "boolean" name to something like "result", any suggestion? Consider I have many functions with different return values.
I think that Postgraphile does this to have its custom mutations follow the Relay specification which says
By convention, mutations are named as verbs, their inputs are the name with "Input" appended at the end, and they return an object that is the name with "Payload" appended.
So your custom mutation creates an ItExistsPayload type with only a single field on it instead of returning a GraphQL Boolean. In the future you might want to extend this payload object with more fields.
It is possible to rename that field by using the #resultFieldName smart tag. In your case:
COMMENT ON FUNCTION it_exists(text, text) IS '#resultFieldName result';
Try returning a table instead:
CREATE FUNCTION it_exists(
email text,
name text
) RETURNS TABLE (result boolean) AS $$ -- return TABLE type
DECLARE
_eva1 boolean;
_eva2 boolean;
BEGIN
_eva1 := EXISTS(SELECT * FROM tableA AS A WHERE A.email = $1::citext);
_eva2 := EXISTS(SELECT * FROM tableB AS A WHERE A.name::citext = $2::citext);
RETURN QUERY SELECT _eva1 OR _eva2; -- modify RETURN to suit TABLE type
END;
$$ LANGUAGE plpgsql STRICT SECURITY DEFINER;

Querying a many:many relationship on PK of the related table (ie. filtering by related table column)

I have a many:many relationship between 2 tables: note and tag, and want to be able to search all notes by their tagId. Because of the many:many I have a junction table note_tag.
My goal is to expose a computed field on my Postgraphile-generated Graphql schema that I can query against, along with the other properties of the note table.
I'm playing around with postgraphile-plugin-connection-filter. This plugin makes it possible to filter by things like authorId (which would be 1:many), but I'm unable to figure out how to filter by a many:many. I have a computed column on my note table called tags, which is JSON. Is there a way to "look into" this json and pick out where id = 1?
Here is my computed column tags:
create or replace function note_tags(note note, tagid text)
returns jsonb as $$
select
json_strip_nulls(
json_agg(
json_build_object(
'title', tag.title,
'id', tag.id,
)
)
)::jsonb
from note
inner join note_tag on note_tag.tag_id = tagid and note_tag.note_id = note.id
left join note_tag nt on note.id = nt.note_id
left join tag on nt.tag_id = tag.id
where note.account_id = '1'
group by note.id, note.title;
$$ language sql stable;
as I understand the function above, I am returning jsonb, based on the tagid that was given (to the function): inner join note_tag on note_tag.tag_id = tagid. So why is the json not being filtered by id when the column gets computed?
I am trying to make a query like this:
query notesByTagId {
notes {
edges {
node {
title
id
tags(tagid: "1")
}
}
}
}
but right now when I execute this query, I get back stringified JSON in the tags field. However, all tags are included in the json, whether or not the note actually belongs to that tag or not.
For instance, this note with id = 1 should only have tags with id = 1 and id = 2. Right now it returns every tag in the database
{
"data": {
"notes": {
"edges": [
{
"node": {
"id": "1",
"tags": "[{\"id\":\"1\",\"title\":\"Psychology\"},{\"id\":\"2\",\"title\":\"Logic\"},{\"id\":\"3\",\"title\":\"Charisma\"}]",
...
The key factor with this computed column is that the JSON must include all tags that the note belongs to, even though we are searching for notes on a single tagid
here are my simplified tables...
note:
create table notes(
id text,
title text
)
tag:
create table tag(
id text,
title text
)
note_tag:
create table note_tag(
note_id text FK references note.id
tag_id text FK references tag.id
)
Update
I am changing up the approach a bit, and am toying with the following function:
create or replace function note_tags(n note)
returns setof tag as $$
select tag.*
from tag
inner join note_tag on (note_tag.tag_id = tag.id)
where note_tag.note_id = n.id;
$$ language sql stable;
I am able to retrieve all notes with the tags field populated, but now I need to be able to filter out the notes that don't belong to a particular tag, while still retaining all of the tags that belong to a given note.
So the question remains the same as above: how do we filter a table based on a related table's PK?
After a while of digging, I think I've come across a good approach. Based on this response, I have made a function that returns all notes by a given tagid.
Here it is:
create or replace function all_notes_with_tag_id(tagid text)
returns setof note as $$
select distinct note.*
from tag
inner join note_tag on (note_tag.tag_id = tag.id)
inner join note on (note_tag.note_id = note.id)
where tag.id = tagid;
$$ language sql stable;
The error in approach was to expect the computed column to do all of the work, whereas its only job should be to get all of the data. This function all_nuggets_with_bucket_id can now be called directly in graphql like so:
query MyQuery($tagid: String!) {
allNotesWithTagId(tagid: $tagid) {
edges {
node {
id
title
tags {
edges {
node {
id
title
}
}
}
}
}
}
}

Zend: Inserting Large data in CLOB and BLOB?

I am pulling data from Google Places API and trying to insert reviews into oracle database using zend framework. But reviews that are very long are giving error like :
ORA-01461: can bind a LONG value only for insert into a LONG
When i try to run the insert query in Orqcle SQL Developer its giving the following error:
I tried some of the solutions i got on google and stackoverflow but still not working.
Here is my db code in zend:
public function addReview($bind) {
$bind['STATUS'] = 1;
$bind['CREATED_TIME'] = $this->_curDate;
$text = htmlentities($bind['TEXT']);
$query = "Insert INTO ".$this->_name." (LID,AUTHOR_NAME,AUTHOR_URL,RATINGS,TYPE,TIME,STATUS,TEXT)
VALUES (".$bind['LID'].",
'".$bind['AUTHOR_NAME']."',
'".$bind['AUTHOR_URL']."',
'".$bind['RATINGS']."',
'".$bind['TYPE']."',
'".$bind['TIME']."',
".$bind['STATUS'].",'".$text."')";
try {
$insert = $this->_dbAdpt->query($query);
} catch (Exception $e) {
echo $query; exit;
}
}
Somehow creating a procedure for inserting the reviews worked! Below is the procedure :
create or replace procedure google_review (lid in int,author_name in varchar2, author_url in varchar2,ratings in varchar2,
type in varchar2,time in varchar2,status int,text in varchar2)
as
begin
INSERT INTO TBL_REVIEWS
(
LID,
AUTHOR_NAME,
AUTHOR_URL,
RATINGS,
TYPE,
TIME,
STATUS,
TEXT
)
VALUES
(
LID,
AUTHOR_NAME,
AUTHOR_URL,
RATINGS,
TYPE,
TIME,
STATUS,
TEXT
);
end;