node-postgres does not show result set for stored procedure - postgresql

I'm trying to use a stored procedure to create a character. The procedure does some validation to make sure that the params are valid before inserting them into the database(let's keep this validation on the database). However when I attempt to use the procedure in my web interface with invalid data, there is no result set, and the error promise does not happen. What do I have to do to make this procedure cause an error on the node side?
-- add a character with the universe performing the universe name lookup
CREATE OR REPLACE FUNCTION add_character(
IN p_chr_name VARCHAR(255),
IN p_unv_name VARCHAR(255),
IN p_chr_bio TEXT
)
RETURNS INT AS $$
DECLARE
unv_id INTEGER := (SELECT unv_id
FROM universes
WHERE LOWER(unv_name) = LOWER(p_unv_name));
new_id INTEGER := NULL;
BEGIN
IF unv_id IS NULL THEN
RAISE EXCEPTION 'unv_id is null for %', p_unv_name;
END IF;
INSERT INTO characters(chr_name, chr_unv_id, chr_bio) VALUES
(p_chr_name, unv_id, p_chr_bio)
RETURNING chr_id INTO new_id;
RETURN new_id;
END $$
LANGUAGE PLPGSQL;
The javascript
app.post('/contrib/chr', (req, res) => {
console.log(req.body);
pool.query('SELECT add_character($1, $2, $3)'
[req.body.chr_name, req.body.unv_name, req.body.chr_bio])
.then((rows) => {
console.log(rows);
res.render('contrib');
}).catch((err) => {
console.error('contrib-chr-err', err);
res.render('contrib');
});
})
The row object returned.
{ command: '', rowCount: NaN, rows: [], fields: null }

