@@ -444,6 +444,19 @@ def get_ids():
444444
445445 self ._ids = get_ids ()
446446
447+ def _values_query (self , query ):
448+ cr = self ._model .env .cr
449+ cr .execute (format_query (cr , "WITH query AS ({}) SELECT count(*) FROM query" , SQLStr (query )))
450+ size = cr .fetchone ()[0 ]
451+
452+ def get_values ():
453+ with named_cursor (cr , itersize = self ._chunk_size ) as ncr :
454+ ncr .execute (SQLStr (query ))
455+ for row in ncr .iterdict ():
456+ yield row
457+
458+ return size , get_values ()
459+
447460 def _browse (self , ids ):
448461 next (self ._end (), None )
449462 args = self ._cr_uid + (list (ids ),)
@@ -494,35 +507,46 @@ def caller(*args, **kwargs):
494507 self ._it = None
495508 return caller
496509
497- def create (self , values , ** kw ):
510+ def create (self , values = None , query = None , ** kw ):
498511 """
499512 Create records.
500513
501514 An alternative to the default `create` method of the ORM that is safe to use to
502515 create millions of records.
503516
504- :param list(dict) values: list of values of the records to create
517+ :param iterable(dict) values: iterable of values of the records to create
518+ :param int size: the no. of elements produced by values, required if values is a generator
519+ :param str query: alternative to values, SQL query that can produce them
505520 :param bool multi: whether to use the multi version of `create`, by default is
506521 `True` from Odoo 12 and above
507522 """
508523 multi = kw .pop ("multi" , version_gte ("saas~11.5" ))
524+ size = kw .pop ("size" , None )
509525 if kw :
510526 raise TypeError ("Unknown arguments: %s" % ", " .join (kw ))
511527
512- if not values :
513- raise ValueError ("`create` cannot be called with an empty `values` argument " )
528+ if not bool ( values ) ^ bool ( query ) :
529+ raise ValueError ("`create` needs to be called using exactly one of `values` or `query` arguments " )
514530
515531 if self ._size :
516532 raise ValueError ("`create` can only called on empty `browse_record` objects." )
517533
518- ids = []
519- size = len (values )
534+ if query :
535+ size , values = self ._values_query (query )
536+
537+ if size is None :
538+ try :
539+ size = len (values )
540+ except TypeError :
541+ raise ValueError ("When passing a generator of values, the size kwarg is mandatory" )
542+
520543 it = chunks (values , self ._chunk_size , fmt = list )
521544 if self ._logger :
522545 sz = (size + self ._chunk_size - 1 ) // self ._chunk_size
523546 qualifier = "env[%r].create([:%d])" % (self ._model ._name , self ._chunk_size )
524547 it = log_progress (it , self ._logger , qualifier = qualifier , size = sz )
525548
549+ ids = []
526550 self ._patch = no_selection_cache_validation ()
527551 for sub_values in it :
528552 self ._patch .start ()
0 commit comments