Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
#1

SQLite Блокровка/разблокировка - C++

05.07.2013, 22:09. Просмотров 1209. Ответов 18
Метки нет (Все метки)

Есть код: таймер периодически создает/запускает поток, поток получает данные ( через интернет) открывает БД (sqlite3_open() ) и добавляет туда новые данные закрывает БД ( sqlite3_close(db); ) поток завершается.

При первом создании потока все проходит нормально данные вставляются ошибок- нет, при втором при попытке
выполнить INSERT пишет что база блокирована, данные не занеслись.

Период между созданиями потоком значительный, так что первый поток успевает завершится до создания второго.

Вопрос : как правильно закрыть БД что бы она разблокировалась ? Или что могло повлиять на такую работу ?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Dr_Quake
Заблокирован
05.07.2013, 23:01     SQLite Блокровка/разблокировка #2
Дебагом посмотреть что возвращает sqlite3_close итд если данные на месте и файла журнала нету.
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
05.07.2013, 23:16  [ТС]     SQLite Блокровка/разблокировка #3
Возвращает :
unable to close due to unfinalized statements or unfinished backups
Добавлено через 2 минуты
Что-то не могу понять где ошибка

Код класса обвертки ( код С++Builder)
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//---------------------------------------------------------------------------
namespace My{
//---------------------------------------------------------------------------
class SQLite
{
   String FError;
   String FResult;
   char *error;
 
   bool   FOpen;
   sqlite3 *db;
 
   public:
    SQLite():FError(""),FOpen(0),error(0),db(0){};
    ~SQLite();
 
    bool Open(String Path);
    bool Exists(String SiteId);
    bool Insert(const My::Subject& Subject);
 
    bool View(TStringGrid* SG);
 
    bool  IsOpen() { return FOpen;  }
    String Error() { return FError; };
    String Result(){ return FResult;};
    bool Close();
};
//-----------------------------End My:: -------------------------------------
}
//---------------------------------------------------------------------------


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//---------------------------------------------------------------------------
bool My::SQLite::Open(String Path)
{
  if(FOpen) return false;
 
  int res = sqlite3_open(UTF8String(Path).c_str(), &db);
  if( res )
    {
      FError= UTF8String(sqlite3_errmsg(db));
      sqlite3_close(db);
      return false;
    }
  else  FOpen= true;
 
return  true;
}
//---------------------------------------------------------------------------
bool My::SQLite::Insert(const My::Subject& Subject)
{
  UTF8String Query=
    L"INSERT INTO \"main\".\"Subjects\" \
   (Id,SiteId,Subject,Author,Reference)\
    VALUES (NULL,'"+Subject.SiteId    +L"','"+
                    Subject.Name      +L"','"+
                    Subject.Author    +L"','"+
                    Subject.Reference +L"')";
 
  int res = sqlite3_exec(db,Query.c_str(),0, 0, &error);
 
  if( res!=SQLITE_OK )
    {
      FError= UTF8String(error);
      sqlite3_free(error);
      return false;
    }
 
return  true;
}
//---------------------------------------------------------------------------
bool My::SQLite::Exists(String SiteId)
{
  sqlite3_stmt *statement;
 
  UTF8String Query=
      L"SELECT  EXISTS(SELECT * FROM  Subjects WHERE SiteId ='"+SiteId+L"')";
 
  int res = sqlite3_prepare(db, Query.c_str(), -1, &statement,0);
  if( res!=SQLITE_OK )
    {
      //FError= UTF8String(error);
      //sqlite3_free(error);
      FError= UTF8String(sqlite3_errmsg(db));
      return false;
    }
 
  sqlite3_step(statement);
  FResult = (char*)sqlite3_column_text(statement,0);
 
return  true;
}
//---------------------------------------------------------------------------
bool My::SQLite::View(TStringGrid* SG)
{
  sqlite3_stmt *statement;
 
  UTF8String Query=
      L"SELECT * FROM Subjects  ORDER BY Id LIMIT 100";
 
  int res = sqlite3_prepare(db, Query.c_str(), -1, &statement,0);
  if( res!=SQLITE_OK )
    {
      FError= UTF8String(sqlite3_errmsg(db));
      return false;
    }
 
  for(int r=0; r<100; ++r)
    {
      if( sqlite3_step(statement)==SQLITE_DONE) break;
 
      String Text;
 
      int col_count= sqlite3_column_count(statement);
      for(int c=0; c<col_count; ++c)
        {
          if(c>=2 && c<=4)
            {
              Text+= UTF8String((char*)sqlite3_column_text(statement,c));
              SG->Cells[2][r+1] = Text;
              Text+="\n";
            }
          else
            if(c<2)
              SG->Cells[c][r+1] = UTF8String((char*)sqlite3_column_text(statement,c));
           //   else
           //     SG->Cells[3][r+1] = UTF8String((char*)sqlite3_column_text(statement,c));
        }
    }
 
  sqlite3_finalize(statement);
 
return  true;
}
//---------------------------------------------------------------------------
bool My::SQLite::Close()
{
  int res= sqlite3_close(db);
  if( res!=SQLITE_OK )
    {
      FError= UTF8String(sqlite3_errmsg(db));
      return false;
    }
return true;
}
//---------------------------------------------------------------------------
My::SQLite::~SQLite()
{
  //if(FOpen) sqlite3_close(db);
};
//---------------------------------------------------------------------------


