Sqlx only accept string literal in query macro, how to use variable? - postgresql

The codes:
// very complex where clause combined from several runtime variables.
let query: String = String.from("where ..........");
let rows_num: i64 = sqlx::query!( &*query).fetch_one(connection)
The error from compiler:
error: expected string literal
--> src/abc.rs:80:25
|
80 | let rows_num: i64 = sqlx::query!(
| ____________^
81 | | &*query,
82 | | ).fetch_one(connection)
| |^
|
= note: this error originates in the macro sqlx::query (in Nightly builds, run with -Z macro-backtrace for more info)
And the doc states:
The query must be a string literal or else it cannot be introspected (and thus cannot be dynamic or the result of another macro).
I know the sqlx computes at compile time, my where clause computation is at run time.
I really want to use variable, because the where clause depends other several conditions.
Are there any ways to use variable in sqlx?

Using sqlx::query() function instead of the sqlx::query!() macro. The document doesn't mention it in their page.

Related

Azure Log Analytics for Postgres Flexible Server

Just trying to use a pre-existing "Slowest queries - top 5" from Azure log analytics for postgres flexible server. The query that is provided is:
// Slowest queries
// Identify top 5 slowest queries.
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.DBFORPOSTGRESQL"
| where Category == "QueryStoreRuntimeStatistics"
| where user_id_s != "10" //exclude azure system user
| summarize avg(todouble(mean_time_s)) by event_class_s , db_id_s ,query_id_s
| top 5 by avg_mean_time_s desc
This query results in the error :
'where' operator: Failed to resolve column or scalar expression named 'user_id_s'
If the issue persists, please open a support ticket. Request id: XXXX
I am guessing that something is not configured in order to utilize the user_id_s column. Any assistance is appreciated.
I am expecting you are checking the integer value 10 is not equal to the user_id_s.
In your KQL query user_id_s != "10" .
Thanks # venkateshdodda-msft I am adding your suggestion to help to fix the issue.
If you are using integer in a KQL make sure to remove the " " double quotes.
# using as a integer
| where user_id_s != 10
Or convert the integer into string by using
# converting into string
| extend user_id_s = tostring(Properties.user_id_s)
| where UserId in ('10')
Modified KQL Query
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.DBFORPOSTGRESQL"
| where Category == "QueryStoreRuntimeStatistics"
# using as a integer
| where user_id_s != 10 //exclude azure system user
| summarize avg(todouble(mean_time_s)) by event_class_s , db_id_s ,query_id_s
| top 5 by avg_mean_time_s desc
Reference:
Operator failed to resolve table or column expression
Converting integer to string

How to use dynamic table name for sub query where the dynamic value coming from its own main query in PostgreSQL?

I have formed this query to get the desired output mentioned below:
select tbl.id, tbl.label, tbl.input_type, tbl.table_name
case when tbl.input_type = 'dropdown' or tbl.input_type = 'searchable-dropdown'
then (select json_agg(opt) from tbl.table_name) as opt) end as options
from mst_config as tbl;
I want output like below:
id | label | input_type | table_name | options
----+----------------------------------------------------+---------------------+-------------------------+-----------------------------------------------------------
1 | Gender | dropdown | mst_gender | [{"id":1,"label":"MALE"},
| | | | {"id":2,"label":"FEMALE"}]
2 | SS | dropdown | mst_ss | [{"id":1,"label":"something"},
| | | | {"id":2,"label_en":"something"}]
But, I'm facing a problem while using,
select json_agg(opt) from tbl.table_name) as opt
In the above part "tbl.table_name", I wanted to use it as dynamic table name but it's not working.
Then, I have searched a lot and found something like Execute format('select * from %s', table_name), where tablename is the dynamic table name. I have even tried the same with postgres function.
But I faced an issue again while using the format method. The reason is I want to use the variable for which the value needs to come from its own main query value instead of already having it in a variable. so this one was also not working.
I would really appreciate if anyone can help me out on this. Also if there are any other possibilities available to achieve this output, help me on that as well.

