crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> SQLite и хранимые процедуры, Поддерживает ли SQLite хранимые процедуры
legat
  опции профиля:
сообщение 9.8.2010, 17:03
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 10
Регистрация: 8.8.2010
Пользователь №: 1940

Спасибо сказали: 0 раз(а)




Репутация:   0  


Поддерживает ли SQLite хранимые процедуры?
Если да, то как средствами Qt их вызвать?
Если нет, то какими способами этот недостаток можно обойти?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
DEADHUNT
  опции профиля:
сообщение 9.8.2010, 17:58
Сообщение #2


Активный участник
***

Группа: Участник
Сообщений: 430
Регистрация: 15.4.2009
Пользователь №: 686

Спасибо сказали: 26 раз(а)




Репутация:   2  


Цитата(legat @ 9.8.2010, 18:03) *
Если нет, то какими способами этот недостаток можно обойти?

написать на C++ аналог нужной хранимой процедуры.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 9.8.2010, 18:52
Сообщение #3


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


я завтра посмотрю на работе, как я это реализовывала. тут дома у меня нет кода.
суть в том, что там можно организовать вызов сишной процедуры. регистрируются входы и символические имена и при запросах можно обращаться к ним, как к хранимым процедурам.
ну а так, SQLite - оперсорц, там всё возможно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 10.8.2010, 6:50
Сообщение #4


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


Вот, добралась до работы.

В сишном интерфейсе SQLite есть подгружаемые SQL функции.

В общем, рекомендую посмотреть вот это для информации:
http://www.sqlite.org/c3ref/create_function.html

Далее, используется примерно так:

// база
wxSQLite3Database* pdb;
.....
// объявляем объект новой функции funcLog
SQLite3DBFunc funcLog(LogErrorCheck);
// (по сути, этот объект нигде не используется и нужен только для связи имени в запросе с функцией-обработчиком)
.....
// после открытия базы
pdb->CreateFunction(_T("LOG_ERROR_CHECK"),3,funcLog);
// в параметрах:
// имя функции для запроса, количество параметров и объект регистрируемой функции
....
// функция-обработчик
void LogErrorCheck(wxSQLite3FunctionContext& context)
{
// проверяем параметры функции
         if(context.GetInt(/*[номер параметра]*/)==/*[какое-то значение]*/)    
         {
                // например, возвращаем NULL
        context.SetResultNull();
         }
        else
        {
               // например, возвращаем какое-то число
    context.SetResult(/*[какое-то значение]*/);    
        }
}

пример вызова созданной функции в запросе:
// например, так:
select LOG_ERROR_CHECK(STATE,PLD_FUNCTION,PLD_VERSION) as ERROR from LOG
// тут STATE, PLD_FUNCTION,PLD_VERSION - поля таблицы, как обычно в запросах с функциями


При выполнении запроса на каждую запись будет вызвана функция LogErrorCheck и значение, возвращаемое через context.SetResult будет подставлено вместо тега ERROR.

P.S. у меня использован wxSQLite, но с обычным SQLite то же самое будет. просто вызовы маленько по-другому будут оформляться.

Сообщение отредактировал Iron Bug - 10.8.2010, 9:31
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 10.8.2010, 11:40
Сообщение #5


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


Ради эксперимента написала тестовую реализацию только через стандартный sqlite3 интерфейс.
Если кому интересно, то вот:

Раскрывающийся текст
#include <iostream>

#include <sqlite3.h>

using namespace std;

// вызываемая функция
void foo(sqlite3_context* context,int argc,sqlite3_value** argv)
{
  if(argc!=1)
  {
      sqlite3_result_error_code(context,-1);
      return;
  }
  switch( sqlite3_value_type(argv[0]) )
  {
    case SQLITE_INTEGER: {
      long long int iVal = sqlite3_value_int64(argv[0]);
      // пускай будет умножение на десять
      iVal *= 10;

      sqlite3_result_int64(context, iVal);
      break;
    }
    default: {
      sqlite3_result_null(context);
      break;
    }
  }
}

int main()
{
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;

    // создали базу
    rc = sqlite3_open("SQLiteTestDB",&db);
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }
    // создание тестовой таблицы
    rc = sqlite3_exec(db,"create table TEST(id int)",0,0,&zErrMsg);
    if( rc!=SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }

    // создание функции
    rc = sqlite3_create_function(db,"FOO",1,SQLITE_ANY,0, foo, 0,0);
    if( rc!=SQLITE_OK ){
        fprintf(stderr, "SQL error: could not create function\n");
    }

    // положим в базу какие-то данные
    rc = sqlite3_exec(db,"insert into TEST (id) values (1)",0,0,&zErrMsg);
    if( rc!=SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    rc = sqlite3_exec(db,"insert into TEST (id) values (2)",0,0,&zErrMsg);
    if( rc!=SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }

    // вычитаем данные
    char **result;
    int nrow,ncol;
    rc = sqlite3_get_table(db,"select id,FOO(id) from TEST",
              &result,&nrow,&ncol,&zErrMsg);

       if( rc == SQLITE_OK ){
            // заголовки
            for(int i=0; i < ncol; ++i)
                cout << result[i] << "\t";
            cout << endl;
            // данные
            for(int i=1; i < nrow; ++i)
            {
                for(int j=0; j < ncol; ++j)
                {
                    if(result[i*ncol+j] != 0)
                    {
                        cout << result[i*ncol+j] << "\t";
                    }
                    else
                    {
                        cout << "NULL" << "\t";
                    }
                }
                cout << endl;
            }
       }
       sqlite3_free_table(result);

    // закрыли базу
    sqlite3_close(db);
    return 0;
}


Сообщение отредактировал Iron Bug - 10.8.2010, 11:54
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 10.8.2010, 11:54
Сообщение #6


фрилансер
******

Группа: Участник
Сообщений: 2885
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


пригодится, спасибо ) Прям мануал получился
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.8.2019, 16:22