psycopg2 string composition error - psycopg2

I am doing an upsert.
owner.sq_properties = ['name', 'place', 'email_address', 'preferred_transport', 'note', 'address_line_one', 'address_line_two', 'address_line_three', 'contact_one', 'contact_two', 'contact_three', 'gst_number', 'nickname']
statement:
sq = sql.SQL("insert into master.customer select * from public.customer on conflict (id) do update set({})=({})").format(sql.SQL(',').join(sql.Identifier(n) for n in owner.sq_properties),sql.SQL(',').join(sql.Identifier("excluded."+n) for n in owner.sq_properties))
when I execute:
print(sq.as_string(cursor))
output is :
insert into master.customer select * from public.customer on conflict (id) do update set ("name", "place", "email_address", "preferred_transport", "note", "address_line_one", "address_line_two", "address_line_three", "contact_one", "contact_two", "contact_three", "gst_number", "nickname") = ("excluded.name", "excluded.place", "excluded.email_address", "excluded.preferred_transport", "excluded.note", "excluded.address_line_one", "excluded.address_line_two", "excluded.address_line_three", "excluded.contact_one", "excluded.contact_two", "excluded.contact_three", "excluded.gst_number", "excluded.nickname")
error:
cursor.execute(sq)
psycopg2.ProgrammingError: column "excluded.name" does not exist
LINE 1: ...o", "contact_three", "gst_number", "nickname") = ("excluded..
What am I doing wrong?

Figured it out. excluded. should be an sql identifier.
joined =sql.SQL(',').join(sql.SQL('excluded.')+sql.Identifier(n) for n in owner.sq_properties)
corrected statement:
sql.SQL("insert into master.customer select * from public.customer on conflict (id) do update set ({}) = ({}) returning id").format(sql.SQL(',').join(sql.Identifier(n) for n in owner.sq_properties), joined)

Related

adding limit to my sequelize query is throwing an error

