1

I understand that psycopg2 queries should not be formed by text replacement like f-strings, %s forms, etc. for fear of injection attacks. The docs make that clear. However, what's not clear to me is if the cursor.mogrify method is subject to the same concerns.

The docs say,

-- Method: mogrify (operation[, parameters])

Return a query string after arguments binding. The string returned is exactly the one that would be sent to the database running the execute() method or similar.

https://www.psycopg.org/docs/cursor.html#cursor.mogrify

That makes it sound like execute basically runs mogrify behind the scenes. The red box talking about guns is pretty scary, though. I don't know what to trust.

Basically, if this is bad,

# don't do this even at gunpoint

my_id = 1234
my_values = ['a', 'b', 'c']


my_query = ''
for val in values:
    insert_statement = f"""INSERT INTO my_table VALUES ({my_id}, {val});"""
    my_query = '\n'.join([my_query, insert_statement])


with self.connection, self.connection.cursor() as cursor:
    cursor.execute(my_query)

is this a good substitute?

# is this a footgun?

my_id = 1234
my_values = ['a', 'b', 'c']


with self.connection, self.connection.cursor() as cursor:
    for val in values:
        my_query = cursor.mogrify("INSERT INTO my_table VALUES (%s, %s);", (my_id, val))
        cursor.execute(my_query)
Lorem Ipsum
  • 4,020
  • 4
  • 41
  • 67
  • I would not get attached to `mogrify` as it does not exist in the next version `psycopg3` . Stick to the best practices methods of [Parameters](https://www.psycopg.org/docs/usage.html#passing-parameters-to-sql-queries) and [Dynamic SQL](https://www.psycopg.org/docs/sql.html). Read this last link as it goes into the reasons why. – Adrian Klaver Feb 02 '22 at 19:33

1 Answers1

0

That description is a bit misleading.

The wire protocol of PostgreSQL fully supports parametrization. A parametrized query will be sent as a "multipart" packet containing (among others) the parametrized query + the values to 'substitute' into the query.

Execution of the query is done by PostgreSQL engine, where the (parametrized) query will be tokenized, and tokens indicating substution will be substituted with actual desired values.

So, although I have never read the actual source code for psycopg, I'm quite certain that behind the scenes, cursor.execute() will leverage this native support of parametrization, and not doing a .mogrify() first.

pepoluan
  • 6,132
  • 4
  • 46
  • 76
  • 1
    Actually `psycopg2` does do the binding client side as the `mogrify` shows. The recently released `psycopg3` does the binding server side. For the lead developer's explanation see [Psycopg3 adaptation](https://www.psycopg.org/articles/2020/11/24/psycopg3-adaptation/). That is why, per my comment, `mogrify` does not exist in `psycopg3`. – Adrian Klaver Feb 03 '22 at 16:04
  • @AdrianKlaver ahh, thank you for the explanation! – pepoluan Feb 05 '22 at 04:30