How to pass param inside single quotes to a postgres query? - node.js

In my node app, i need to run below query and and i'm passing parameters dynamically. But it's not fetching the parameters since they are referenced inside single quotes. Suggest a solution for this.
const text = `UPDATE glacier_restore_progress
SET
status='completed',
restore_end=CURRENT_TIMESTAMP,
restore_expire=DATE_TRUNC('minutes', current_timestamp + interval '$1 minutes')
WHERE file_path = '$2' AND date_trunc('minutes', current_timestamp - interval '$1 minutes') <= restore_start`;
const values = [restoreDuration, fileKey];
await pool.query(text, values);
and the error i get is,
"bind message supplies 2 parameters, but prepared statement \"\" requires 0"

You are absolutely right; parameters cannot be inside quotes. There are a few ways we can solve this:
Taking the similarly broken example SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL '$1 years';
Have the client submit the "full" value: SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL $1;
Construct string in the query: SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL ($1 || ' years');
(interval specific) Use the fact the unit can be specified as its own keyword: SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL $1 MINUTE
My preference in this case is 1, however the most faithful to your question is 3. Be careful to use MINUTE and not MINUTES. Option 2, using the concatentation operator, is a good hack to have in your toolbelt. All answers tested in Postgres 13.
In addition to this, your parameter is likely going to bound as a number, which will get you an error. You may need to cast it to text, like so $1::TEXT
Your full query would be:
UPDATE glacier_restore_progress
SET
status = 'completed',
restore_end = CURRENT_TIMESTAMP,
restore_expire = DATE_TRUNC('minutes', CURRENT_TIMESTAMP + INTERVAL $1::TEXT MINUTE)
WHERE file_path = $2
AND DATE_TRUNC('minutes', current_timestamp - INTERVAL $1 MINUTE) <= restore_start

use this,
const text = `UPDATE glacier_restore_progress
SET
status='completed',
restore_end=CURRENT_TIMESTAMP,
restore_expire=DATE_TRUNC('minutes', current_timestamp + interval '1 minutes' * $1)
WHERE file_path = $2 AND date_trunc('minutes', current_timestamp - interval '1 minutes' * $1) <= restore_start`;
const values = [restoreDuration, fileKey];
await pool.query(text, values);
this convention is mentioned here refrence

Related

Influx subquery returns no results

I'm experimenting with subqueries in InfluxDB (shell version: 1.7.4), and I've encountered this issue:
> SELECT "value" AS "legacy" FROM my_table WHERE time >= '2022-12-22 18:00:00' AND entityId = '637deee12ccd09000b8bea57' tz('Europe/Athens')
name: my_table
time legacy
---- ------
2022-12-22T18:15:16.261+02:00 11
2022-12-22T19:15:30.65+02:00 12
> SELECT * FROM (SELECT "value" AS "legacy" FROM my_table WHERE time >= '2022-12-22 18:00:00' AND entityId = '637deee12ccd09000b8bea57' tz('Europe/Athens'))
>
> SELECT SUM(*) FROM (SELECT "value" AS "legacy" FROM my_table WHERE time >= '2022-12-22 18:00:00' AND entityId = '637deee12ccd09000b8bea57' tz('Europe/Athens'))
>
The second and third queries, both return an empty result. I would expect the second to return the same result as the first one, and the third to return the sum. What have I misunderstood?

ScyllaDB window function-like query

I am using ScyllaDB open-source version 4.4.
I am trying to figure out how to write a query which I would have done with a window function or a UNION set operator if this was a traditional relational database with a full SQL.
A simplified table schema:
CREATE TABLE mykeyspace.mytable (
name text ,
timestamp_utc_nanoseconds bigint ,
value bigint ,
PRIMARY KEY( (name),timestamp_utc_nanoseconds )
) WITH CLUSTERING ORDER BY (timestamp_utc_nanoseconds DESC);
My query needs to calculate and return 6 values, each of them is an average of "value" over one of the previous minutes.
In pseudo-code:
SELECT AVG(value) AS one_min_avg_6_min_ago FROM mykeyspace.mytable WHERE name = 'some_name' AND timestamp_utc_nanoseconds >= [*6 minutes ago*] AND timestamp_utc_nanoseconds < [*5 minutes ago*];
SELECT AVG(value) AS one_min_avg_5_min_ago FROM mykeyspace.mytable WHERE name = 'some_name' AND timestamp_utc_nanoseconds >= [*5 minutes ago*] AND timestamp_utc_nanoseconds < [*4 minutes ago*];
SELECT AVG(value) AS one_min_avg_4_min_ago FROM mykeyspace.mytable WHERE name = 'some_name' AND timestamp_utc_nanoseconds >= [*4 minutes ago*] AND timestamp_utc_nanoseconds < [*3 minutes ago*];
SELECT AVG(value) AS one_min_avg_3_min_ago FROM mykeyspace.mytable WHERE name = 'some_name' AND timestamp_utc_nanoseconds >= [*3 minutes ago*] AND timestamp_utc_nanoseconds < [*2 minutes ago*];
SELECT AVG(value) AS one_min_avg_2_min_ago FROM mykeyspace.mytable WHERE name = 'some_name' AND timestamp_utc_nanoseconds >= [*2 minutes ago*] AND timestamp_utc_nanoseconds < [*1 minutes ago*];
SELECT AVG(value) AS one_min_avg_1_min_ago FROM mykeyspace.mytable WHERE name = 'some_name' AND timestamp_utc_nanoseconds >= [*1 minute ago*];
My client-side is C# .NET 5. I can easily do pretty much anything on the client side. But the latency in this case is going to be a big problem.
My question is:
How can I combine these 6 queries into one result set on the server side (not on the client app side)?
Ideally you would use a UDA - User Defined Aggregate function, however support for these is not yet complete. In the meantime, you can execute these 6 queries in parallel which might even be preferable.

