Russian Qt Forum

Qt => Базы данных => Тема начата: QCasper от Май 08, 2009, 11:45



Название: Открытие базы данных только для чтения
Отправлено: QCasper от Май 08, 2009, 11:45
Работаю с базой sqlite с помощью класса QSqlDatabase и прочими, применимыми для этого дела. Как открывать её только для чтения? То есть чтобы запросы типа update и прочие "пишущие" не срабатывали.


Название: Re: Открытие базы данных только для чтения
Отправлено: developer от Май 08, 2009, 13:22
Как сделать на уровне базы данных не знаю. Но програмно попробуй просто проверить sql, если он имеет слово SELECT тогда такой запрос пропустить, иначе запретить исполнениэ запроса, слово SELECT можеш найти с помощью регекса.


Название: Re: Открытие базы данных только для чтения
Отправлено: QCasper от Май 08, 2009, 17:06
Ага, а если он имеет слово и селект и апдейт? И ремув до кучи. Запрос вложенный может быть. Вобщем это костыль, рассматривался, не устраивает.


Название: Re: Открытие базы данных только для чтения
Отправлено: lit-uriy от Май 08, 2009, 17:33
не знаю можно ли задать параметры средствами Qt, но сама СУБД позволяет открывать БД в режиме "только чтение" см. тут: http://www.sqlite.org/c3ref/open.html


Название: Re: Открытие базы данных только для чтения
Отправлено: lit-uriy от Май 08, 2009, 17:39
Ещё один вариант создать временные тригеры:
CREATE TEMPORARY TRIGGER ...
и в них осуществлять какую-нибудь ругань.
Они автоматически удаляются при закрытии соединения.


Название: Re: Открытие базы данных только для чтения
Отправлено: QCasper от Май 08, 2009, 17:48
не знаю можно ли задать параметры средствами Qt, но сама СУБД позволяет открывать БД в режиме "только чтение" см. тут: http://www.sqlite.org/c3ref/open.html

Интересно таки с помощью Qt, поэтому здесь и спрашиваю.

Ещё один вариант создать временные тригеры

А вот здесь я что-то не очень понял, можно подробнее?


Название: Re: Открытие базы данных только для чтения
Отправлено: lit-uriy от Май 08, 2009, 17:58
>>А вот здесь я что-то не очень понял, можно подробнее?
Я мало работал с Лайтом. Незнаю есть ли в нём возможность генерить исключения из тригера.
Но для огнептица, например так:
создается тригер на событие (в твоём случае на BEFORE UPDATE/BEFORE INSERT) на интерисующие или все таблицы. Т.к. обе операции запрещены, то в тригере сразу же генерится исключение, и следовательно опрерация вставки/обновления прерывается.


Название: Re: Открытие базы данных только для чтения
Отправлено: QCasper от Май 12, 2009, 10:00
создается тригер на событие (в твоём случае на BEFORE UPDATE/BEFORE INSERT) на интерисующие или все таблицы. Т.к. обе операции запрещены, то в тригере сразу же генерится исключение, и следовательно опрерация вставки/обновления прерывается.

А можно ли в одном случае прервать операцию вставки/обновления по срабатыванию триггера, а в другом случае продолжить?


Название: Re: Открытие базы данных только для чтения
Отправлено: QCasper от Май 12, 2009, 14:38
Вобщем пока решил вот таким образом:

Код:
void setWritingAllowed(bool allowed) {
QString query = (!allowed
?
"create trigger disallow_%1_on_%2 before %1 on %2 begin select "
"case when 1=1 then raise(abort, 'writing_not_allowed') end; end"
:
"drop trigger disallow_%1_on_%2")
;

const QStringList actionList = QStringList()
<< "DELETE" << "INSERT" << "UPDATE";

foreach(QString table, c_TableNameList)
foreach(QString action, actionList)
execQuery(query.arg(action).arg(table));
}

и, соответственно в местах, где хочу защититься от записи пишу:

Код:
setWritingAllowed(false);
// здесь код выполнения запроса
setWritingAllowed(true);

Если у кого-то есть более красивое и короткое решение, буду несказанно рад о нём узнать.

В этом же решении меня особенно раздражает строчка "select case when 1=1 then raise(abort, 'writing_not_allowed') end", но как по другому заполнить пустое место между BEGIN и END я не осилил найти.


Название: Re: Открытие базы данных только для чтения
Отправлено: break от Май 20, 2009, 02:59
Цитировать
Ага, а если он имеет слово и селект и апдейт? И ремув до кучи. Запрос вложенный может быть. Вобщем это костыль, рассматривался, не устраивает.

Конечно понимаю что так вам не хочется но все же - если создать массив ключевых слов меняющих метаданных и в каждом отправляемом запросе искать их (а не select)- если их нет - то пропусать если хоть одно нашлось нет.

собственно ваш список таких меняющих метаданные слов:

const QStringList actionList = QStringList()
actionList << "DELETE" << "INSERT" << "UPDATE";

может это и костыль но создание / удаление триггеров в БД это еще больший костыль - т.к. программа должна стремиться не менять метаданные бех надобности. Что например будет если ваша программа сделает setWritingAllowed(false); --- а потом вылетит с ошибкой?

Кстати как там в SQLite нет у триггеров такого понятия как "активность" - тогда уж хоть через него