working sample:
sql:
t=# create or replace function s110(_b boolean) returns int as
$$
begin
if not _b then
raise info '%','here is notice';
raise warning '%','warning it is';
end if;
if _b then
raise exception '%','final exception it is';
end if;
return 9;
end;
$$ language plpgsql;
CREATE FUNCTION
js
var pg = require('pg');
var client = new pg.Client({"database": "t"});
client.connect(function (err) {
if (err) throw err;
client.query('SELECT * from s110(true)', [], function (err, result) {
if (err) throw err;
console.log(result);
client.end(function (err) {
if (err) throw err;
});
});
});
run
MacBook-Air:n vao$ vi q1.js && node q1.js
/Users/vao/n/q1.js:6
if (err) throw err;
^
error: final exception it is
at Connection.parseE (/Users/vao/node_modules/pg/lib/connection.js:569:11)
at Connection.parseMessage (/Users/vao/node_modules/pg/lib/connection.js:396:17)
at Socket.<anonymous> (/Users/vao/node_modules/pg/lib/connection.js:132:22)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:153:18)
at Socket.Readable.push (_stream_readable.js:111:10)
at TCP.onread (net.js:531:20)
if I change SELECT * from s110(true) to SELECT * from s110(false):
MacBook-Air:n vao$ vi q1.js && node q1.js
{ command: 'SELECT',
rowCount: 1,
oid: NaN,
rows: [ { s110: 9 } ],
fields:
[ { name: 's110',
tableID: 0,
columnID: 0,
dataTypeID: 23,
dataTypeSize: 4,
dataTypeModifier: -1,
format: 'text' } ],
_parsers: [ [Function] ],
RowCtor: [Function],
rowAsArray: false,
_getTypeParser: [Function: bound ] }
UPDATE
Also you can get STDOUT messages with little change. I'm not good in javascript, hopefully I don't advice very silly things, here. If you add this line above .query:
client.connection.on('message', function(a) {console.log(a);});
client.query('SELECT s110(false)', [], function (err, result) {...
You will get all RAISE output to console.log:
{ [notice: here is notice]
name: 'notice',
length: 123,
severity: 'INFO',
code: '00000',
detail: undefined,
hint: undefined,
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: 'PL/pgSQL function s110(boolean) line 4 at RAISE',
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'pl_exec.c',
line: '3165',
routine: 'exec_stmt_raise' }
{ [notice: warning it is]
name: 'notice',
length: 128,
severity: 'WARNING',
code: '01000',
detail: undefined,
hint: undefined,
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: 'PL/pgSQL function s110(boolean) line 5 at RAISE',
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'pl_exec.c',
line: '3165',
routine: 'exec_stmt_raise' }
{ name: 'dataRow', length: 11, fieldCount: 1, fields: [ '9' ] }
{ name: 'commandComplete', length: 13, text: 'SELECT 1' }
{ name: 'readyForQuery', length: 5, status: 'I' }

Related

Error on sequelize full text search raw sql query

Attempting to use raw sql in sequelize db, not sure why it is not working.
Here is the controller with the query:
const db = require("../../models");
const Book = db.book;
const User = db.user;
const Sequelize = require('sequelize');
const { sequelize } = require('../../models/index.js');
exports.getAllBooks = async (req, res) => {
console.log('query: ', req.query);
let books;
if (Object.keys(req.query).length === 0) {
books = await Book.findAll();
res.json(books);
} else {
[books, metadata] = await sequelize.query(`
SELECT ('title')
FROM Book
WHERE searchable ## to_tsquery(${req.query});
`);
res.json(books);
}
};
get request to
http://localhost:8080/api/books?searchable=humor
the tsvector column in the db is named "searchable"
the log response:
Server is running on port 8080.
query: { searchable: 'humor' }
Executing (default): SELECT ('title')
FROM Book
WHERE searchable ## to_tsquery([object Object]);
node:internal/process/promises:279
triggerUncaughtException(err, true /* fromPromise */);
^
Error
at Query.run (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/sequelize/lib/dialects/postgres/query.js:50:25)
at /Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/sequelize/lib/sequelize.js:314:28
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async exports.getAllBooks (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/app/controllers/book.controller.js:16:29) {
name: 'SequelizeDatabaseError',
parent: error: syntax error at or near "["
at Parser.parseErrorMessage (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/parser.js:287:98)
at Parser.handlePacket (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/parser.js:126:29)
at Parser.parse (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/parser.js:39:38)
at Socket.<anonymous> (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/index.js:11:42)
at Socket.emit (node:events:513:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
length: 90,
severity: 'ERROR',
code: '42601',
detail: undefined,
hint: undefined,
position: '83',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'scan.l',
line: '1180',
routine: 'scanner_yyerror',
sql: "SELECT ('title')\n" +
' FROM Book\n' +
' WHERE searchable ## to_tsquery([object Object]);',
parameters: undefined
},
original: error: syntax error at or near "["
at Parser.parseErrorMessage (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/parser.js:287:98)
at Parser.handlePacket (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/parser.js:126:29)
at Parser.parse (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/parser.js:39:38)
at Socket.<anonymous> (/Users/darius/IdeaProjects/node-jwt-auth-postgresql/node_modules/pg-protocol/dist/index.js:11:42)
at Socket.emit (node:events:513:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
length: 90,
severity: 'ERROR',
code: '42601',
detail: undefined,
hint: undefined,
position: '83',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'scan.l',
line: '1180',
routine: 'scanner_yyerror',
sql: "SELECT ('title')\n" +
' FROM Book\n' +
' WHERE searchable ## to_tsquery([object Object]);',
parameters: undefined
},
sql: "SELECT ('title')\n" +
' FROM Book\n' +
' WHERE searchable ## to_tsquery([object Object]);',
parameters: {}
}
[nodemon] app crashed - waiting for file changes before starting...
First, you passed the whole query object instead of the searchable prop only.
Second, it's better to use bind option to pass such values safely (remember about SQL injection!).
await sequelize.query(`
SELECT ('title')
FROM Book
WHERE searchable ## to_tsquery($searchable);
`, {
type: QueryTypes.SELECT,
bind: {
searchable: req.query.searchable
}
})

Unable to update data using prisma

I am using prisma to update some fields but i am getting error.
I am using unique id to update the data.
Before update i am able to get all the data from table so prisma is working on select
const cartUpdate = await prisma.custom_checkout__c.update({
where: {
id: uniqueId,
},
data: {
status__c: 'Checkout completed',
coupon_code__c: coupon,
checkout_id__c: result.subscription.id,
}
})
Error is below
PrismaClientUnknownRequestError:
Invalid `prisma.custom_checkout__c.update()` invocation:
Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Error { kind: Db, cause: Some(DbError { severity: "ERROR", parsed_severity: Some(Error), code: SqlState(E42883), message: "function get_xmlbinary() does not exist", detail: None, hint: Some("No function matches the given name and argument types. You might need to add explicit type casts."), position: Some(Internal { position: 2, query: "(get_xmlbinary() = 'base64')" }), where_: Some("PL/pgSQL function hc_custom_checkout__c_status() line 3 at IF"), schema: None, table: None, column: None, datatype: None, constraint: None, file: Some("parse_func.c"), line: Some(629), routine: Some("ParseFuncOrColumn") }) }) })
at RequestHandler.handleRequestError (/Users/bi

Null value in column "title" of relation "blog" violates not-null constraint

I'm building a little blog using express js for the backend, but I'm facing an issue: I get this error in the console
null value in column "contentblog" of relation "blog" violates not-null constraint
Code:
const connection = require('../DatabaseConnection/db')
module.exports.Add = function (req, res) {
const blog = {
title: req.body.title,
contentBlog: req.body.contentBlog,
}
connection.query('INSERT INTO blog(contentBlog) values($1)', [blog.contentBlog], function (error, results, fields) {
if (error) {
res.json({
status: false,
message: 'there are some errors with the query'
})
console.log(error)
} else {
res.json({
status: true,
data: results,
message: 'Post has been added successfully'
})
}
});
}
You are trying to insert a null or undefined variable into your postgresql table.
Check the value of req.body.contentBlog.

Mongoose create on session fails on validation

I am trying to create a document, on an existing collection, using MongoDB + async..await programming + session/transaction control (in order to be able to rollback to a previous state if anything goes wrong). The relevant code is shown below:
exports.campaign_totalize = async (campaign, start_date, end_date, now) => {
var session = await mongoose.startSession();
session.startTransaction();
try {
// ...
let commission = await commissionModel.create({
datetime: Date.now(),
value: 10,
status: 'issued',
affiliate: affiliate_id,
campaign: campaign_id
}, { session: session });
// ...
}
// ...
} catch (err) {
console.log("Error totalizing commissions:", err);
await session.abortTransaction();
session.endSession();
throw err;
}
}
Executing code above I get ValidationError on ALL fields (even being sure they are all OK). If I remove the session parameter, however, everything works fine! The collections exists for sure.
Below information about my environment:
"dependencies": {
"express": "^4.16.4",
"mongoose": "^5.3.9",
"mongoose-bcrypt": "^1.6.0",
"validator": "^10.9.0"
}
$ node --version
v10.14.0
$ mongod --version
db version (v3.6.3) -> v4.0.4
Thank you very much.
Update:
As Shivam Pandey pointed out in the comments, mongoDB version starts supporting transactions on version 4.0. I just updated it to 4.0.4 and it is returning the same errors, though.
Update 2:
Stack trace:
Trace: error
at Object.exports.campaign_totalize (/home/luiz/magalabs/magafilio/magafilio-server/logic/commission_calc.js:147:17)
at process._tickCallback (internal/process/next_tick.js:68:7)
Error totalizing commissions: { ValidationError: Commission validation failed: campaign: All commissions must be associated to a campaign, affiliate: All commissions must be associated to an affiliate, status: Commission needs a status associated, value: Commission needs a value - use 0 for no valued commissions, datetime: Commission needs date/time info
at ValidationError.inspect (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/error/validation.js:59:24)
at formatValue (internal/util/inspect.js:453:31)
at inspect (internal/util/inspect.js:193:10)
at Object.formatWithOptions (util.js:165:18)
at Console.(anonymous function) (console.js:188:15)
at Console.log (console.js:199:31)
at Object.exports.campaign_totalize (/home/luiz/magalabs/magafilio/magafilio-server/logic/commission_calc.js:148:17)
at process._tickCallback (internal/process/next_tick.js:68:7)
errors:
{ campaign:
{ ValidatorError: All commissions must be associated to a campaign
at new ValidatorError (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:844:13)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:897:11
at Array.forEach (<anonymous>)
at ObjectId.SchemaType.doValidate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:853:19)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/document.js:1893:9
at process._tickCallback (internal/process/next_tick.js:61:11)
message: 'All commissions must be associated to a campaign',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'campaign',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true },
affiliate:
{ ValidatorError: All commissions must be associated to an affiliate
at new ValidatorError (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:844:13)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:897:11
at Array.forEach (<anonymous>)
at ObjectId.SchemaType.doValidate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:853:19)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/document.js:1893:9
at process._tickCallback (internal/process/next_tick.js:61:11)
message: 'All commissions must be associated to an affiliate',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'affiliate',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true },
status:
{ ValidatorError: Commission needs a status associated
at new ValidatorError (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:844:13)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:897:11
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:853:19)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/document.js:1893:9
at process._tickCallback (internal/process/next_tick.js:61:11)
message: 'Commission needs a status associated',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'status',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true },
value:
{ ValidatorError: Commission needs a value - use 0 for no valued commissions
at new ValidatorError (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:844:13)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:897:11
at Array.forEach (<anonymous>)
at SchemaNumber.SchemaType.doValidate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:853:19)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/document.js:1893:9
at process._tickCallback (internal/process/next_tick.js:61:11)
message: 'Commission needs a value - use 0 for no valued commissions',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'value',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true },
datetime:
{ ValidatorError: Commission needs date/time info
at new ValidatorError (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:844:13)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:897:11
at Array.forEach (<anonymous>)
at SchemaDate.SchemaType.doValidate (/home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/schematype.js:853:19)
at /home/luiz/magalabs/magafilio/magafilio-server/node_modules/mongoose/lib/document.js:1893:9
at process._tickCallback (internal/process/next_tick.js:61:11)
message: 'Commission needs date/time info',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'datetime',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true } },
_message: 'Commission validation failed',
name: 'ValidationError' }
I think there's an issue with how you're using the create, or at least that's my first guess.
To specify options, docs must be an array, not a spread.
https://mongoosejs.com/docs/api.html#model_Model.create
Has to be in this form
Model.create([doc], options)
you have
Model.create(doc, options)
This might be what you want
let [commission] = await commissionModel.create([{datetime: Date.now(),
...}], {session})
let [commission] = await commissionModel.create([doc], options})
When you pass an array into Model.create(), Model.create() will return an array with the documents you created/saved so that's why I used "let [commission]" which will set variable commission to the first item in the array that gets returned.

