1

I am using psycopg2 to create a table partition and insert some rows into this newly created partition. The table is RANGE partitioned on a date type column.

Psycopg2 code:

conn = connect_db()
cursor = conn.cursor()
sysdate = datetime.now().date()
sysdate_str = sysdate.strftime('%Y%m%d')
schema_name = "schema_name"
table_name = "transaction_log"

# Add partition if not exists for current day
sql_add_partition = sql.SQL("""
    CREATE TABLE IF NOT EXISTS {table_partition}
    PARTITION of {table}
    FOR VALUES FROM (%(sysdate)s) TO (maxvalue);
""").format(table = sql.Identifier(schema_name, table_name), table_partition = sql.Identifier(schema_name, f'{table_name}_{sysdate_str}'))
print(cursor.mogrify(sql_add_partition, {'sysdate': dt.date(2015,6,30)}))
cursor.execute(sql_add_partition, {'sysdate': sysdate})

Formatted output of cursor.mogrify():

CREATE TABLE IF NOT EXISTS "schema_name"."transaction_log_20211001"
PARTITION of "schema_name"."transaction_log"
FOR VALUES FROM ('2021-10-01'::date) TO (maxvalue);

Error received:

ERROR:  syntax error at or near "::"
LINE 3: for values FROM ('2021-10-01'::date) TO (maxvalue);

Interestingly enough, psycopg2 appears to be attempting to cast the string '2021-10-01' to a date object with the "::date" syntax, and according to the postgreSQL documentation, this appears to be valid (although there are no explicit examples given in the docs), however executing the statement with both pyscopg2 and in a postgreSQL query editor yields this syntax error. However, executing the following statement in a postgreSQL SQL editor is successful:

CREATE TABLE IF NOT EXISTS "schema_name"."transaction_log_20211001"
PARTITION of "schema_name"."transaction_log"
FOR VALUES FROM ('2021-10-01') TO (maxvalue);

Any ideas on how to get psycopg2 to format the query correctly?

4
  • Try converting it to a string in Python and interpolating that. Commented Oct 1, 2021 at 11:24
  • @LaurenzAlbe That should work. Although I'm curious to know why both the psycopg2 docs and the postgresql docs indicate the syntax is valid despite this syntax error. I'll leave the question open for now. Commented Oct 1, 2021 at 12:15
  • The syntax is not valid. You need to supply a constant, not an expression like a type cast. Commented Oct 1, 2021 at 12:17
  • The reason is from Create Table: 'Each of the values specified in the partition_bound_spec is a literal, NULL, MINVALUE, or MAXVALUE. Each literal value must be either a numeric constant that is coercible to the corresponding partition key column's type, or a string literal that is valid input for that type.' Added this as update to my answer. Commented Oct 1, 2021 at 18:08

1 Answer 1

2

To follow up on @LaurenzAlbe comment:


sql_add_partition = sql.SQL("""
    CREATE TABLE IF NOT EXISTS {table_partition}
    PARTITION of {table}
    FOR VALUES FROM (%(sysdate)s) TO (maxvalue);
""").format(table = sql.Identifier(schema_name, table_name), table_partition = sql.Identifier(schema_name, f'{table_name}_{sysdate_str}'))
print(cursor.mogrify(sql_add_partition, {'sysdate': '2021-10-01'}))

#OR

sql_add_partition = sql.SQL("""
    CREATE TABLE IF NOT EXISTS {table_partition}
    PARTITION of {table}
    FOR VALUES FROM ({sysdate}) TO (maxvalue);
""").format(table = sql.Identifier(schema_name, table_name), 
table_partition = sql.Identifier(schema_name, f'{table_name}_{sysdate_str}'),
sysdate=sql.Literal('2021-10-01'))
print(cursor.mogrify(sql_add_partition))

#Formatted as

CREATE TABLE IF NOT EXISTS "schema_name"."transaction_log_20211001"
    PARTITION of "schema_name"."transaction_log"
    FOR VALUES FROM ('2021-10-01') TO (maxvalue);

Pass the date in as a literal value instead of a date object. psycopg2 does automatic adaptation of date(time) objects to Postgres date/timestamp types(Datetime adaptation) which is what is biting you.

UPDATE

Per my comment, the reason why it needs to be a literal is explained here Create Table:

Each of the values specified in the partition_bound_spec is a literal, NULL, MINVALUE, or MAXVALUE. Each literal value must be either a numeric constant that is coercible to the corresponding partition key column's type, or a string literal that is valid input for that type.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.