Why is TIMESTAMP column always zero after updating using Node JS? - javascript

query("CREATE TABLE IF NOT EXISTS `discount_codes` (`discount_code` VARCHAR(50), `expirationDate` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `claimedBy` VARCHAR(15), `type` TEXT)")
exports.claimDiscount = function(code, user) {
var queryString = "UPDATE discount_codes SET expirationDate=NOW(), claimedBy = ? WHERE discount_code = ?"
try{
query(queryString, [user, code])
} catch(err){
console.log(err)
}
}
The column is always 0000-00-00 00:00:00, both on insert query and update query, the other column is updated correctly. I have no idea what I am doing wrong, punching my head in wall for hours because of this. Any help is really appreciated

I think you are missing some parentheses.
Use TIMESTAMP DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP() instead of TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

Related

Building a MySQL query from optional filters in Express JS

Sorry if it's a dumb question but I'm new to express and MySQL and I couldn't find a solution anywhere.
I need to create a MySQL query based on some user input filters from an HTML form.
The parameters are something like this:
let sDate = req.body.startDate;
let eDate = req.body.endDate;
let param1 = req.body.param1;
let param2 = req.body.param2;
let param3 = req.body.param3;
let param4 = req.body.param4;
A normal query that I will use if all params are not null will be
const query = `
SELECT * FROM table
WHERE
date BETWEEN ? AND ?
AND col1 = ?
AND col2 = ?
AND col3 = ?
AND col4 = ?;`
db.query(query, [startDate, endDate, param1, param2, param3, param4], (e, rows)=>{});
But every single parameter can be null, so there are a lot of possible filter combinations.
Is there a way to query the db with one single query? I could handle it in many if-else statements but it feels wrong.
Thanks for your help in advance!
For your col1 = ? pattern you can use (? IS NULL OR ? = col1).
For your date matching you can do this.
WHERE date <= IF( ? IS NOT NULL THEN ? ELSE '2999-12-31')
AND date >= IF( ? IS NOT NULL THEN ? ELSE '1000-01-01')
But notice that parameters appear twice. So your query is
const sql = `
SELECT *
FROM tbl
WHERE date <= IF(? IS NOT NULL, ?, '2999-12-31')
AND date >= IF(? IS NOT NULL, ?, '1000-01-01')
AND (? IS NULL OR col1 = ?)
AND (? IS NULL OR col2 = ?)
AND (? IS NULL OR col3 = ?)
AND (? IS NULL OR col4 = ?);`
And you'll invoke it like this.
const params = [startDate, startDate,
endDate, endDate,
param1, param1,
param2, param3,
param2, param3,
param4, param4]
db.query(query, params, (e, rows)=>{});
But beware: this kind of query is a notorious edge case for the query-optimization software in the database server. It can't tell what you want well enough to use table statistics to choose the right index. Still, be sure to put an index on
(date, col1, col2, col3, col4)
for this query. You're likely to have a date range.
This may be slow, especially if that table is really large. You may be better off building up a custom query from strings each time you handle the request. The query optimizer understands stuff like this better than stuff with that ? IS NULL OR clause in there.
WHERE date <= ?
AND date >= ?
AND col2 = ?
AND col3 = ?
You can use a LIKE clause with a combination of the COALESCE() function and the NULLIF() function to prevent a NULL value from being passed to the LIKE clause
const query = "SELECT * FROM accounts WHERE name LIKE COALESCE(NULLIF(?, ''), '%')";
const values = [name];

PostgreSQL outputs different TimeStamp format than Javascript TimeStamp format