Postgres: create a new jsonb object with matched values

So I have this table questions that have a settings jsonb column:
{
id: 'question-id-1',
settings: {
foo1: true,
foo2: true,
bar: false
}
},
{
id: 'question-id-2',
settings: {
bar: true
}
}
now I want to make a postgres db update migration script that results to:
{
id: 'question-id-1',
settings: {
foo1: true,
foo2: true,
bar: false,
opts: ['foo1', 'foo2']
}
},
{
id: 'question-id-2',
settings: {
bar: true,
opts: ['bar']
}
}
so only those that has values true is added to a new opts array inside settings.
This is for Postgres 9.5.
Thank you in advanced.
Create a function to update the column:
create or replace function add_opts(jsonb)
returns jsonb language sql as $$
select $1 || jsonb_build_object('opts', jsonb_agg(key))
from jsonb_each_text($1)
where value::bool;
$$;
Test:
with questions(settings) as (
values
('{
"foo1": true,
"foo2": true,
"bar": false
}'::jsonb)
)
select add_opts(settings)
from questions;
add_opts
----------------------------------------------------------------------
{"bar": false, "foo1": true, "foo2": true, "opts": ["foo1", "foo2"]}
(1 row)
Your update query should look like this:
update questions
set settings = add_opts(settings);
The variant which eliminates the opts array when there are no set options:
create or replace function add_opts(jsonb)
returns jsonb language sql as $$
select case
when jsonb_agg(key) is null then $1
else $1 || jsonb_build_object('opts', jsonb_agg(key))
end
from jsonb_each_text($1)
where value::bool;
$$;