this works properly
let data=await db.company.findAll({
include:{model:db.user,as:'users'},
where:{'$users.id$':7}
});
but as soon as i add limit below, it throws an error
let data=await db.company.findAll({
limit:10,
include:{model:db.user,as:'users'},
where:{'$users.id$':7}
});
here's the error when i execute the one with limit.
{
name: "SequelizeDatabaseError",
parent: {
message: "The multi-part identifier "users.id" could not be bound.",
code: "EREQUEST",
number: 4104,
state: 1,
class: 16,
serverName: "LAPTOP-5ED24571",
procName: "",
lineNumber: 1,
sql: "SELECT [company].*, [users].[id] AS [users.id], [users].[username] AS [users.username], [users].[name] AS [users.name], [users].[address] AS [users.address], [users].[active] AS [users.active], [users].[email] AS [users.email], [users].[phone] AS [users.phone], [users].[job_role] AS [users.job_role], [users].[time_zone] AS [users.time_zone], [users].[country] AS [users.country], [users].[currency] AS [users.currency], [users].[induction] AS [users.induction], [users].[createdAt] AS [users.createdAt], [users].[updatedAt] AS [users.updatedAt], [users].[userRoleId] AS [users.userRoleId], [users->user_company_mm].[id] AS [users.user_company_mm.id], [users->user_company_mm].[userId] AS [users.user_company_mm.userId], [users->user_company_mm].[companyId] AS [users.user_company_mm.companyId], [users->user_company_mm].[createdAt] AS [users.user_company_mm.createdAt], [users->user_company_mm].[updatedAt] AS [users.user_company_mm.updatedAt] FROM (SELECT [company].[id], [company].[name], [company].[address], [company].[city], [company].[country], [company].[state_region], [company].[logo], [company].[numberOfLocations], [company].[numberOfEmployees], [company].[audience_builder], [company].[creator_user_id], [company].[tags], [company].[createdAt], [company].[updatedAt] FROM [company] AS [company] WHERE [users].[id] = 7 ORDER BY [company].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY) AS [company] LEFT OUTER JOIN ( [user_company_mm] AS [users->user_company_mm] INNER JOIN [user] AS [users] ON [users].[id] = [users->user_company_mm].[userId]) ON [company].[id] = [users->user_company_mm].[companyId];"
}
Any idea why this is happening? thank you
I'm not necessarily familiar with sequelize.js. But looking at your query statement, you have a WHERE condition in your sub query limiting it to [Users].[Id] = 7. But this doesn't exist in this part of your query context.
...
FROM
(SELECT [company].[id],
[company].[name],
[company].[address],
[company].[city],
[company].[country],
[company].[state_region],
[company].[logo],
[company].[numberOfLocations],
[company].[numberOfEmployees],
[company].[audience_builder],
[company].[creator_user_id],
[company].[tags],
[company].[createdAt],
[company].[updatedAt] FROM [company] AS [company]
/* HERE --> */ WHERE [users].[id] = 7 ORDER BY [company].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
)
AS [company] LEFT OUTER JOIN
( [user_company_mm] AS [users->user_company_mm] INNER JOIN [user]
AS [users] ON [users].[id] = [users->user_company_mm].[userId]) ON [company].[id] = [users->user_company_mm].[companyId]
But why the query is structured as so, I can't tell. That would be something for how you've configured it/how sequalized works.

Python sqlite3: Loop through rows from table_a stops when inserting into table_b

Trying to to loop through rows from table_a, pass them into a function, and insert the outputs into table_b. I can manage to loop through rows from table_a, but as soon as i try to insert to table_b something, my script just stops.
with sqlite3.connect(db_path) as db:
cursor = db.cursor()
cursor.execute("""SELECT * FROM cars""")
for row in cursor:
car_price = get_car_price(row[0])
cursor.execute("""INSERT INTO car_prices (price, car_id) VALUES (?,?);""",(car_price, row[0]))
output :
[Finished in 1.0s]
It is weird because the below works, but as soon as i try executing to car_prices table (as in the previous code), the code just ends at first iteration.
with sqlite3.connect(db_path) as db:
cursor = db.cursor()
cursor.execute("""SELECT * FROM cars""")
for row in cursor:
print(row)
output:
(1, "car_1")
(2, "car_2")
...
(n, "car_n")
[Finished in 0.7s]
As asked, here is the .schema:
sqlite> .schema
CREATE TABLE IF NOT EXISTS "cars" (
"id" integer NOT NULL,
"name" text NOT NULL,
"website_url" text NOT NULL,
PRIMARY KEY("id")
);
CREATE TABLE IF NOT EXISTS "car_prices" (
"price_id" integer,
"price" NUMERIC NOT NULL,
"car_id" integer NOT NULL,
PRIMARY KEY("price_id"),
FOREIGN KEY("car_id") REFERENCES "cars"("id")
The problem is that you're reusing your cursor, throwing away the results of your first query.
Here's a minimal runnable example (you may have gotten a faster answer if you had included this in your question, since it would've taken less effort for people to get involved):
#!/usr/bin/env python3
import sqlite3
import sys
def get_car_price(carid):
return carid * 11 + 101
with sqlite3.connect(':memory:') as db:
db.execute('''
CREATE TABLE IF NOT EXISTS "cars" (
"id" integer NOT NULL,
"name" text NOT NULL,
"website_url" text NOT NULL,
PRIMARY KEY("id")
)
''')
db.execute('''
CREATE TABLE IF NOT EXISTS "car_prices" (
"price_id" integer,
"price" NUMERIC NOT NULL,
"car_id" integer NOT NULL,
PRIMARY KEY("price_id"),
FOREIGN KEY("car_id") REFERENCES "cars"("id")
)
''')
for ix, name in enumerate(('Lolvo', 'Yotoya', 'Edison')):
url = 'http://example.com/' + name.lower()
db.execute('INSERT INTO cars VALUES(?,?,?)', (ix, name, url))
cursor = db.cursor()
if 'sep' in sys.argv:
insertcursor = db.cursor()
else:
insertcursor = cursor
cursor.execute("""SELECT * FROM cars""")
for row in cursor:
car_price = get_car_price(row[0])
print(row, car_price)
insertcursor.execute("""INSERT INTO car_prices (price, car_id) VALUES (?,?);""",(car_price, row[0]))
cursor.execute('''SELECT * FROM car_prices''')
for row in cursor:
print('car_prices:', row)
Running with no args, it'll use the same cursor, reproducing your problem:
python-sqlite-stops$ ./stuff.py
(0, 'Lolvo', 'http://example.com/lolvo') 101
car_prices: (1, 101, 0)
Give it 'sep' as an arg, and it'll use a separate cursor for insertion, fixing your problem:
python-sqlite-stops$ ./stuff.py sep
(0, 'Lolvo', 'http://example.com/lolvo') 101
(1, 'Yotoya', 'http://example.com/yotoya') 112
(2, 'Edison', 'http://example.com/edison') 123
car_prices: (1, 101, 0)
car_prices: (2, 112, 1)
car_prices: (3, 123, 2)
You could make it even simpler by just using db.execute() for the inserts; no cursor() call necessary.

Compare uuid and string on TypeORM query builder

I want to join 2 tables where user.id = photo.userId but the problem here is that the userId on photo table is varchar and that can't change. So I did a queryBuilder to join and the problem is here:
....
.where(user.id = photo.userId)
....
this query throw an error: operator does not exists: uuid = character varying
Is there any way to make this work?
Note: My project is a NestJS API, using TypeORM and Postgresql.
EDIT
I already have the Photo result and use it on a subQuery:
query = query
.where(qb => {
const subQuery = qb.subQuery()
.select('user.id')
.from(User, 'user')
.where('user.id = photo.userId)
.getQuery();
return 'EXISTS' + subQuery;
});
https://www.postgresqltutorial.com/postgresql-cast/
where (user.id::VARCHAR = photo.userId)
Thank you for the help, finally the best solution I found was to create a postgres function as indicated here and then call it in the code like this:
query = query
.where(qb => {
const subQuery = qb.subQuery()
.select('user.id')
.from(User, 'user')
.where('user.id = uuid_or_null(photo.userId)) // here
.getQuery();
return 'EXISTS' + subQuery;
});
First off the conversion of 'I' to "i" (upper to lower) in userId is exactly what would be expected, as identifiers are all lower cased unless double quoted. Avoid that if possible as when used you must double quote every time the identifier is used.
Secondly the type uuid has some strange and unexpected formatting rules. You can compare a string::uuid to a uuid as expected, but uuid::text may not compare to a srting. As uuid::text will format as hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh (where h is a hexdigit). The dashes are often removed if storing as a a string. So reverse the typical order; cast the string as uuid. See the following example:
create table id_uuid (id uuid, col1 text);
create table id_str (id text, col1 text
insert into id_uuid(id, col1) values(gen_random_uuid(),'Id defined as uuid');
insert into id_str (id, col1)
select replace(id::text,'-',''),'Id defined as string'
from id_uuid;
select * from id_uuid;
select * from id_str;
select *
from id_uuid u
join id_str s
on (u.id::text = s.id);
select *
from id_uuid u
join id_str s
on (u.id = s.id::uuid);

Not able to parameterize LIMIT and OFFSET in sqlite3

Why following code is giving syntax error "sqlite3.OperationalError: near "?": syntax error"
import sqlite3
connection = sqlite3.connect('data.db')
cursor = connection.cursor()
table = "device_store"
uuid = "bbebe39e-fe2e-4817-b022-a3ef13bd6283"
page = 1
POSTS_PER_PAGE = 10
query = "SELECT * FROM ? WHERE uuid=? LIMIT ? OFFSET ?"
result = cursor.execute(query, (table, uuid, POSTS_PER_PAGE, 0))
rows = result.fetchall()
connection.close()
print("==>> Printing rows <<==")
print(rows)
The error is caused by the placeholder in FROM ?, not the others. Table names can't be passed as parameters, they have to be hardcoded in the statement.

Query Parameter Format for SELECT ... IN with Cassandra using Node.js Driver

I have a Cassandra SELECT query with an IN parameter that I want to run via the Node driver, but can't figure out the syntax.
On the cqlsh console, I can run this select and get a correct result:
SELECT * FROM sourcedata WHERE company_id = 4 AND item_id in (ac943b6f-0143-0e1f-5282-2d39209f3a7a,bff421a0-c465-0434-8806-f128612b6850,877ddb6d-a164-1152-da77-1ec4c4468258);
However, trying to run this query using an array of IDs using the Cassandra Node driver, I get various errors depending on the format. Here's what I've tried:
client.execute("SELECT * FROM sourcedata WHERE company_id = ? AND item_id in (?)", [id, item_ids], function(err, rs) { ...
The error is:
ResponseError: Invalid list literal for item_id of type uuid
With this:
client.execute("SELECT * FROM sourcedata WHERE company_id = ? AND item_id in (?)", [id, item_ids], function(err, rs) { ...
The error is:
ResponseError: line 1:72 no viable alternative at input '[' (...WHERE company_id = 4 AND [item_id] in...)
item_ids is an array of string objects, and they were acquired via a select on another Cassandra table.
This is a working app, and other queries that don't use "SELECT .. IN" work fine.
I can also do make it work the "ugly" way, but would prefer not to:
client.execute("SELECT * FROM sourcedata WHERE company_id = ? AND item_id in (" + item_ids.toString() + ")", [id,], function(err, rs) { ...
You should use IN ? without parenthesis, to provide a list:
const query = 'SELECT * FROM sourcedata WHERE company_id = ? AND item_id in ?';
client.execute(query, [ id, item_ids ], { prepare: true }, callback);

Resources