Добавлено через 5 минут
Вроде нашел ошибку в методе Exists забыл выполнить sqlite3_finalize()

C++
1
2
3
sqlite3_step(statement);
FResult = (char*)sqlite3_column_text(statement,0);
sqlite3_finalize(statement);
Dr_Quake
Заблокирован
05.07.2013, 23:38     SQLite Блокровка/разблокировка #4
Ну если код такой простой тебе вообще это нафиг не нужно, а в критичных местах можно вообще делать тупо exec begin transaction;&&amp;commit;
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
05.07.2013, 23:42  [ТС]     SQLite Блокровка/разблокировка #5
Не совсем понял, что не надо ?

Как бы только начал разбираться с библиотекой, а в доке находил только простые примеры.
Dr_Quake
Заблокирован
06.07.2013, 00:29     SQLite Блокровка/разблокировка #6
В простых вещах prepared queries не нужны, фильтровать лучше у себя учиться если именно про обучение.
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
06.07.2013, 00:30  [ТС]     SQLite Блокровка/разблокировка #7
Цитата Сообщение от Dr_Quake Посмотреть сообщение
В простых вещах prepared queries не нужны, фильтровать лучше у себя учиться если именно про обучение.
А как данные вытягивать ?

Я так и не понял как правильно это делать через колбеки: sqlite3
Dr_Quake
Заблокирован
06.07.2013, 00:32     SQLite Блокровка/разблокировка #8
Напрямую sql в sqlite3_exec, но опять же это только для обучения важно пройти. CALLBACK в sqlite нафиг не нужен на мой взгляд, не те масштабы чтобы так издеваться над файловой БД, но тут мало ли для чего пригодится, ты callback правильный фактически в нормальном виде на размере данных небольшом и не увидишь нормально, максимум 1-2 раза, но тут уже я не работал с этим почти, весь смысл sqlite - быстрая локальная небольшая база, а по правильному - ещё и memtable, это его основное назначение.
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
06.07.2013, 00:36  [ТС]     SQLite Блокровка/разблокировка #9
Цитата Сообщение от Dr_Quake Посмотреть сообщение
Напрямую sql в sqlite3_exec, но опять же это только для обучения важно пройти.
Не понял что вы имеете ввиду "под напрямую"? sqlite3_exec() использует колбек для получения результата запроса
Dr_Quake
Заблокирован
06.07.2013, 00:41     SQLite Блокровка/разблокировка #10
К тому, что там prepare/exec не нужен по сути. Prepared Statements для скорости и автоматизации escaping'a нужны.

http://stackoverflow.com/questions/1...ve-performance
castaway
Эксперт С++
4872 / 3011 / 370
Регистрация: 10.11.2010
Сообщений: 11,061
Записей в блоге: 10
Завершенные тесты: 1
06.07.2013, 16:05     SQLite Блокровка/разблокировка #11
Applications should finalize all prepared statements, close all BLOB handles, and finish all sqlite3_backup objects associated with the sqlite3 object prior to attempting to close the object.
Думаю не хватает sqlite3_finalize(statement); в My::SQLite::Exists()

Добавлено через 4 минуты
Пардон, не заметил что эту ошибку ты уже нашел...
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
06.07.2013, 16:09  [ТС]     SQLite Блокровка/разблокировка #12
Цитата Сообщение от Avazart Посмотреть сообщение
Я так и не понял как правильно это делать через колбеки: sqlite3
Это актуально ...
castaway
Эксперт С++
4872 / 3011 / 370
Регистрация: 10.11.2010
Сообщений: 11,061
Записей в блоге: 10
Завершенные тесты: 1
06.07.2013, 16:15     SQLite Блокровка/разблокировка #13
Цитата Сообщение от Avazart Посмотреть сообщение
Я так и не понял как правильно это делать через колбеки: sqlite3
Я делаю так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>
#include "../sqlite/sqlite3.h"
 
static int callback( void *NotUsed, int argc, char **argv, char **azColName )
{
    for ( int i = 0; i < argc; i++ ) {
        printf( "%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL" );
    }
    printf( "\n" );
    return 0;
}
 