sqlite3 variable substitution not working python3

I'm trying to get the SQLlite3 variable substitution in Python working, but I always get the error:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.
I've tried:
date_range = '10'
with sqlite3.connect(DATABASE_LOGIN) as connection:
cursor = connection.cursor()
template = "SELECT DISTINCT date FROM schedule WHERE date BETWEEN DATETIME('NOW') AND DATETIME('NOW', '-? DAYS') ORDER BY date"
cursor.execute(template, date_range)
and I know it's very bad form to use:
date_range = '10'
with sqlite3.connect(DATABASE_LOGIN) as connection:
cursor = connection.cursor()
template = f"SELECT DISTINCT date FROM schedule WHERE date BETWEEN DATETIME('NOW') AND DATETIME('NOW', '-{date_range} DAYS') ORDER BY date"
cursor.execute(template)
but for some reason the former query doesn't work.
You must concatenate the placeholder ?:
SELECT DISTINCT date
FROM schedule
WHERE date BETWEEN DATETIME('NOW') AND DATETIME('NOW', '-' || ? || ' DAY') ORDER BY date

Athena query results show null values despite is not null condition in query

I have the following query which I run in Athena. I would like to receive all the results that contain a tag in the 'resource_tags_aws_cloudformation_stack_name'. However, when I run the query my results show me rows where the 'resource_tags_aws_cloudformation_stack_name' is empty and I don't know what I am doing wrong.
SELECT
cm.line_item_usage_account_id,
pr.line_of_business,
cm.resource_tags_aws_cloudformation_stack_name,
SUM(CASE WHEN cm.line_item_product_code = 'AmazonEC2'
THEN line_item_unblended_cost * 0.97
ELSE cm.line_item_unblended_cost END) AS discounted_cost,
CAST(cm.line_item_usage_start_date AS DATE) AS start_day
FROM cost_management cm
JOIN prod_cur_metadata pr ON cm.line_item_usage_account_id = pr.line_item_usage_account_id
WHERE cm.line_item_usage_account_id IN ('1234504482')
AND cm.resource_tags_aws_cloudformation_stack_name IS NOT NULL
AND cm.line_item_usage_start_date
BETWEEN date '2020-01-01'
AND date '2020-01-30'
GROUP BY cm.line_item_usage_account_id,pr.line_of_business, cm.resource_tags_aws_cloudformation_stack_name, CAST(cm.line_item_usage_start_date AS DATE), pr.line_of_business
HAVING sum(cm.line_item_blended_cost) > 0
ORDER BY cm.line_item_usage_account_id
I modified my query to exclude ' ' and that seems to work:
SELECT
cm.line_item_usage_account_id,
pr.line_of_business,
cm.resource_tags_aws_cloudformation_stack_name,
SUM(CASE WHEN cm.line_item_product_code = 'AmazonEC2'
THEN line_item_unblended_cost * 0.97
ELSE cm.line_item_unblended_cost END) AS discounted_cost,
CAST(cm.line_item_usage_start_date AS DATE) AS start_day
FROM cost_management cm
JOIN prod_cur_metadata pr ON cm.line_item_usage_account_id = pr.line_item_usage_account_id
WHERE cm.line_item_usage_account_id IN ('1234504482')
AND NOT cm.resource_tags_aws_cloudformation_stack_name = ' '
AND cm.line_item_usage_start_date
BETWEEN date '2020-01-01'
AND date '2020-01-30'
GROUP BY cm.line_item_usage_account_id,pr.line_of_business, cm.resource_tags_aws_cloudformation_stack_name, CAST(cm.line_item_usage_start_date AS DATE), pr.line_of_business
HAVING sum(cm.line_item_blended_cost) > 0
ORDER BY cm.line_item_usage_account_id
You can try space use case as below
AND Coalesce(cm.resource_tags_aws_cloudformation_stack_name,' ') !=' '
Or if you have multiple spaces try. The below query is not good if spaces required in actual data
AND Regexp_replace(cm.resource_tags_aws_cloudformation_stack_name,' ') is not null
Adding to this you may also have special char like CR or LF in data. Although its rare scenario

Getting DateTime difference in OrientDB

I have the following Carts table schema of orientDB. All I wanted to do is to select those records where
(CurrentTime - timeStamp) >= expiration
I had also tried to achive my goal thorugh converting to unix timestamp and tried following queries
SELECT * FROM Carts WHERE eval("('+new Date().getTime()+' timeStamp.asLong())/1000") >= expiration
And also by following technique but when :parameter is passed in eval funtion it convert it into '?' and don't return required data.
db.query(
'SELECT eval("'+new Date().getTime()+' - timeStamp.asLong()") as DIFF, :nowTimeStamp as NOW, timeStamp.asLong() as THEN FROM Carts ',
{
params: {
nowTimeStamp: new Date().getTime()
}
}).then(callback);
Try this query:
SELECT * FROM Carts WHERE eval("SYSDATE().asLong() / 1000 - timeStamp.asLong() / 1000") >= expiration
Hope it helps.

Resources