def _users_handle_update(self, req, resp): update_clause, u_values = util.entry_to_update( req.entry, deferred=self._filter_defer) filter_clause, f_values = util.equivalent_filter( req.match, deferred=self._filter_defer) values = u_values + f_values if not filter_clause or not update_clause: self._logger.info( "Could not generate update SQL: " "filter_clause: '%s', update_clause: '%s'", filter_clause, update_clause) resp.result_type = general_pb2.ResultType.ERROR resp.error = "Bad input: could not generate SQL." return sql = "UPDATE users SET " + update_clause + " WHERE " + filter_clause valstr = ', '.join(str(v) for v in values) self._logger.debug('Running query "%s" with values (%s)', sql, valstr) try: count = self._db.execute_count(sql, *values) except sqlite3.Error as e: resp.result_type = general_pb2.ResultType.ERROR resp.error = str(e) return if count != 1: err = 'UPDATE affected {} rows, expected 1'.format(count) resp.result_type = general_pb2.ResultType.ERROR self._logger.warning(err) resp.error = err resp.result_type = general_pb2.ResultType.OK
def _follow_handle_find(self, req, resp): default = [("state", database_pb2.Follow.ACTIVE)] filter_clause, values = util.equivalent_filter(req.match, default) try: if not filter_clause: # Since we set a default match, this should never happen. err = 'Query {} not allowed for follows'.format( 'SELECT * FROM follows', ) self._logger.warning(err) resp.result_type = general_pb2.ResultType.ERROR resp.error = err return else: query = 'SELECT * FROM follows WHERE ' + filter_clause valstr = ', '.join(str(v) for v in values) self._logger.debug('Running query "%s" with values (%s)', query, valstr) res = self._db.execute(query, *values) except sqlite3.Error as e: self._logger.warning('Got error reading DB: ' + str(e)) resp.result_type = general_pb2.ResultType.ERROR resp.error = str(e) return resp.result_type = general_pb2.ResultType.OK for tup in res: if not self._db_tuple_to_entry(tup, resp.results.add()): del resp.results[-1] self._logger.debug('%d results of follower query.', len(resp.results))
def test_equivalent_filter_defaults(self): entry = database_pb2.PostsEntry(title="Despacito") clause, vals = util.equivalent_filter(entry, defaults=[('body', 'cool')]) self.assertIn("title = ?", clause) self.assertIn("AND", clause) self.assertIn("body = ?", clause) self.assertIn("Despacito", vals) self.assertIn("cool", vals)
def test_equivalent_filter_deferred_default_unset(self): entry = database_pb2.PostsEntry(title="Despacito", ) d = {'body': lambda entry, comp: ("body" + comp, True)} de = [('body', False)] clause, vals = util.equivalent_filter(entry, defaults=de, deferred=d) self.assertIn("title = ?", clause) self.assertIn("AND", clause) self.assertIn("body = ?", clause) self.assertIn("Despacito", vals) self.assertIn(False, vals)
def _handle_delete(self, req, resp): filter_clause, values = util.equivalent_filter(req.match) try: if not filter_clause: self._db.execute('DELETE FROM posts') else: self._db.execute('DELETE FROM posts WHERE ' + filter_clause, *values) except sqlite3.Error as e: resp.result_type = general_pb2.ResultType.ERROR resp.error = str(e) return resp.result_type = general_pb2.ResultType.OK
def _follow_handle_delete(self, req, resp): self._logger.info('Deleting follow from Follow database.') try: filter_clause, values = util.equivalent_filter(req.match) query = 'DELETE FROM follows WHERE ' + filter_clause # TODO(iandioch): Count affected rows. self._db.execute(query, *values) except sqlite3.Error as e: self._logger.error(str(e)) resp.result_type = general_pb2.ResultType.ERROR resp.error = str(e) return resp.result_type = general_pb2.ResultType.OK
def test_equivalent_filter_deferred(self): entry = database_pb2.PostsEntry( title="Despacito", body="alexa", ) d = {'body': lambda entry, comp: ("body" + comp, True)} clause, vals = util.equivalent_filter(entry, deferred=d) self.assertIn("title = ?", clause) self.assertIn("AND", clause) self.assertIn("body = ?", clause) self.assertIn("Despacito", vals) self.assertIn(True, vals) self.assertNotIn("alexa", vals)
def _handle_find(self, req, resp): filter_clause, values = util.equivalent_filter(req.match) user_id = -1 if req.HasField("user_global_id"): user_id = req.user_global_id.value try: if not filter_clause: res = self._db.execute(self._select_base, user_id, user_id, user_id) else: res = self._db.execute( self._select_base + "WHERE " + filter_clause + " ORDER BY p.global_id DESC", *([user_id, user_id, user_id] + values)) except sqlite3.Error as e: resp.result_type = general_pb2.ResultType.ERROR resp.error = str(e) return resp.result_type = general_pb2.ResultType.OK for tup in res: if not self._db_tuple_to_entry(tup, resp.results.add()): del resp.results[-1]
def _follow_handle_update(self, req, resp): if not req.HasField("match") or not req.HasField("entry"): resp.result_type = general_pb2.ResultType.ERROR resp.error = "bad parameters: please set both match and entry" return if not req.match.follower or not req.match.followed: resp.result_type = general_pb2.ResultType.ERROR resp.error = "bad parameters: please set both follower and followed" return filter_clause, values = util.equivalent_filter(req.match) if not filter_clause: resp.result_type = general_pb2.ResultType.ERROR resp.error = "could not create filter for UPDATE" return try: # since we only update state we can hardcode that paramater query = 'UPDATE follows SET state = ? WHERE ' + filter_clause valstr = str(req.entry.state) + ", " + ', '.join( str(v) for v in values) count = self._db.execute_count(query, req.entry.state, *values) except sqlite3.Error as e: self._logger.warning('Got error writing to DB: ' + str(e)) resp.result_type = general_pb2.ResultType.ERROR resp.error = str(e) return if count != 1: err = 'UPDATE affected {} rows, expected 1'.format(count) resp.result_type = general_pb2.ResultType.ERROR self._logger.warning(err) resp.error = err resp.result_type = general_pb2.ResultType.OK
def test_equivalent_filter(self): entry = database_pb2.PostsEntry(title="Despacito") clause, vals = util.equivalent_filter(entry) self.assertEqual(clause, "title = ?") self.assertEqual(vals, ["Despacito"])
def _users_handle_find(self, req, resp): filter_clause, values = util.equivalent_filter( req.match, deferred=self._filter_defer) self._user_find_op(resp, filter_clause, values, self._get_uid(req))