xsample.cpp
| Код | #include <stdio.h> #include <windows.h>
/* Конечно SQLite можно загрузить из DLL или же Link Lib(?). */ #define SQLITEDLL
#ifdef SQLITEDLL
#define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_ROW 100 /* sqlite_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite_step() has finished executing */
typedef struct sqlite_vm sqlite_vm; typedef struct sqlite sqlite;
typedef int (*sqlite_callback)(void*,int,char**, char**);
typedef int (__cdecl * sqlite_exec_dll)( sqlite*, /* An open database */ const char *sql, /* SQL to be executed */ sqlite_callback, /* Callback function */ void *, /* 1st argument to callback function */ char **errmsg /* Error msg written here */ ); typedef sqlite * (__cdecl * sqlite_open_dll)( const char *filename, int mode, char **errmsg
);
typedef int (__cdecl * sqlite_compile_dll)( sqlite *db, /* The open database */ const char *zSql, /* SQL statement to be compiled */ const char **pzTail, /* OUT: uncompiled tail of zSql */ sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */ char **pzErrmsg /* OUT: Error message. */ );
typedef int (__cdecl * sqlite_step_dll)( sqlite_vm *pVm, /* The virtual machine to execute */ int *pN, /* OUT: Number of columns in result */ const char ***pazValue, /* OUT: Column data */ const char ***pazColName /* OUT: Column names and datatypes */ );
typedef int (__cdecl * sqlite_finalize_dll)( sqlite_vm *pVm, /* The virtual machine to be finalized */ char **pzErrMsg /* OUT: Error message */ );
typedef void (__cdecl * sqlite_close_dll)( sqlite *db ); sqlite_exec_dll sqlite_exec; sqlite_open_dll sqlite_open; sqlite_compile_dll sqlite_compile; sqlite_step_dll sqlite_step; sqlite_finalize_dll sqlite_finalize; sqlite_close_dll sqlite_close; HINSTANCE SQLiteDLL; #else
#include "sqlite.h" #endif
int myCallback(void*,int,char**, char**); int init(); void finish();
int main() {
/*это собственно указатель на БД. Таких может быть несколько в программе, если понадобится работать с несколькими файлами. */ sqlite *db;
// Мессага, которая обяснит ошибку, если таковая произойдёт char *zErrMsg = 0;
//Error code int rc; if( init()!=0) { printf("DLL's not loaded "); return 1; } /*arg1: Моя_БД.db есть файл БД. Если его несуществует, SQLite сама его создаст. arg2:Mode 0= Открыть файл read/write, 1 read only. Обьяснение простое: Если файл открыт на read/write никакой другой процесс ОС не сможет в него писать. Соответственно открываем read only если нам нужно только селектировать данные, но не изменять БД и оставляем другому процессу возможность изменять БД. Но в нашем случае (как и в большинстве других)никакие другие процессы не будут испльзовать этот файл, так что 0 нас вполне устроит. arg3: Сообщение об ошибке. Его можно распечатать, но только если возвращённый db==NULL.
../Где_Угодно/Моя_БД.db
*/ db = sqlite_open("my.db", 0, &zErrMsg);
/* Если было невозможно создать файлик то db естественно NULL, a zErrMsg сообщит, что именно случилось. */ if( db==0 ) { printf( "Can't open database: %s\n", zErrMsg); return 1; } /* Всё в порядке, можно работать!
В SQLite существует два способа получения результата БД.
1. exec/callback Функция callback будет вызываться SQLite с каждой строкой от ResultSet'a Чем то похоже Listener на в JAVA
2. compile/step/finalize в этом случае можно забирать ResultSet строка за строкой */ /*
рассмотрим sqlite_exec
arg1: Наша БД arg2: SQL statement arg3: Функция callback (Здесь нам не нужна). arg4: Аргумент, который будет передаваться в функцию callback. Например вектор, в который мы хотим добавлять результат, или вообще указатель на какой нибудь обьект (Здесь нам не нужeн). arg5: Сообщение об ошибке. Его можно распечатать, но только если возвращённый rc!=0.
Накидаем табличку */ rc=sqlite_exec(db, "create table test(num integer,name string);", NULL, NULL, &zErrMsg);
/* if(rc!=SQLITE_OK) { printf( "%s\n", zErrMsg); return 1; } */ /* При импорте данных очень важно начать с begin иначе БД будет тормозить. Обьяснение: Все записи будут осуществляться в памяти и только с commit писаться на диск. После этого SQLite проверит, всё ли записано правильно. Без beginn'a это будет осуществляться при каждой записи */ rc=sqlite_exec(db, "begin;", NULL, NULL, &zErrMsg);
for(int i=0;i<10;i++) { /* На оригинальность не претендую :) */ char sqlText[200]; sprintf(sqlText,"insert into test values(%i,'name_%i');",i,i);
rc=sqlite_exec(db, sqlText, NULL, NULL, &zErrMsg); if(rc!=SQLITE_OK) { printf( "%s\n", zErrMsg); break; } } /* произведём селект способом 1: */ printf("\n exec/callback \n"); rc=sqlite_exec(db, "select * from test;", myCallback, NULL, &zErrMsg);
if(rc!=SQLITE_OK) { printf( "%s\n", zErrMsg); return 1; }
/* произведём SELECT способом 2: */ const char *sqlText="select * from test;"; /* ppVm непрозрачная структура виртуальной машины. В некоторых случаях я исползьовал несколько таких машин, чтобы опрашивать несколько разных ResultSet'ов. */ sqlite_vm *ppVm;
/* рассмотрим sqlite_compile
arg1:Наша БД arg2:SQL statement arg3:Указатель на Statement. не примомню , можно/нужно ли это как то использовать. В нашем случае нет. arg4:Виртуальная машинка. arg5:Сообщение об ошибке (SQLSyntax). */ rc=sqlite_compile(db, sqlText,&sqlText,&ppVm,&zErrMsg); if(rc!=SQLITE_OK) { printf( "%s\n", zErrMsg); return 1; }
printf("\n compile/step/finalize \n"); int columns; const char **pazValue; const char **pazColName; /* рассмотрим sqlite_step arg1:Виртуальная машинка arg2:Эта переменная соовщит нам, сколько колонок в строчке результата. arg3:data arg4:Имена колонок и типы данных
*/ rc=sqlite_step(ppVm,&columns,&pazValue,&pazColName); while(rc!=SQLITE_DONE) {
for(int i=0;i<columns;i++) { /* Типы данных хранятся в pazColName с отступом в columns. */ printf("%s(%s)=%s |",pazColName[i],pazColName[i+columns],pazValue[i]); }
printf("\n"); rc=sqlite_step(ppVm,&columns,&pazValue,&pazColName); }
/*destructor Виртуальной машины*/ rc=sqlite_finalize(ppVm,&zErrMsg);
rc=sqlite_exec(db, "commit;", NULL, NULL, &zErrMsg); sqlite_close(db); return 0; }
static int myCallback(void *NotUsed, int columns, char **pazValue, char **pazColName){ int i; for(i=0; i<columns; i++){
printf("%s(%s)=%s |",pazColName[i],pazColName[i+columns],pazValue[i] ? pazValue[i]:"NULL"); } printf("\n"); finish(); return 0; }
int init() { #ifdef SQLITEDLL HINSTANCE SQLiteDLL = LoadLibrary("sqlite.dll");
sqlite_exec=((sqlite_exec_dll) GetProcAddress (SQLiteDLL, "sqlite_exec")); sqlite_open=((sqlite_open_dll) GetProcAddress (SQLiteDLL, "sqlite_open")); sqlite_compile=((sqlite_compile_dll) GetProcAddress (SQLiteDLL, "sqlite_compile")); sqlite_step=((sqlite_step_dll) GetProcAddress (SQLiteDLL, "sqlite_step")); sqlite_finalize=((sqlite_finalize_dll) GetProcAddress (SQLiteDLL, "sqlite_finalize")); sqlite_close=((sqlite_close_dll) GetProcAddress (SQLiteDLL, "sqlite_close")); return SQLiteDLL==NULL ? 1:0;
#endif return 0; }
void finish() { #ifdef SQLITEDLL if(SQLiteDLL!=NULL) FreeLibrary(SQLiteDLL); #endif } | |