diff --git a/src/infi/clickhouse_orm/database.py b/src/infi/clickhouse_orm/database.py index 1103a1b..2911d96 100644 --- a/src/infi/clickhouse_orm/database.py +++ b/src/infi/clickhouse_orm/database.py @@ -26,8 +26,11 @@ class Database(object): self.db_url = db_url self.username = username self.password = password - self.readonly = readonly - if not self.readonly: + self.readonly = False + if readonly: + self.connection_readonly = self._is_connection_readonly() + self.readonly = True + else: self.create_database() self.server_timezone = self._get_server_timezone() @@ -175,7 +178,8 @@ class Database(object): params['user'] = self.username if self.password: params['password'] = self.password - if self.readonly: + # Send the readonly flag, unless the connection is already readonly (to prevent db error) + if self.readonly and not self.connection_readonly: params['readonly'] = '1' return params @@ -197,3 +201,7 @@ class Database(object): except DatabaseException: logger.exception('Cannot determine server timezone, assuming UTC') return pytz.utc + + def _is_connection_readonly(self): + r = self._send("SELECT value FROM system.settings WHERE name = 'readonly'") + return r.text.strip() != '0' diff --git a/tests/test_readonly.py b/tests/test_readonly.py index ca992ec..f67c093 100644 --- a/tests/test_readonly.py +++ b/tests/test_readonly.py @@ -11,17 +11,32 @@ from .base_test_with_data import * class ReadonlyTestCase(TestCaseWithData): - def test_readonly(self): + def _test_readonly_db(self, username): + self._insert_and_check(self._sample_data(), len(data)) orig_database = self.database - self.database = Database(orig_database.db_name, readonly=True) - with self.assertRaises(DatabaseException): - self._insert_and_check(self._sample_data(), len(data)) - self.assertEquals(self.database.count(Person), 0) - with self.assertRaises(DatabaseException): - self.database.drop_table(Person) - with self.assertRaises(DatabaseException): - self.database.drop_database() - self.database = orig_database + try: + self.database = Database(orig_database.db_name, username=username, readonly=True) + with self.assertRaises(DatabaseException): + self._insert_and_check(self._sample_data(), len(data)) + self.assertEquals(self.database.count(Person), 100) + list(self.database.select('SELECT * from $table', Person)) + with self.assertRaises(DatabaseException): + self.database.drop_table(Person) + with self.assertRaises(DatabaseException): + self.database.drop_database() + except DatabaseException, e: + if 'Unknown user' in unicode(e): + raise unittest.SkipTest('Database user "%s" is not defined' % username) + else: + raise + finally: + self.database = orig_database + + def test_readonly_db_with_default_user(self): + self._test_readonly_db('default') + + def test_readonly_db_with_readonly_user(self): + self._test_readonly_db('readonly') def test_insert_readonly(self): m = ReadOnlyModel(name='readonly')