int main( int narg, char **arg )
{
    int         r;
    sqlite3 *   db = 0;
    char *      err_msg = 0;
 
    if ( narg != 2 ) {
        fprintf( stderr, "%s \"REQUEST\"\n", arg[0] );
        return 1;
    }
 
    r = sqlite3_open( "test_db", &db );
    if ( !r ) {
        r = sqlite3_exec( db, arg[1], callback, 0, &err_msg );
        if ( r == SQLITE_OK ) {
            fprintf( stderr, "sqlite3_exec(): ok\n" );
        } else {
            fprintf( stderr, "sqlite3_exec(): %s\n", err_msg );
            sqlite3_free( err_msg );
        }
    } else {
        fprintf( stderr, "sqlite3_open(): error %s\n", sqlite3_errmsg( db ) );
    }
 
    if ( db ) {
        r = sqlite3_close( db );
        fprintf( stderr, "sqlite3_close(): %s\n", r == SQLITE_OK ? "ok" : "fail" );
    }
 
    return 0;
}
Добавлено через 1 минуту
Пример результата запроса "SELECT * FROM my_table" уже созданной БД:
id = 1
name = John
text = aaa

id = 2
name = Ben
text = bbb

id = 3
name = CCC
text = c

id = 4
name = DDD
text = d

id = 5
name = EEE
text = ee

id = 6
name = FFF
text = fff
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
06.07.2013, 16:17  [ТС]     SQLite Блокровка/разблокировка #14
Смотри ссылку sqlite3 ...

Меня интересует как занести, к примеру, данные таблицы в двумерный массив ...
castaway
Эксперт С++
4872 / 3011 / 370
Регистрация: 10.11.2010
Сообщений: 11,061
Записей в блоге: 10
Завершенные тесты: 1
06.07.2013, 16:22     SQLite Блокровка/разблокировка #15
callback предоставляет тебе эти (запрошенные) данные. Бери и заноси, в чем проблема? Ты не знаешь как создать двумерный массив?
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
06.07.2013, 16:25  [ТС]     SQLite Блокровка/разблокировка #16
C++
1
2
3
4
5
6
7
8
static int callback( void *NotUsed, int argc, char **argv, char **azColName )
{
    for ( int i = 0; i < argc; i++ ) {
        printf( "%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL" );
    }
    printf( "\n" );
    return 0;
}
char **argv - одномерный массив строк, где тут колонки, а где столбцы ?
castaway
Эксперт С++
4872 / 3011 / 370
Регистрация: 10.11.2010
Сообщений: 11,061
Записей в блоге: 10
Завершенные тесты: 1
06.07.2013, 16:30     SQLite Блокровка/разблокировка #17
Цитата Сообщение от Avazart Посмотреть сообщение
где тут колонки, а где столбцы ?
Колонки и столбцы в запросе.

Я не специалист по БД но представляю себе это так:
1. Например, есть БД, в ней таблица, в ней 3 столбца ( id, name, age ).
2. Мне нужно заполнить массив именами (name).
3. Делаем запрос: "SELECT name FROM my_table"
4. callback выдает тебе список имен (argv[i] - одно имя), ты их заносишь.

Что я сказал не так?
Avazart
7044 / 5221 / 259
Регистрация: 10.12.2010
Сообщений: 22,944
Записей в блоге: 17
06.07.2013, 16:39  [ТС]     SQLite Блокровка/разблокировка #18
Зайду иначе ..

Имеем вывод
id = 1
name = John
text = aaa

id = 2
name = Ben
text = bbb

id = 3
name = CCC
text = c

id = 4
name = DDD
text = d

id = 5
name = EEE
text = ee

id = 6
name = FFF
text = fff
А мне надо
id name text
-- ------- -----
1 John aaa
2 Ben bbb
3 CCC cccc
5 DDD ddd
6 ...
Добавлено через 3 минуты
Блин написал пост, и само дошло что calback может вызываться несколько раз при выполнении одного запроса. .... на то он и колбек...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2013, 16:44     SQLite Блокровка/разблокировка
Еще ссылки по теме:

C++ Работа с SQLite
Vector allocator SQLite C++
Как собрать приложение С++ которое содержит исходники SQLite C++
Неправильная кодировка в SQLite C++
SQLite for Excel или как выгрузить данные в SQLite VBA

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
castaway
Эксперт С++
4872 / 3011 / 370
Регистрация: 10.11.2010
Сообщений: 11,061
Записей в блоге: 10
Завершенные тесты: 1
06.07.2013, 16:44     SQLite Блокровка/разблокировка #19
Цитата Сообщение от Avazart Посмотреть сообщение
А мне надо
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static int callback( void *NotUsed, int argc, char **argv, char **azColName )
{
    static int first = 1;
 
    if ( first ) {
        for ( int i = 0; i < argc; i++ ) {
            printf( "\t%s", azColName[i] ); // выводим имена столбцов
        }
        first = 0;
        printf( "\n" );
    }
 
    for ( int i = 0; i < argc; i++ ) {
        printf( "\t%s", argv[i] ? argv[i] : "NULL" ); // выводим информацию под столбцами
    }
    printf( "\n" );
 
    return 0;
}
id name text
1 John aaa
2 Ben bbb
3 CCC c
4 DDD d
5 EEE ee
6 FFF fff
Yandex
Объявления
06.07.2013, 16:44     SQLite Блокровка/разблокировка
Ответ Создать тему
Опции темы

Текущее время: 13:30. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru