SectorLabs /
django-postgres-extra
| 1 | 1 | from django.core.exceptions import SuspiciousOperation |
|
|
0 ignored issues
–
show
|
|||
| 2 | 1 | from django.db.models.sql.compiler import SQLInsertCompiler, SQLUpdateCompiler |
|
|
0 ignored issues
–
show
The import
django.db.models.sql.compiler could not be resolved.
This can be caused by one of the following: 1. Missing DependenciesThis error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands. # .scrutinizer.yml
before_commands:
- sudo pip install abc # Python2
- sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use
the command for the correct version.
2. Missing __init__.py filesThis error could also result from missing Loading history...
|
|||
| 3 | |||
| 4 | 1 | from psqlextra.expressions import HStoreValue |
|
| 5 | |||
| 6 | |||
| 7 | 1 | class PostgresReturningUpdateCompiler(SQLUpdateCompiler): |
|
|
0 ignored issues
–
show
|
|||
| 8 | """Compiler for SQL UPDATE statements that return |
||
| 9 | the primary keys of the affected rows.""" |
||
| 10 | |||
| 11 | 1 | def execute_sql(self, _result_type): |
|
|
0 ignored issues
–
show
|
|||
| 12 | 1 | sql, params = self.as_sql() |
|
| 13 | 1 | sql += self._form_returning() |
|
| 14 | |||
| 15 | 1 | with self.connection.cursor() as cursor: |
|
|
0 ignored issues
–
show
|
|||
| 16 | 1 | cursor.execute(sql, params) |
|
| 17 | 1 | primary_keys = cursor.fetchall() |
|
| 18 | |||
| 19 | 1 | return primary_keys |
|
| 20 | |||
| 21 | 1 | def as_sql(self): |
|
| 22 | 1 | self._prepare_query_values() |
|
| 23 | 1 | return super().as_sql() |
|
| 24 | |||
| 25 | 1 | def _prepare_query_values(self): |
|
| 26 | """Extra prep on query values by converting |
||
| 27 | dictionaries into :see:HStoreValue expressions. |
||
| 28 | |||
| 29 | This allows putting expressions in a dictionary. |
||
| 30 | The :see:HStoreValue will take care of resolving |
||
| 31 | the expressions inside the dictionary.""" |
||
| 32 | |||
| 33 | 1 | new_query_values = [] |
|
| 34 | 1 | for field, model, val in self.query.values: |
|
|
0 ignored issues
–
show
|
|||
| 35 | 1 | if isinstance(val, dict): |
|
| 36 | 1 | val = HStoreValue(val) |
|
| 37 | |||
| 38 | 1 | new_query_values.append(( |
|
| 39 | field, |
||
| 40 | model, |
||
| 41 | val |
||
| 42 | )) |
||
| 43 | |||
| 44 | 1 | self.query.values = new_query_values |
|
|
0 ignored issues
–
show
|
|||
| 45 | |||
| 46 | 1 | def _form_returning(self): |
|
| 47 | """Builds the RETURNING part of the query.""" |
||
| 48 | |||
| 49 | 1 | qn = self.connection.ops.quote_name |
|
|
0 ignored issues
–
show
|
|||
| 50 | 1 | return ' RETURNING %s' % qn(self.query.model._meta.pk.attname) |
|
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 51 | |||
| 52 | |||
| 53 | 1 | class PostgresInsertCompiler(SQLInsertCompiler): |
|
| 54 | """Compiler for SQL INSERT statements.""" |
||
| 55 | |||
| 56 | 1 | def __init__(self, *args, **kwargs): |
|
| 57 | """Initializes a new instance of :see:PostgresInsertCompiler.""" |
||
| 58 | |||
| 59 | 1 | super().__init__(*args, **kwargs) |
|
| 60 | 1 | self.qn = self.connection.ops.quote_name |
|
|
0 ignored issues
–
show
|
|||
| 61 | |||
| 62 | 1 | def as_sql(self, return_id=False): |
|
| 63 | """Builds the SQL INSERT statement.""" |
||
| 64 | |||
| 65 | 1 | queries = [ |
|
| 66 | self._rewrite_insert(sql, params, return_id) |
||
| 67 | for sql, params in super().as_sql() |
||
| 68 | ] |
||
| 69 | |||
| 70 | 1 | return queries |
|
| 71 | |||
| 72 | 1 | def execute_sql(self, return_id=False): |
|
| 73 | # execute all the generate queries |
||
| 74 | 1 | with self.connection.cursor() as cursor: |
|
|
0 ignored issues
–
show
|
|||
| 75 | 1 | rows = [] |
|
| 76 | 1 | for sql, params in self.as_sql(return_id): |
|
| 77 | 1 | cursor.execute(sql, params) |
|
| 78 | 1 | rows.extend(cursor.fetchall()) |
|
| 79 | |||
| 80 | # create a mapping between column names and column value |
||
| 81 | 1 | return [ |
|
| 82 | { |
||
| 83 | column.name: row[column_index] |
||
| 84 | for column_index, column in enumerate(cursor.description) if row |
||
| 85 | } |
||
| 86 | for row in rows |
||
| 87 | ] |
||
| 88 | |||
| 89 | 1 | def _rewrite_insert(self, sql, params, return_id=False): |
|
| 90 | """Rewrites a formed SQL INSERT query to include |
||
| 91 | the ON CONFLICT clause. |
||
| 92 | |||
| 93 | Arguments: |
||
| 94 | sql: |
||
| 95 | The SQL INSERT query to rewrite. |
||
| 96 | |||
| 97 | params: |
||
| 98 | The parameters passed to the query. |
||
| 99 | |||
| 100 | returning: |
||
| 101 | What to put in the `RETURNING` clause |
||
| 102 | of the resulting query. |
||
| 103 | |||
| 104 | Returns: |
||
| 105 | A tuple of the rewritten SQL query and new params. |
||
| 106 | """ |
||
| 107 | |||
| 108 | 1 | returning = self.qn(self.query.model._meta.pk.attname) if return_id else '*' |
|
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 109 | |||
| 110 | 1 | if self.query.conflict_action.value == 'UPDATE': |
|
|
0 ignored issues
–
show
|
|||
| 111 | 1 | return self._rewrite_insert_update(sql, params, returning) |
|
| 112 | 1 | elif self.query.conflict_action.value == 'NOTHING': |
|
|
0 ignored issues
–
show
|
|||
| 113 | 1 | return self._rewrite_insert_nothing(sql, params, returning) |
|
| 114 | |||
| 115 | raise SuspiciousOperation(( |
||
| 116 | '%s is not a valid conflict action, specify ' |
||
| 117 | 'ConflictAction.UPDATE or ConflictAction.NOTHING.' |
||
| 118 | ) % str(self.query.conflict_action)) |
||
|
0 ignored issues
–
show
|
|||
| 119 | |||
| 120 | 1 | def _rewrite_insert_update(self, sql, params, returning): |
|
| 121 | """Rewrites a formed SQL INSERT query to include |
||
| 122 | the ON CONFLICT DO UPDATE clause.""" |
||
| 123 | |||
| 124 | 1 | update_columns = ', '.join([ |
|
| 125 | '{0} = EXCLUDED.{0}'.format(self.qn(field.column)) |
||
| 126 | for field in self.query.update_fields |
||
|
0 ignored issues
–
show
|
|||
| 127 | ]) |
||
| 128 | |||
| 129 | # build the conflict target, the columns to watch |
||
| 130 | # for conflicts |
||
| 131 | 1 | conflict_target = self._build_conflict_target() |
|
| 132 | |||
| 133 | 1 | index_predicate = self.query.index_predicate |
|
|
0 ignored issues
–
show
|
|||
| 134 | |||
| 135 | 1 | sql_template = ( |
|
| 136 | '{insert} ON CONFLICT {conflict_target} DO UPDATE ' |
||
| 137 | 'SET {update_columns} RETURNING {returning}' |
||
| 138 | ) |
||
| 139 | |||
| 140 | 1 | if index_predicate: |
|
| 141 | 1 | sql_template = ( |
|
| 142 | '{insert} ON CONFLICT {conflict_target} WHERE {index_predicate} DO UPDATE ' |
||
| 143 | 'SET {update_columns} RETURNING {returning}' |
||
| 144 | ) |
||
| 145 | |||
| 146 | 1 | return ( |
|
| 147 | sql_template.format( |
||
| 148 | insert=sql, |
||
| 149 | conflict_target=conflict_target, |
||
| 150 | update_columns=update_columns, |
||
| 151 | returning=returning, |
||
| 152 | index_predicate=index_predicate, |
||
| 153 | ), |
||
| 154 | params |
||
| 155 | ) |
||
| 156 | |||
| 157 | 1 | def _rewrite_insert_nothing(self, sql, params, returning): |
|
| 158 | """Rewrites a formed SQL INSERT query to include |
||
| 159 | the ON CONFLICT DO NOTHING clause.""" |
||
| 160 | |||
| 161 | # build the conflict target, the columns to watch |
||
| 162 | # for conflicts |
||
| 163 | 1 | conflict_target = self._build_conflict_target() |
|
| 164 | |||
| 165 | 1 | where_clause = ' AND '.join([ |
|
| 166 | '{0} = %s'.format(self._format_field_name(field_name)) |
||
| 167 | for field_name in self.query.conflict_target |
||
|
0 ignored issues
–
show
|
|||
| 168 | ]) |
||
| 169 | |||
| 170 | 1 | where_clause_params = [ |
|
| 171 | self._format_field_value(field_name) |
||
| 172 | for field_name in self.query.conflict_target |
||
|
0 ignored issues
–
show
|
|||
| 173 | ] |
||
| 174 | |||
| 175 | 1 | params = params + tuple(where_clause_params) |
|
| 176 | |||
| 177 | # this looks complicated, and it is, but it is for a reason... a normal |
||
| 178 | # ON CONFLICT DO NOTHING doesn't return anything if the row already exists |
||
| 179 | # so we do DO UPDATE instead that never executes to lock the row, and then |
||
| 180 | # select from the table in case we're dealing with an existing row.. |
||
| 181 | 1 | return ( |
|
| 182 | ( |
||
| 183 | 'WITH insdata AS (' |
||
| 184 | '{insert} ON CONFLICT {conflict_target} DO UPDATE' |
||
| 185 | ' SET {pk_column} = NULL WHERE FALSE RETURNING {returning})' |
||
| 186 | ' SELECT * FROM insdata UNION ALL' |
||
| 187 | ' SELECT {returning} FROM {table} WHERE {where_clause} LIMIT 1;' |
||
| 188 | ).format( |
||
| 189 | insert=sql, |
||
| 190 | conflict_target=conflict_target, |
||
| 191 | pk_column=self.qn(self.query.model._meta.pk.column), |
||
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 192 | returning=returning, |
||
| 193 | table=self.query.objs[0]._meta.db_table, |
||
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 194 | where_clause=where_clause |
||
| 195 | ), |
||
| 196 | params |
||
| 197 | ) |
||
| 198 | |||
| 199 | 1 | def _build_conflict_target(self): |
|
| 200 | """Builds the `conflict_target` for the ON CONFLICT |
||
| 201 | clause.""" |
||
| 202 | |||
| 203 | 1 | conflict_target = [] |
|
| 204 | |||
| 205 | 1 | if not isinstance(self.query.conflict_target, list): |
|
|
0 ignored issues
–
show
|
|||
| 206 | raise SuspiciousOperation(( |
||
| 207 | '%s is not a valid conflict target, specify ' |
||
| 208 | 'a list of column names, or tuples with column ' |
||
| 209 | 'names and hstore key.' |
||
| 210 | ) % str(self.query.conflict_target)) |
||
|
0 ignored issues
–
show
|
|||
| 211 | |||
| 212 | 1 | def _assert_valid_field(field_name): |
|
| 213 | 1 | field_name = self._normalize_field_name(field_name) |
|
| 214 | 1 | if self._get_model_field(field_name): |
|
| 215 | 1 | return |
|
| 216 | |||
| 217 | 1 | raise SuspiciousOperation(( |
|
| 218 | '%s is not a valid conflict target, specify ' |
||
| 219 | 'a list of column names, or tuples with column ' |
||
| 220 | 'names and hstore key.' |
||
| 221 | ) % str(field_name)) |
||
| 222 | |||
| 223 | 1 | for field_name in self.query.conflict_target: |
|
|
0 ignored issues
–
show
|
|||
| 224 | 1 | _assert_valid_field(field_name) |
|
| 225 | |||
| 226 | # special handling for hstore keys |
||
| 227 | 1 | if isinstance(field_name, tuple): |
|
| 228 | 1 | conflict_target.append( |
|
| 229 | '(%s->\'%s\')' % ( |
||
| 230 | self._format_field_name(field_name), |
||
| 231 | field_name[1] |
||
| 232 | ) |
||
| 233 | ) |
||
| 234 | else: |
||
| 235 | 1 | conflict_target.append( |
|
| 236 | self._format_field_name(field_name)) |
||
| 237 | |||
| 238 | 1 | return '(%s)' % ','.join(conflict_target) |
|
| 239 | |||
| 240 | 1 | def _get_model_field(self, name: str): |
|
| 241 | """Gets the field on a model with the specified name. |
||
| 242 | |||
| 243 | Arguments: |
||
| 244 | name: |
||
| 245 | The name of the field to look for. |
||
| 246 | |||
| 247 | This can be both the actual field name, or |
||
| 248 | the name of the column, both will work :) |
||
| 249 | |||
| 250 | Returns: |
||
| 251 | The field with the specified name or None if |
||
| 252 | no such field exists. |
||
| 253 | """ |
||
| 254 | |||
| 255 | 1 | field_name = self._normalize_field_name(name) |
|
| 256 | |||
| 257 | # 'pk' has special meaning and always refers to the primary |
||
| 258 | # key of a model, we have to respect this de-facto standard behaviour |
||
| 259 | 1 | if field_name == 'pk' and self.query.model._meta.pk: |
|
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 260 | 1 | return self.query.model._meta.pk |
|
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 261 | |||
| 262 | 1 | for field in self.query.model._meta.local_concrete_fields: |
|
|
0 ignored issues
–
show
It seems like
_meta was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
| 263 | 1 | if field.name == field_name or field.column == field_name: |
|
| 264 | 1 | return field |
|
| 265 | |||
| 266 | 1 | return None |
|
| 267 | |||
| 268 | 1 | def _format_field_name(self, field_name) -> str: |
|
| 269 | """Formats a field's name for usage in SQL. |
||
| 270 | |||
| 271 | Arguments: |
||
| 272 | field_name: |
||
| 273 | The field name to format. |
||
| 274 | |||
| 275 | Returns: |
||
| 276 | The specified field name formatted for |
||
| 277 | usage in SQL. |
||
| 278 | """ |
||
| 279 | |||
| 280 | 1 | field = self._get_model_field(field_name) |
|
| 281 | 1 | return self.qn(field.column) |
|
| 282 | |||
| 283 | 1 | def _format_field_value(self, field_name) -> str: |
|
| 284 | """Formats a field's value for usage in SQL. |
||
| 285 | |||
| 286 | Arguments: |
||
| 287 | field_name: |
||
| 288 | The name of the field to format |
||
| 289 | the value of. |
||
| 290 | |||
| 291 | Returns: |
||
| 292 | The field's value formatted for usage |
||
| 293 | in SQL. |
||
| 294 | """ |
||
| 295 | |||
| 296 | 1 | field_name = self._normalize_field_name(field_name) |
|
| 297 | 1 | field = self._get_model_field(field_name) |
|
| 298 | |||
| 299 | 1 | return SQLInsertCompiler.prepare_value( |
|
| 300 | self, |
||
| 301 | field, |
||
| 302 | # Note: this deliberately doesn't use `pre_save_val` as we don't |
||
| 303 | # want things like auto_now on DateTimeField (etc.) to change the |
||
| 304 | # value. We rely on pre_save having already been done by the |
||
| 305 | # underlying compiler so that things like FileField have already had |
||
| 306 | # the opportunity to save out their data. |
||
| 307 | getattr(self.query.objs[0], field.attname) |
||
|
0 ignored issues
–
show
|
|||
| 308 | ) |
||
| 309 | |||
| 310 | 1 | def _normalize_field_name(self, field_name) -> str: |
|
|
0 ignored issues
–
show
This method could be written as a function/class method.
If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example class Foo:
def some_method(self, x, y):
return x + y;
could be written as class Foo:
@classmethod
def some_method(cls, x, y):
return x + y;
Loading history...
|
|||
| 311 | """Normalizes a field name into a string by |
||
| 312 | extracting the field name if it was specified |
||
| 313 | as a reference to a HStore key (as a tuple). |
||
| 314 | |||
| 315 | Arguments: |
||
| 316 | field_name: |
||
| 317 | The field name to normalize. |
||
| 318 | |||
| 319 | Returns: |
||
| 320 | The normalized field name. |
||
| 321 | """ |
||
| 322 | |||
| 323 | 1 | if isinstance(field_name, tuple): |
|
| 324 | 1 | field_name, _ = field_name |
|
| 325 | |||
| 326 | return field_name |
||
| 327 |
This can be caused by one of the following:
1. Missing Dependencies
This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.
2. Missing __init__.py files
This error could also result from missing
__init__.pyfiles in your module folders. Make sure that you place one file in each sub-folder.