Try to update postgresql database using Doobie but no update happening

I'm trying to update table in postgresql database passing dynamic value using doobie functional JDBC while executing sql statement getting below error.Any help will be appreciable.
Code
Working code
sql"""UPDATE layout_lll
|SET runtime_params = 'testing string'
|WHERE run_id = '123-ksdjf-oreiwlds-9dadssls-kolb'
|""".stripMargin.update.quick.unsafeRunSync
Not working code
val abcRunTimeParams="testing string"
val runID="123-ksdjf-oreiwlds-9dadssls-kolb"
sql"""UPDATE layout_lll
|SET runtime_params = '${abcRunTimeParams}'
|WHERE run_id = '$runID'
|""".stripMargin.update.quick.unsafeRunSync
Error
Exception in thread "main" org.postgresql.util.PSQLException: The column index is out of range: 3, number of columns: 2.
Remove the ' quotes - Doobie make sure they aren't needed. Doobie (and virtually any other DB library) uses parametrized queries, like:
UPDATE layout_lll
SET runtime_params = ?
WHERE run_id = ?
where ? will be replaced by parameters passes later on. This:
makes SQL injection impossible
helps spotting errors in SQL syntax
When you want to pass parameter, the ' is part of the value passed, not part of the parametrized query. And Doobie (or JDBC driver) will "add" it for you. The variables you pass there are processed by Doobie, they aren't just pasted there like in normal string interpolation.
TL;DR Try running
val abcRunTimeParams="testing string"
val runID="123-ksdjf-oreiwlds-9dadssls-kolb"
sql"""UPDATE layout_lll
|SET runtime_params = ${abcRunTimeParams}
|WHERE run_id = $runID
|""".stripMargin.update.quick.unsafeRunSync

Getting an error of 'Token Unknown' while Execute Stored Procedures

I'm new in learning stored procedures in SQL.
I want to create a stored procedure for inserting values from automatic data by calculation.
Table Attendance:
EMPL_KODE |EMPL_NAME |DATE_IN |TIME_IN |TIME_OUT|TIME_IN |TIME_OUT
001 | Michel |25.04.2016 |06:50 |15:40 | |
002 | Clara |25.04.2016 |06:15 |15:43 | |
003 | Rafael |25.04.2016 |06:25 |15:45 | |
001 | Michel |26.04.2016 |06:23 |15:42 | |
002 | Clara |26.04.2016 |06:10 |15:41 | |
003 | Rafael |26.04.2016 |06:30 |15:42 | |
001 | Michel |27.04.2016 |06:33 |15:42 | |
002 | Clara |27.04.2016 |06:54 |15:44 | |
003 | Rafael |27.04.2016 |07:00 |15:45 | |
I want to fill TIME_IN and TIME_OUT values automatically by creating a stored procedure. Here is the code :
CREATE PROCEDURE InsertTotalEmployee
#TOTAL_MINUTES int,
#TOTAL_HOURS float
AS
BEGIN
INSERT INTO ATTENDANCE (TOTAL_MINUTES, TOTAL_HOURS)
VALUES (
SELECT
DATEDIFF(MINUTE, ATTENDANCE.TIME_IN, ATTENDANCE.TIME_OUT),
DATEDIFF(MINUTE, ATTENDANCE.TIME_IN, ATTENDANCE.TIME_OUT) / 60.0
)
END
After I write and execute my statement, a message error occurs:
Token unknown - line 2, column 5 #
I run the code using Flamerobin.
It looks like you are trying to use Microsoft SQL Server syntax in Firebird, that is not going to work.
For one, the # is not allowed like that in identifiers (unless you use double quotes around them), and the list of parameters must be enclosed in parentheses.
See the syntax of CREATE PROCEDURE. You need to change it to:
CREATE PROCEDURE InsertTotalEmployee(TOTAL_MINUTES int, TOTAL_HOURS float)
You also might want to change the datatype float to double precision, and the body of your stored procedure seems to be incomplete because you are selecting from nothing (a select requires a table to select from), and are missing a semicolon at the end of the statement.
All in all I suggest you study the Firebird language reference, then try to create a functioning insert and only then create a stored procedure around it.
Also note that when creating a stored procedure in Flamerobin, that you must switch statement terminators using set term otherwise Flamerobin can't send the stored procedure correctly, see also the first section in Procedural SQL (PSQL) Statements.

