crossplatform.ru

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


  Ответ в SQLite и хранимые процедуры
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
Алексей1153 Дата 10.8.2010, 11:54
  пригодится, спасибо ) Прям мануал получился
Iron Bug Дата 10.8.2010, 11:40
  Ради эксперимента написала тестовую реализацию только через стандартный 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, 6:50
  Вот, добралась до работы.

В сишном интерфейсе 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 Дата 9.8.2010, 18:52
  я завтра посмотрю на работе, как я это реализовывала. тут дома у меня нет кода.
суть в том, что там можно организовать вызов сишной процедуры. регистрируются входы и символические имена и при запросах можно обращаться к ним, как к хранимым процедурам.
ну а так, SQLite - оперсорц, там всё возможно.
DEADHUNT Дата 9.8.2010, 17:58
 
Цитата(legat @ 9.8.2010, 18:03) *
Если нет, то какими способами этот недостаток можно обойти?

написать на C++ аналог нужной хранимой процедуры.
legat Дата 9.8.2010, 17:03
  Поддерживает ли SQLite хранимые процедуры?
Если да, то как средствами Qt их вызвать?
Если нет, то какими способами этот недостаток можно обойти?
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 23.7.2019, 6:36