From: | Adrian Klaver <adrian(dot)klaver(at)aklaver(dot)com> |
---|---|
To: | Stephen Lagree <stephen(dot)lagree(at)gmail(dot)com> |
Cc: | Daniele Varrazzo <daniele(dot)varrazzo(at)gmail(dot)com>, psycopg(at)postgresql(dot)org |
Subject: | Re: Inserting default values into execute_values |
Date: | 2020-04-01 21:15:49 |
Message-ID: | fa748f68-6c8f-382d-8e17-68e0c3f5e537@aklaver.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | psycopg |
On 4/1/20 2:04 PM, Adrian Klaver wrote:
> On 4/1/20 1:31 PM, Stephen Lagree wrote:
>> Thanks Daniele and Adrian, your answers were really helpful!
>>
>> Daniele, you are right, it is a waste sending long strings when I am
>> just trying to generate entries in the sequence.
>> I do want to do it in one shot so your generate_series suggestion
>> should be great
>> insert into testins (id) select nextval('testins_id_seq') from
>> generate_series(1, 10);
>>
>> However, I was playing around with the sql.Default and Adrian's
>> Default class and couldn't get them to work with execute_values. I
>> know in my case it might not make sense to use a Default literal if
>> that is all that is being added, but it might make sense for a query
>> that sometimes is used for inserting DEFAULT and sometimes to insert a
>> value.
>>
>> query2 = "INSERT INTO MYTABLE (id) VALUES %s RETURNING id;"
>> args_list = [sql.DEFAULT, sql.DEFAULT]
>> execute_values(cursor, query2, args_list,
>> template=None, page_size=100, fetch=True)
>>
>> There is a TypeError in execute_values for both Adrian's Default and
>> sql.Default:
>>
>> for page in _paginate(argslist, page_size=page_size):
>> if template is None:
>> > template = b'(' + b','.join([b'%s'] *
>> len(page[0])) + b')'
>> E TypeError: object of type 'SQL' has no len()
>>
>> ../../.con
>> da/envs/stbase/lib/python3.7/site-packages/psycopg2/extras.py:1275:
>> TypeError
>>
>> I added a len and slicing function to Adrian's default class and tried
>> it, but it then had an error with the mogrify line in execute values.
>> I tried a few variations of templates with and without parentheses and
>> that didn't work either.
>
> The DEFAULT and sql.SQL("DEFAULT") both return objects that do not play
> well with the template as you found out.
Not concentrating, the above is not correct for the DEFAULT case:
class Default(object):
"""Set up DEFAULT value for a field.
When doing INSERT or UPDATE in Postgres one can use DEFAULT/default
as the value to have the server use the default set on the field.
The below allows
for doing that.
"""
def __conform__(self, proto):
if proto is psycopg2.extensions.ISQLQuote:
return self
def getquoted(self):
return 'DEFAULT'
DEFAULT = Default()
args_list = [(DEFAULT, DEFAULT)]
execute_values(cur, query2, args_list, template=None, page_size=100,
fetch=True)
[(6,)]
select * from t2;
id | name
----+-------
1 | test
2 | test2
3 | name
4 | name
5 | name
6 | name
What we both forgot is that args_list needs to a sequence of sequences.
>
> The simplest way I found is to do:
>
> query2 = "INSERT INTO t2 (id, name) VALUES %s RETURNING id;"
>
> execute_values(cur, query2, args_list, template="(DEFAULT, DEFAULT)",
> page_size=100, fetch=True)
>
> [(3,), (4,)]
>
> test=# alter table t2 alter COLUMN name set default 'name';
> ALTER TABLE
> test=# select * from t2;
> id | name
> ----+-------
> 1 | test
> 2 | test2
> (2 rows)
>
> test=# select * from t2;
> id | name
> ----+-------
> 1 | test
> 2 | test2
> 3 | name
> 4 | name
> (4 rows)
>
>
>
>
>
>>
--
Adrian Klaver
adrian(dot)klaver(at)aklaver(dot)com
From | Date | Subject | |
---|---|---|---|
Next Message | Daniele Varrazzo | 2020-04-06 07:54:11 | Psycopg 2.8.5 released |
Previous Message | Adrian Klaver | 2020-04-01 21:04:37 | Re: Inserting default values into execute_values |