def evaluate_expression(expression, instance, connection): """ A limited evaluator for Django's F expressions. This are evaluated within the get/put transaction in _update_entity so these will happen atomically """ if isinstance(expression, (six.string_types, int, float)): return expression if isinstance(expression, Aggregate): raise NotSupportedError("Aggregate expressions are not supported on the datastore") if hasattr(expression, 'name'): field = instance._meta.get_field(expression.name) return get_prepared_db_value(connection, instance._original, field) if isinstance(expression, Col): field = expression.field return get_prepared_db_value(connection, instance._original, field) if hasattr(expression, 'value'): return expression.value if hasattr(expression, 'connector') and expression.connector in CONNECTORS: if hasattr(expression, 'children'): lhs, rhs = expression.children else: lhs, rhs = expression.lhs, expression.rhs return CONNECTORS[expression.connector]( evaluate_expression(lhs, instance, connection), evaluate_expression(rhs, instance, connection), ) raise NotImplementedError("Support for expression %r isn't implemented", expression)
def _update_entity(self, key): caching.remove_entity_from_context_cache_by_key(key) result = datastore.Get(key) original = copy.deepcopy(result) instance_kwargs = {field.attname:value for field, param, value in self.values} instance = MockInstance(**instance_kwargs) for field, param, value in self.values: result[field.column] = get_prepared_db_value(self.connection, instance, field, raw=True) #Add special indexed fields for index in special_indexes_for_column(self.model, field.column): indexer = REQUIRES_SPECIAL_INDEXES[index] result[indexer.indexed_column_name(field.column)] = indexer.prep_value_for_database(value) if not constraints.constraint_checks_enabled(self.model): #The fast path, no constraint checking datastore.Put(result) caching.add_entity_to_context_cache(self.model, result) else: to_acquire, to_release = constraints.get_markers_for_update(self.model, original, result) #Acquire first, because if that fails then we don't want to alter what's already there constraints.acquire_identifiers(to_acquire, result.key()) try: datastore.Put(result) caching.add_entity_to_context_cache(self.model, result) except: constraints.release_identifiers(to_acquire) raise else: #Now we release the ones we don't want anymore constraints.release_identifiers(to_release)
def _update_entity(self, key): result = datastore.Get(key) original = copy.deepcopy(result) for field, param, value in self.values: result[field.column] = get_prepared_db_value(self.connection, MockInstance(field, value), field) #Add special indexed fields for index in special_indexes_for_column(self.model, field.column): indexer = REQUIRES_SPECIAL_INDEXES[index] result[indexer.indexed_column_name(field.column)] = indexer.prep_value_for_database(value) entity_pre_update.send(sender=self.model, entity=result) to_acquire, to_release = constraints.get_markers_for_update(self.model, original, result) #Acquire first, because if that fails then we don't want to alter what's already there constraints.acquire_identifiers(to_acquire, result.key()) try: datastore.Put(result) except: constraints.release_identifiers(to_acquire) raise else: #Now we release the ones we don't want anymore constraints.release_identifiers(to_release) entity_post_update.send(sender=self.model, entity=result)
def _update_entity(self, key): caching.remove_entity_from_context_cache_by_key(key) result = datastore.Get(key) original = copy.deepcopy(result) for field, param, value in self.values: result[field.column] = get_prepared_db_value(self.connection, MockInstance(field, value), field) #Add special indexed fields for index in special_indexes_for_column(self.model, field.column): indexer = REQUIRES_SPECIAL_INDEXES[index] result[indexer.indexed_column_name(field.column)] = indexer.prep_value_for_database(value) to_acquire, to_release = constraints.get_markers_for_update(self.model, original, result) #Acquire first, because if that fails then we don't want to alter what's already there constraints.acquire_identifiers(to_acquire, result.key()) try: datastore.Put(result) caching.add_entity_to_context_cache(self.model, result) except: constraints.release_identifiers(to_acquire) raise else: #Now we release the ones we don't want anymore constraints.release_identifiers(to_release)
def _update_entity(self, key): result = datastore.Get(key) for field, param, value in self.values: result[field.column] = get_prepared_db_value(self.connection, MockInstance(field, value), field) #Add special indexed fields for index in special_indexes_for_column(self.model, field.column): indexer = REQUIRES_SPECIAL_INDEXES[index] result[indexer.indexed_column_name(field.column)] = indexer.prep_value_for_database(value) datastore.Put(result)
def _update_entity(self, key): caching.remove_entity_from_cache_by_key(key) try: result = datastore.Get(key) except datastore_errors.EntityNotFoundError: reserve_id(key.kind(), key.id_or_name()) result = datastore.Entity(key.kind(), id=key.id_or_name()) original = copy.deepcopy(result) instance_kwargs = { field.attname: value for field, param, value in self.values } instance = MockInstance(**instance_kwargs) for field, param, value in self.values: column_value = get_prepared_db_value(self.connection, instance, field, raw=True) result[field.column] = column_value # Add special indexed fields for index in special_indexes_for_column(self.model, field.column): indexer = REQUIRES_SPECIAL_INDEXES[index] values = indexer.prep_value_for_database(column_value) if values is None: continue if not hasattr(values, "__iter__"): values = [values] for value in values: column = indexer.indexed_column_name(field.column, value) if column in result: if not isinstance(result[column], list): result[column] = [result[column], value] else: result[column].append(value) else: result[column] = value if not constraints.constraint_checks_enabled(self.model): # The fast path, no constraint checking datastore.Put(result) caching.add_entity_to_cache(self.model, result, caching.CachingSituation.DATASTORE_PUT) else: to_acquire, to_release = constraints.get_markers_for_update( self.model, original, result) # Acquire first, because if that fails then we don't want to alter what's already there constraints.acquire_identifiers(to_acquire, result.key()) try: datastore.Put(result) caching.add_entity_to_cache( self.model, result, caching.CachingSituation.DATASTORE_PUT) except: constraints.release_identifiers(to_acquire) raise else: # Now we release the ones we don't want anymore constraints.release_identifiers(to_release)