-
Notifications
You must be signed in to change notification settings - Fork 68
[ADD] util/update_table_from_dict #297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[ADD] util/update_table_from_dict #297
Conversation
Usage example: https://github.com/odoo/upgrade/pull/8079 |
upgradeci retry with always only base |
1e5c9a3
to
31ecb56
Compare
3dbdbe7
to
e3ab180
Compare
A recurrent challenge in writing upgrade scripts is that of updating values in a table based on some form of already available mapping from the id (or another identifier) to the new value, this is often addressed with an iterative solution in the form: ```python for key, value in mapping.items(): cr.execute( """ UPDATE table SET col = %s WHERE key_col = %s """, [value, key], ) ``` or in a more efficient (only issuing a single query) but hacky way: ```python cr.execute( """ UPDATE table SET col = (%s::jsonb)->>(key_col::text) WHERE key_col = ANY(%s) """, [json.dumps(mapping), list(mapping)], ) ``` With the former being ineffective for big mappings and the latter often requiring some comments at review time to get it right. This commit introduces a util meant to make it easier to efficiently perform such updates.
e3ab180
to
876a5d9
Compare
@@ -1621,3 +1622,89 @@ def create_id_sequence(cr, table, set_as_default=True): | |||
table=table_sql, | |||
) | |||
) | |||
|
|||
|
|||
def update_table_from_dict(cr, table, mapping, key_col="id", bucket_size=DEFAULT_BUCKET_SIZE): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the interface should be
def update_table_from_dict(cr, table, mapping, key_col="id", bucket_size=DEFAULT_BUCKET_SIZE): | |
def update_table_from_dict(cr, table, columns, mapping, key_col="id", bucket_size=DEFAULT_BUCKET_SIZE): |
From experience, when we use a dict to update, sometimes the dict becomes too big. If we make the keys repeated each time we may unintentionally make this harder. We can instead take a mapping {id: [val1, val2,...]}
and a spec of columns to update [col1, col2, ...]
, or {id: val}
with just col1
. This has the advantage that for the most common case where we update a single column the values could be scalar as well. When columns
is a list then the values in the mapping must be a list as well.
Example usage:
update_table_from_dict(cr, table, "name", {1: "foo", 2: "bar"})
update_table_from_dict(cr, table, ["name", "passwd"], {1: ["foo", "baz"], 2: ["bar", ""]})
A recurrent challenge in writing upgrade scripts is that of updating values in a table based on some form of already available mapping from the id (or another identifier) to the new value, this is often addressed with an iterative solution in the form:
or in a more efficient (only issuing a single query) but hacky way:
With the former being ineffective for big mappings and the latter often requiring some comments at review time to get it right. This commit introduces a util meant to make it easier to efficiently perform such updates.