Правильный VACUUM SQLite3

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Правильный VACUUM SQLite3

Сообщение LevelZero »

fpc 2.2.4
lazarus 0.9.27-0 сборка из svn от 2009-08-26
ubuntu 9.04
WindowsXP SP3

Очередной глупый вопрос.

Согласно документации команда SQLite3 VACUUM выпоняется при следующих условиях:

1. The VACUUM command will fail if there is an active transaction.
2. The VACUUM command is a no-op for in-memory databases.
3. VACUUM only works on the main database. It is not possible to VACUUM an attached database file.

Транзакций я не применяю, как победить (и надо ли) второй пункт знаний нет, с третьим пунктом вопросов нет.
Поделитесь пожалуйста рабочим примером правильного применения команды VACUUM к базе SQLite3 в Lazarus.

PS Коды своих самостоятельных попыток приводить не буду, потому как всего пять строчек да и такие советы как "читай букварь", "за парту в школу" и т.д. и т.п. я и сам себе наговорить могу. Надеюсь добрейший Logo заметит меня раньше чем alexs.
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

А в чём проблема? Вопрос непонятен...

Добавлено спустя 48 секунд:
VACCUM
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Сообщение LevelZero »

Mr.Smart писал(а):А в чём проблема? Вопрос непонятен...

Добавлено спустя 48 секунд:
VACCUM


каюсь читал
и не раз
и даже в переводе на русский
но
если я делаю это в С++ то все нормально
если сделать в Lazaruse анпример так ?

Код: Выделить всё

SQL_QQuery.Close;
SQL_Query.SQL.Clear;
SQL_Query.SQL.Add('VACUUM;');
SQL_Query.ExecSQL;;   


то имеем "Transaction not Set"
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Необходима связка компонентов TSQLTransaction, TSQLite3Connection и TSQLQuery.

Добавлено спустя 1 минуту 27 секунд:
А что вам мешает делать это на чистом API. Если у вас в С++ получается то и здесь получится :wink:
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Сообщение LevelZero »

Mr.Smart писал(а):Необходима связка компонентов TSQLTransaction, TSQLite3Connection и TSQLQuery.

Добавлено спустя 1 минуту 27 секунд:
А что вам мешает делать это на чистом API. Если у вас в С++ получается то и здесь получится :wink:



именно с ними я и пытась

чистый API ?

Код: Выделить всё

uses sqlite3,sqlite3db;

var
  MySQL: TSQLite; 

  MySQL := TSQLite.Create('Base.db3');
  MySQL.BusyTimeout := 1000;
  // writeln(MySQL.Version);
  Writeln('VACUUM');
  MySQL.Query('VACUUM;', nil);
  MySQL.Free;       


дает ошибку "File not Open"
хотя дальше связка TSQLite3Connection и TSQLQuery работает без вопросов
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Нет это не чистый API.
На чистом API будет выглядеть примерно так:

Код: Выделить всё

uses sqlite3dyn;

function CallBack(NotUsed: Pointer; argc: Integer; argv: PPChar; azColName: PPChar): Integer; cdecl;
var
 j: Integer;
begin
  for j:=0 to argc-1 do
   begin
    Write(azColName[j]^,': ');
    if argv[j]<>nil then
     WriteLn(argv[j]^)
    else
     WriteLn('NULL');
   end;
  Result:=0;
end;

var
 db: PSQLite3;
 Err: PChar;
 rc: Integer;
begin
  rc:=sqlite3_open('Имя файла',db);
  if rc<>SQLITE_OK then
   begin
    WriteLn('Ошибка открытия базы.');
    sqlite3_close(db);
    Halt;
   end;
  rc:=sqlite3_exec(db,'SQL Запрос',@CallBack,nil,@Err);
  if rc<>SQLITE_OK then
   begin
    WriteLn('Ошибка в запросе "',Err);
    sqlite3_free(Err);
   end;
  sqlite3_close(db);
end;
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Сообщение LevelZero »

понимаю
смотрел
но лезть сюда не хочу
хотелось бы штатными средствами
есть возможность ?
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Я так понимаю, что стандартные компоненты требуют инициализацию транзакции.
Попробуйте посмотреть каким сообщением заканчивается операция подключения к файлу

Код: Выделить всё

uses sqlite3,sqlite3db;

var
  MySQL: TSQLite; 

  MySQL := TSQLite.Create('Base.db3');
  WriteLn(MySQL.LastError,': ',MySQL.LastErrorMessage);
  MySQL.BusyTimeout := 1000;
  // writeln(MySQL.Version);
  Writeln('VACUUM');
  MySQL.Query('VACUUM;', nil);
  MySQL.Free;       
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Сообщение LevelZero »

сделал
приложение у меня не консольное
при компиляции выдает "File not Open"
при запуске в консоле то же самое
и сообщений никаких
сейчас я в WindowsXP
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Укажите полный путь к файлу базы данных
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Сообщение LevelZero »

это было первое что я сделал
может надо имя файла в строковой переменой явно перекодировать в системную кодировку ?
если да - то как это сделать правильно в Lazarus
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Для перекодировки в системную кодировку есть функция UTF8ToSys.
Хотя здесь написано, что необходимо передавать имя файла только в кодировке UTF-8 и Windows не исключение.
Аватара пользователя
LevelZero
новенький
Сообщения: 19
Зарегистрирован: 27.02.2007 11:52:36

Сообщение LevelZero »

все верно
кодировка не виновата
куда дальше ?
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

решил так (нашел на забугорном форуме):

Код: Выделить всё

uses ..., sqlite3ds;


procedure TForm1.MyVacuum();
var
    dsLite : TSqlite3Dataset;
begin
     dsLite := TSqlite3Dataset.Create(nil);
     dsLite.FileName:='db' + SepDir + 'settaggi.s3db';
     dsLite.ExecSQL('VACUUM;');
     dsLite.Free;
end;
Angel_19
новенький
Сообщения: 37
Зарегистрирован: 24.06.2014 17:29:47

Сообщение Angel_19 »

Нашел такое решение:

Код: Выделить всё

...
TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    SQLite3ConnectionService: TSQLite3Connection;
...
...
...


SQLite3ConnectionService.ExecuteDirect('End Transaction');
SQLite3ConnectionService.ExecuteDirect('VACUUM');
SQLite3ConnectionService.ExecuteDirect('Begin Transaction');
Ответить