I'm having trouble binding the results from SQL to my Model in Javascript /Typescript.
In my model, I have a property of created_at with types of Date.
When I use JSON functions in the Postgres SQL statement to avoid duplicate parent rows for a relationship, I will get a different format for the timestamp.
Here is a simple example
SELECT
a.*,
(
SELECT
ROW_TO_JSON(profile)
FROM
(
SELECT
*
FROM
profile p
WHERE
p.account_id = a.id
)
profile
)
AS profile
FROM
account a
WHERE
a.id = 16
And here are the results in JSON
{
"id":16,
"email":"test#gmail.com",
"password":"$password",
"role_id":0,
"created_at":"2020-04-01T22:03:44.324Z",
"profile":{
"id":8,
"username":"firmanjml",
"gender":0,
"bio":null,
"avatar":"www.firmanjml.me/test.jpg",
"account_id":16,
"created_at":"2020-04-02T06:03:44.32498"
}
}
I noticed that the parent row which is from the account table has the Z at the end of created_at whereas the child table that is converted to JSON has a different timestamp format.
Is there a way that I could make all the timestamp be in Javascript format?
Query to create schema and insert data
CREATE TABLE "account"(
id SERIAL primary key,
email varchar(50) not null,
password varchar(50) not null,
role_id int2 default 0 not null,
created_at timestamp default now() not null
);
CREATE TABLE "profile"(
id SERIAL primary key,
username varchar(50) not null,
gender int2 not null,
bio varchar(50),
avatar varchar(50),
account_id integer not null REFERENCES account (id),
created_at timestamp default now() not null
);
INSERT INTO "account" (email,"password","role_id",created_at) VALUES
('test#gmail.com','$password',0,'2020-04-02 06:03:44.324');
INSERT INTO "profile" (username,gender,bio,avatar,account_id,created_at) VALUES
('fimrnajml',0,NULL,'www.firmanjml.me/test.jpg',1,'2020-04-02 06:03:44.324');
Use the TO_CHAR() function to format the timestamp in your SQL, like https://www.postgresqltutorial.com/postgresql-to_char/
A format of 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"' should do it. This assumes all your timestamps are in UTC (the way the pros do it :-)
Your SQL then looks like:
SELECT
a.*,
(
SELECT
ROW_TO_JSON(profile)
FROM
(
SELECT
username,gender,bio,avatar,account_id,to_char(created_at, 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') created_at
FROM
profile p
WHERE
p.account_id = a.id
)
profile
)
AS profile
FROM
account a
WHERE
a.id = 16
try it here

Javascript variable being overwriiten after query execution

I am using mysql database with Nodejs. I am running a query like this:
rows = await pool.query(`Select partID,stageID,locationID,QuantityAfter, QuantityChange, rowDeleted from InventoryTransactions
where partID = ${item.partID} and stageID = ${item.stageID} and locationID = ${item.locationID} and orderID = ${orderID}
order by transactionID desc`)
if(rows[0].rowDeleted != 1){ //This means that the quantity in the inventory table and inv trans table is not the same
console.log(`=====================================`)
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
await pool.query(`Insert into inventorytransactions(OrderID,PartID,LocationID,StageID,QuantityBefore,QuantityChange,QuantityAfter,ITTTimeStamp,rowDeleted,id)
Values(${orderID},${rows[0].partID},${rows[0].locationID},${rows[0].stageID},${parseInt(rows[0].QuantityAfter)},${-parseInt(rows[0].QuantityChange)},${parseInt(rows[0].QuantityAfter)-parseInt(rows[0].QuantityChange)},'${(new Date ((new Date((new Date(new Date())).toISOString() )).getTime() - ((new Date()).getTimezoneOffset()*60000))).toISOString().slice(0, 19).replace('T', ' ')}',true,${id})`)
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
console.log(`Update inventory set Quantity = quantity - ${Number(rows[0].QuantityChange)} where partID =${rows[0].partID} and stageID = ${rows[0].stageID} and locationID = ${rows[0].locationID}`)
await pool.query(`Update inventory set Quantity = quantity - ${Number(rows[0].QuantityChange)} where partID =${rows[0].partID} and stageID = ${rows[0].stageID} and locationID = ${rows[0].locationID} `)
console.log(`=====================================`)
}
The reason I have so many console.log is because I have encountered a very weird bug. All of the values of rows[0].QuantityChange) should be the same.
But my console shows:
====================================
4
4
4
425
NaN
NaN
NaN
Update inventory set Quantity = quantity - NaN where partID =12462 and stageID = 1 and locationID = 1
{ Error: ER_BAD_FIELD_ERROR: Unknown column 'NaN' in 'field list'
I know 425 is the value of ${id} variable which can be found at the end of the insert sql statement. Which makes no sense to me. What makes even less sense is how are the the bottom values are undefined or NAN
The 425 likely comes from some other code that is running during your await pool.query() statement (not from anything in the code you show us). await blocks the execution of the local function, but it does not block the event queue so other events can run while an await ... is waiting for completion.
Then, you don't show where rows is defined, but it seems possible that it's getting overwritten by some other code that is running during the await. If you show us a lot more context around this code including where rows is defined, we could advise and explain in more detail.
I'm not sure, but, in this part
'${(new Date ((new Date((new Date(new Date())).toISOString() )).getTime() - ((new Date()).getTimezoneOffset()*60000))).toISOString().slice(0, 19).replace('T', ' ')}'
Exist an incorrect use of single quotes, which can be altering the result of the consult. You should scape inner single quotes, or use Double quotes for wrapping the complete instruction.
"${(new Date ((new Date((new Date(new Date())).toISOString() )).getTime() - ((new Date()).getTimezoneOffset()*60000))).toISOString().slice(0, 19).replace('T', ' ')}"

column is of type timestamp without time zone but expression is of type integer

I get error message like below , when I create this table just like others set column timestamp timestamp without time zone NOT NULL , but when I tried to insert 2015-08-16 18:51:05 to this table, then I get error, but other table is work, why and how to solve it?
CREATE TABLE IF NOT EXISTS "UserForgetPasswordPending"(
"UserForgetPasswordPendingId" SERIAL NOT NULL,
"Email" varchar(50) NOT NULL,
"TokenTimestamp" timestamp without time zone NOT NULL,
"Token" varchar(100) NOT NULL,
PRIMARY KEY ("UserForgetPasswordPendingId")
);
ALTER TABLE "UserForgetPasswordPending"
OWNER TO db_admin;
error
[error: column "TokenTimestamp" is of type timestamp without time zone but expression is of type integer]
name: 'error',
length: 216,
severity: 'ERROR',
code: '42804',
detail: undefined,
hint: 'You will need to rewrite or cast the expression.',
insert
var utc = moment(new Date()).unix();
var tokenTimestamp = moment.unix(utc).format('YYYY-MM-DD HH:mm:ss');
var upsertUserForgetPasswordPending = function(userEmail, tokenTimestamp, token) {
return new Promise(function (fulfill, reject){
var queryInsert = 'INSERT INTO "UserForgetPasswordPending" ("Email","TokenTimestamp","Token") SELECT $1,2,$3';
var queryUpsert = 'UPDATE "UserForgetPasswordPending" SET "TokenTimestamp" = $2, "Token" = $3 WHERE "Email" = $1';
var query = 'WITH upsert AS ('+queryUpsert+' RETURNING *) '+queryInsert+' WHERE NOT EXISTS (SELECT * FROM upsert)';
console.log(tokenTimestamp);
dbClient.query(query, [userEmail,tokenTimestamp,token], function(error, result) {
if (error) {
reject(error);
} else {
fulfill(result);
}
});
});
};
This because you are inserting integer data to time stamp column.
Correct the following syntax:
var queryInsert = 'INSERT INTO "UserForgetPasswordPending ("Email","TokenTimestamp","Token") SELECT $1,2,$3';
In above query you are selecting 2 for TokenTimestamp that's why you are getting this error.
you should replace 2 with some date time format yyyy-mm-dd hh:mm:ss .
For example: '2015-08-07 05:00:01'
For me casting the type explicitely worked.
Please note, I used joda Datetime
#CreatedDate
#Column(name = "created_on", updatable = false, nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime createdOn;

parse.com - query Constraints on filed just if exist

How can I do it?
query.exists("year");
query.lessThanOrEqualTo("year", toYear);
query.greaterThanOrEqualTo("year", fromYear);
When the code is like above I get an error - I think it is because I have blank filed "year".
How can I do the Constraints on the "year" filed only if the "exists" is true?
thanks
simply use two queries..
//1st query
query.exists("year");
query.find{
success:{
//2nd query
query.lessThanOrEqualTo("year", toYear);
query.greaterThanOrEqualTo("year", fromYear);
query.find{
success:{
//desired result
}
}
}error:{
//"year does not exists";
}

Categories

Resources