I am using golang SQLC to generate CRUD operation go code from sql.
My select query is like bellow
-- name: SearchProducts :many
SELECT * FROM product
WHERE ( $1::varchar(100) IS NULL OR name LIKE '%$1%' )
AND ( $2::varchar(1000) IS NULL OR description LIKE '%$2%' );
SQLC generating code like bellow
type SearchProductsParams struct {
Column1 string `json:"column_1"`
Column2 string `json:"column_2"`
}
func (q *Queries) SearchProducts(ctx context.Context, arg SearchProductsParams) ([]Product, error) {
rows, err := q.db.QueryContext(ctx, searchProducts, arg.Column1, arg.Column2)
if err != nil {
return nil, err
}
....
Is there any way to configure sqlc so that it will use name & description instead of Column1 & Column2 in SearchProductsParams struct
You can use named parameters
-- name: SearchProducts :many
SELECT * FROM product
WHERE ( sqlc.arg(email)::varchar(100) IS NULL OR name LIKE '%sqlc.arg(email)%' )
AND ( sqlc.arg(description)::varchar(1000) IS NULL OR description LIKE '%sqlc.arg(description)%' );
You can find the documentation here
When doing selects with conditional filters what it works for me was something like this:
SELECT * FROM product
WHERE
email like CASE
WHEN #filter_email::bool
THEN #email::VARCHAR
ELSE '%'
END
AND
description = CASE
WHEN #filter_description::bool
THEN #description::VARCHAR
ELSE description
END
You have to use the flag filter_email or filter_description flag and the value when you actually want to filter.
Related
I'm using the postgres crate which makes a query with postgres::Connection. I query a table based on a string value in an ilike '%search_string%' expression:
extern crate postgres;
use std::error::Error;
//DB Create queries
/*
CREATE TABLE TestTable (
Id SERIAL primary key,
_Text varchar(50000) NOT NULL
);
insert into TestTable (_Text) values ('test1');
insert into TestTable (_Text) values ('test1');
*/
fn main() -> Result<(), Box<dyn Error>> {
let conn = postgres::Connection::connect(
"postgres://postgres:postgres#localhost:5432/notes_server",
postgres::TlsMode::None,
)?;
let text = "test";
// //Does not work
// let query = &conn.query(
// "
// select * from TestTable where _text ilike '%$1%'
// ",
// &[&text],
// )?;
//Works fine
let query = &conn.query(
"
select * from TestTable where Id = $1
",
&[&1],
)?;
println!("Rows returned: {}", query.iter().count());
Ok(())
}
If I uncomment the //Does not work part of the code, I will get the following error:
thread 'main' panicked at 'expected 0 parameters but got 1'
It appears it doesn't recognize the $1 parameter that is contained in the ilike expression. I've tried escaping the single quotes and that doesn't change it.
The only dependencies are:
postgres = { version = "0.15.2", features = ["with-chrono"] }
To my surprise, here was the fix:
let text = "%test%";
let query = &conn.query(
"
select * from TestTable where _text like $1
",&[&text],
)?;
Apparently the postgres function knows to add single quotes around strings in this scenario.
I found out about this from here: https://www.reddit.com/r/rust/comments/8ltad7/horrible_quote_escaping_conundrum_any_ideas_on/
An example should do the magic.
At the top, I am using pg. So, import it. My code looks like
const title = req.params.title;
const posts = await db.query("SELECT * FROM postsTable INNER JOIN usersTable ON postsTable.author = usersTable.username WHERE title ILIKE $1 ORDER BY postsTable.created_on DESC LIMIT 5;", [`%${title}℅`])
Current JSON
{
"layout":"dynamicReport1",
"templateType":"DYNAMIC_REPORTS",
"containers":{
"fieldsContainer":[
{
"fieldName":"role_id",
"displayName":"Role",
"fieldType":"text",
"isHidden":true,
"index":0,
"queryForParam":"select name as \"role_id\" from um_role_master where id=#role_id#",
"queryIdForParam":476
},
{
"fieldName":"course_id",
"displayName":"Course",
"fieldType":"text",
"isHidden":true,
"index":1,
"queryForParam":"select course_name as course_id from tr_course_master where course_id=#course_id#",
"queryIdForParam":477
},
{
"fieldName":"location_id",
"displayName":"Location",
"fieldType":"text",
"isHidden":true,
"index":2,
"queryForParam":"select name as location_id from location_master where id = #location_id#",
"queryIdForParam":478
}
]
}
}
Hierarchy is like
containers -> fieldContainer -> object
Above is my json config and i want to add queryUUIDForParam: random UUID to each Object through query.
How i can insert ?
I tried to get updated config by this query but it throws error:
select config::jsonb || ('{"queryUUIDForParam":' || cast(uuid as text) || '}')::jsonb
error :
SQL Error [22P02]: ERROR: invalid input syntax for type json Detail:
Token "5574ff23" is invalid. Where: JSON data, line 1:
{"queryUUIDForParam":5574ff23...
My expected output is to add "queryUUIDForParam" element in Object Like.
I want an element with UUID value to be appended.This UUId value is generated using random function.
{
"layout":"dynamicReport1",
"templateType":"DYNAMIC_REPORTS",
"containers":{
"fieldsContainer":[
{
"fieldName":"role_id",
"displayName":"Role",
"fieldType":"text",
"isHidden":true,
"index":0,
"queryForParam":"select name as \"role_id\" from um_role_master where id=#role_id#",
"queryIdForParam":476,
"queryUUIDForParam":"1ea99f17-6965-4a0d-8d31-22b8777b9c62"
},
{
"fieldName":"course_id",
"displayName":"Course",
"fieldType":"text",
"isHidden":true,
"index":1,
"queryForParam":"select course_name as course_id from tr_course_master where course_id=#course_id#",
"queryIdForParam":477,
"queryUUIDForParam":"3ea99f17-6965-4a0d-8d31-22b8777b9c62"
},
{
"fieldName":"location_id",
"displayName":"Location",
"fieldType":"text",
"isHidden":true,
"index":2,
"queryForParam":"select name as location_id from location_master where id = #location_id#",
"queryIdForParam":478,
"queryUUIDForParam":"9ea99f17-6965-4a0d-8d31-22b8777b9c62"
}
]
}
}
Thanks in advance :)
Try This:
with cte as (select jsonb_array_elements(jsonb_extract_path(config, 'containers','fieldsContainer')::jsonb) "objects" from example),
final_array as (
select jsonb_build_array(d) "array_data" from (select array_agg(objects::jsonb || jsonb_build_object('queryUUIDForParam',(select uuid_generate_v4()))) "fieldsContainer" from cte )d)
select jsonb_set(
config::jsonb,
'{containers,fieldsContainer}', (f.array_data),false)
from example, final_array f;
in case you want different uuid for each object
with cte as (select uuid_generate_v4() "uuid_",jsonb_array_elements(jsonb_extract_path(config, 'containers','fieldsContainer')::jsonb) "objects" from example),
final_array as (
select jsonb_build_array(d) "array_data" from (select array_agg(objects::jsonb || jsonb_build_object('queryUUIDForParam',uuid_)) "fieldsContainer" from cte )d)
select jsonb_set(
config::jsonb,
'{containers,fieldsContainer}', (f.array_data),false)
from example, final_array f;
Note: I have used Inbuilt function of Postgres to generate the UUID. Please run following statement before using it
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
DEMO on DB-Fiddle
I have the following gorm.Model and I want to Query my Postgres database to return Confessions that have a specific category in their .Categories attribute, but I have no idea how to Query inside a pq.StringArray. Is there a work-around?
type Confession struct {
gorm.Model
User string `json:"User"`
Title string `json:"Title"`
Body string `json:"Body"`
Mood string `json:"Mood"`
Categories pq.StringArray `gorm:"type:varchar(64)[]" json:"Categories"`
}
And here is how I tried to query, but using the LIKE operator throws an error.
if categories != nil {
for _, cat := range categories {
tx = tx.Where("Categories LIKE ?", "%"+cat+"%")
}
}
Use <# for array contains. You can query using Query function of *sql.DB and get *sql.DB using tx.DB() in gorm
sel := "SELECT * FROM confessions WHERE $1 <# categories"
categories := []string{"cat1", "cat2"}
rows, err := tx.DB().Query(sel, pq.Array(categories))
Or try Gorm Raw SQL , but I won't sure it will work properly or not for array functions.
References:
PostgreSQL Array function here
ProtgreSQL Array use in golang here
The easiest solution to my problem was to use the .Where command as such
tx = tx.Where("categories && ?", pq.Array(categories))
This will return a gorm.DB so I can continue to chain actions. The && operator is to check for OVERLAPPING elements.
I have a function that generates a prepared statement for batch insert into postgres where I am trying to insert the string into type jsonb in postgres.
My struct looks like:
type struct1 struct {
id int
comment string
extra string
}
and my table schema looks like:
create table deal (
id bigserial,
comment varchar(75),
extra jsonb
)
and I want to dump []struct1 to Postgres DB "deal".
My function which generates the prepared statement looks like this:
func BulkInsert(str []struct1, ctx context.Context) string {
log.Debug("inserting records to DB")
query := fmt.Sprintf(`insert into deal (%s) values `, strings.Join(dbFields, ","))
var numFields = len(dbFields)
var values []interface{}
for i, database := range str {
values = append(values, database.Comment,`'`+database.Extra+`'`)
n := i * numFields
query += `(`
for j := 0; j < numFields; j++ {
query += `$` + strconv.Itoa(n+j+1) + `,`
}
query = query[:len(query)-1] + `),`
}
query = query[:len(query)-1]
return query
Expected results should be: I should be able to insert string to json or you can say cast string to json and dump it.
The actual result is :
could not save batch: pq: invalid input syntax for type json"
Function of json_build_array('exp1'::Text, 'exp2'::Text) may help you.
return json object: {'exp1', 'exp2'}
And extract the values just use operator ->><index> like ->>1 to get 'exp2'.
If you just want to insert into database, function of to_json('any element') should also works, which can convert any element to a json object.
And you can get more funtions about json(jsonb) in postgres document.
I'm trying to execute SELECT statement, where parameters might have null values:
SQL(
"""
SELECT id FROM devices WHERE
name = {name}
""")
.on("name" -> device.name)()
.collectFirst {
...
}.getOrElse {
...
}
device.name can return null. With db.default.logStatements=true I see that generated SQL looks like this: SELECT id FROM devices WHERE name = NULL.
name = NULL is not quite valid for Postgre SQL, but I've enabled it using transform_null_equals. Now when I execute SQL from log using pgAdmin, it works perfectly fine. However, ANORM does not find anything.
Following code does return result:
SQL(
"""
SELECT id FROM devices WHERE
name = NULL
""")
.on("name" -> device.name)()
.collectFirst {
...
}.getOrElse {
...
}
What's wrong with it?!