Re: Inserting default values into execute_values

Поиск
Список
Период
Сортировка
От Adrian Klaver
Тема Re: Inserting default values into execute_values
Дата
Msg-id fa748f68-6c8f-382d-8e17-68e0c3f5e537@aklaver.com
обсуждение исходный текст
Ответ на Re: Inserting default values into execute_values  (Adrian Klaver <adrian.klaver@aklaver.com>)
Список 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.klaver@aklaver.com



В списке psycopg по дате отправления:

Предыдущее
От: Adrian Klaver
Дата:
Сообщение: Re: Inserting default values into execute_values
Следующее
От: Daniele Varrazzo
Дата:
Сообщение: Psycopg 2.8.5 released