Construction of a class with task property in Ada 2005

I have a class Test_Class in Ada 2005 which has a parent-linked task property called Primary, from type Primary_Task, defined as:
type Test_Class is tagged limited
record
Info : Integer;
Value : Float;
Primary : Primary_Task (Test_Class'Access);
end record;
I need build a one-step constructor for my class in the form
function Construct (T : access Test_Class) return Test_Class_Ptr is
begin
return new Test_Class'(Info => T.Info + 1,
Value => 0.0,
Primary => [WHAT I WANNA KNOW]);
end Construct;
Currently my code is:
-- test_pkg.ads
package Test_Pkg is
type Test_Class;
type Test_Class_Ptr is access all Test_Class;
task type Primary_Task (This_Test : access Test_Class) is
pragma Storage_Size (1000);
end Primary_Task;
type Test_Class is tagged limited
record
Info : Integer;
Value : Float;
Primary : Primary_Task (Test_Class'Access);
end record;
function Construct (T : access Test_Class) return Test_Class_Ptr;
end Test_Pkg;
-- test_pkg.adb
with Text_IO; use Text_IO;
package body Test_Pkg is
[...]
function Construct (T : access Test_Class) return Test_Class_Ptr is
T_Ptr : constant Test_Class_Ptr := new Test_Class;
begin
T_Ptr.Info := T.Info + 1;
T_Ptr.Value := 0.0;
return T_Ptr;
end Construct;
end Test_Pkg;
So, how can I code it? What should I put in Primary => [...] code? Should I change the definition of Primary : Primary_Task (Test_Class'Access); in Test_Class definition?
I got an answer from Randy Brukardt (thank you) on comp.lang.ada:
In Ada 2005 or later, use "<>" to default initialize a component in an
aggregate (which is the only thing you can do with a task).
(...)
function Construct (T : access Test_Class) return Test_Class_Ptr is
begin
return new Test_Class'(Info => T.Info + 1,
Value => 0.0,
Primary => <>);
end Construct;
However, I tried to compile it using GNAT GPL 2011 and got the GNATBUG below
c:\tst>gnatmake -gnat12 test_pkg.adb
gcc -c -gnat12 test_pkg.adb
+===========================GNAT BUG DETECTED==============================+
| GPL 2011 (20110428) (i686-pc-mingw32) GCC error: |
| in create_tmp_var, at gimplify.c:505 |
| Error detected around test_pkg.adb:20:29 |
| Please submit a bug report by email to report#adacore.com. |
| GAP members can alternatively use GNAT Tracker: |
| http://www.adacore.com/ section 'send a report'. |
| See gnatinfo.txt for full info on procedure for submitting bugs. |
| Use a subject line meaningful to you and us to track the bug. |
| Include the entire contents of this bug box in the report. |
| Include the exact gcc or gnatmake command that you entered. |
| Also include sources listed below in gnatchop format |
| (concatenated together with no headers between files). |
| Use plain ASCII or MIME attachment. |
+==========================================================================+
Please include these source files with error report
Note that list may not be accurate in some cases,
so please double check that the problem can still
be reproduced with the set of files listed.
Consider also -gnatd.n switch (see debug.adb).
test_pkg.adb
test_pkg.ads
raised TYPES.UNRECOVERABLE_ERROR : comperr.adb:423
gnatmake: "test_pkg.adb" compilation error
So GNAT GPL users may have to wait for the next release to use this solution.