윈도우용 sqlite 라이브러리 만들어 보기

2023. 3. 20. 19:47프로그래밍

728x90
 

저번 문서1에서 만들었던 안드로이드용 sqlite 빌드를 약간 고쳐서 윈도우용으로 만들어 보기로 한다.

데이터베이스 파일을 만들고 이를 확인 하려고 할 때, 안드로이드 기기 상에서 확인하는 방법도 있는 데, 그럴수 없을 경우에는 윈도우 용으로 하나 따로 만들어서 돌려보고 확인 한다면 좋을 것 같기도 하고,

안드로이드용으로 컴파일 해서 사용하는 방법이 오히려 복잡한 것 같아도 디버깅에는 용이할 수 있다는 생각이 들어서 그냥 한번 만들어 보기로 한다.

첨부파일에 실행 환경이랑 최종 테스트를 위한 소스를 첨부 하였다.

 

1. 안드로이드용 라이브러리 찾기

우선 다음 사이트2에서 압축파일로 다운 받아서 사용하기로 내맘대로 결정하고, 원하는 디렉토리에 풀어주고 MinGW를 실행 해 준다.

 

그리고 저번 문서에서 만들었던 컴파일 내용을 들고 와서 컴파일 해 준다. 약간 고쳐서 해야 하는 데 별 무리는 없는 것으로 보인다.

 

2. 컴파일

@gcc -Os -Wall -fPIC -Wl,--kill-at -Wno-unused-parameter -Wno-int-to-pointer-cast -Wno-maybe-uninitialized -Wno-parentheses -shared -Wl,--out-implib
,/tests/test_sqlite/FreeSQLiteEncryption-master/lib/libsqliteX.a -DSQLITE_HAS_CODEC -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA -DNO_SUPPORT_
JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL -U__APPLE__ -DHAVE_STRCHRNUL=0 -I. -I/tests/test_sqlite/FreeSQLiteEncryption-master/include -c sqlite3se
cure.c -o sqlite3secure.o ...compile
 

-Os 는 크기 최소화

-O2 는 성능 최대화

 

3. 라이브러리 빌드

gcc -shared -Wl,--out-implib,/tests/test_sqlite/FreeSQLiteEncryption-master/lib/libsqliteX.a -DSQLITE_HAS_CODEC -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTI
ONS -DGKWQ_NO_JAVA -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL -U__APPLE__ -DHAVE_STRCHRNUL=0 -o /tests/test_sqlite/FreeSQLiteEncryption
-master/lib/libsqliteX.dll sqlite3secure.o -ldl -static-libgcc -static-libstdc++
export PATH=./lib:$PATH
 

4. 테스트 코드 만들어 보기

구글에서 검색 해서 다음 사이트들에서 소스가져다가 고쳤음을 밝힌다.

로그 출력을 위한 함수3

 

sqlite C API 예제 4

- 이 예제들을 하나씩 붙여 나갔다. 고친것은 거의 없으며 위의 로그출력 부분과 DB 이름 가져오는 부분으로 손을 봤을 뿐임

Makefile 예제5 -

### Makefile 시작
CC = gcc
STRIP=strip
CFLAGS = -std=gnu99 -I../include
LIBS = -L../lib -lsqliteX -static
OBJS = sqlite_db_test.o
TARGET = bin/sqlite_test.exe
.SUFFIXES : .c .o

all : $(TARGET)
   $(TARGET): $(OBJS)
   $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
   $(STRIP) $(TARGET)
clean :
   rm -f $(OBJS) $(TARGET)

Makefile 끝 ###

 

 

5. 디렉토리 만들어 주기 및 실행

아래와 같이 데이터 베이스용과 바이너리 데이터 용 디렉토리 하나 씩을 만들어 준다.

mkdir cache_data blob
 

그리고 실행한다.

./sqlite_test
 

출력 결과 물이 아래와 같이 나오면 된다.

$ ./sqlite_test.exe
========> sqlite version - 3.7.10
3.7.10
========> special query test--result[0]
Table Cars created successfully
========> insert query test--result[0]
Table Friends created successfully
The last Id of the inserted row is 5
========> last inserted row id test--result[0]
Id = 1
Name = Audi
Price = 52642
Id = 2
Name = Mercedes
Price = 57127
Id = 3
Name = Skoda
Price = 9000
Id = 4
Name = Volvo
Price = 29000
Id = 5
Name = Bentley
Price = 350000
Id = 6
Name = Citroen
Price = 21000
Id = 7
Name = Hummer
Price = 41400
Id = 8
Name = Volkswagen
Price = 21600
========> select car test--result[0]
3: Skoda
========> select parameterized car test--result[0]
4: Volvo
========> select parameterized car test--result[0]
Table Images created successfully
========> create image table--result[0]
========> insert image--result[0]
========> retrieve image--result[0]
cid = 0
name = Id
type = INT
notnull = 0
dflt_value = NULL
pk = 0
cid = 1
name = Name
type = TEXT
notnull = 0
dflt_value = NULL
pk = 0
cid = 2
name = Price
type = INT
notnull = 0
dflt_value = NULL
pk = 0
========> retrieve meta data Cars--result[0]
name = Cars
name = Images
========> retrieve all meta data--result[0]
 

6. 암호화

암호화에 대해서 알아보자

​인터넷을 돌아다녀 봐도 잘 못찾겠네...

​여하튼 두가지 방식이 존재 하는 것으로 보이는 데

첫번째 방식은 함수를 사용해서 암호화 하는 방법이 있고

두번째 방식은 그냥 SQL 문에 담아서 암호화 하는 방법이 있다.

첫번째 방식에 대해서 open_crypt_db2 함수를 살펴보면

int open_crypt_db2(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open_v2(dbname, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n",
		sqlite3_errmsg(db));
		sqlite3_close(db);
		return 1;
	}

	//암호화 키로 데이터베이스를 암호화 한다.
	rc = sqlite3_key( db, dbname, "'secretkey'");

	if (rc != SQLITE_OK) {

		LOG_TRACE(LOG_ERROR, "Cannot encrypt database: %s\n",
		sqlite3_errmsg(db));
		sqlite3_close(db);
	}
	//그런 다음 조회 하는 것으로 ...
	char *sql = "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT);"
	"INSERT INTO Friends(Name) VALUES ('Tom');"
	"INSERT INTO Friends(Name) VALUES ('Rebecca');"
	"INSERT INTO Friends(Name) VALUES ('Jim');"
	"INSERT INTO Friends(Name) VALUES ('Roger');"
	"INSERT INTO Friends(Name) VALUES ('Robert');";

	rc = sqlite3_exec(db, sql, 0, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to create table\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
	} else {
		LOG_TRACE(LOG_INFO, "Table Friends created successfully\n");
	}

	sql = NULL;

	sql = "SELECT * FROM Friends;";

	rc = sqlite3_exec(db, sql, callback, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to select data\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);

		return 1;
	}

	sqlite3_close(db);

	return 0;
}
 

두번째 방식으로 보면

int open_crypt_db(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open_v2(dbname, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n",
		sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}

	//SQL 방식의 데이터베이스 암호화
	char *sql = "PRAGMA key = 'secretkey';";

	rc = sqlite3_exec(db, sql, 0, 0, &err_msg);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}


	sql = NULL;
	sql = "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT);"
	"INSERT INTO Friends(Name) VALUES ('Tom');"
	"INSERT INTO Friends(Name) VALUES ('Rebecca');"
	"INSERT INTO Friends(Name) VALUES ('Jim');"
	"INSERT INTO Friends(Name) VALUES ('Roger');"
	"INSERT INTO Friends(Name) VALUES ('Robert');";

	rc = sqlite3_exec(db, sql, callback, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to create table\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
	} else {
		LOG_TRACE(LOG_INFO, "Table Friends created successfully\n");
	}


	sql = NULL;

	sql = "SELECT * FROM Friends;";
	//sql = "SELECT name FROM sqlite_master WHERE type='table'";

	rc = sqlite3_exec(db, sql, callback, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to select data\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);

		return 1;
	}

	sqlite3_close(db);

	return 0;
}​
 

7. 호환성

자 그럼 무슨 말인고 하니, 윈도우용을 만들었고 안드로이드 용을 만들었는 데

두개의 데이터베이스가 호환성을 가질 수 있는 가? 에 대한 물음에 진지하게 답해 보자...

두개의 데이터베이스는 sqlite을 만든 팀은 호환성이 있다고 말한다. 그리고 실제로도

구동시켜본 결과 한개의 데이터베이스를 두개의 시스템에서 구동하여 결과를 보니 과연 호환성이 있다고 생각이 든다.

하지만! 두개의 데이터베이스를 위와 같은 코드로 암호화를 했을 때 호환성을 가지느냐? 는 문제는 어떨까

​대답은 현재까지는 호환되지 않는다 이다. 위의 코드를 사용해서 두가지 테스트를 실시 하였다.

안드로이드 시스템에서 데이터베이스 생성 -> 암호화

윈도우즈 시스템에서 데이터베이스 생성 -> 암호화

윈도우즈 시스템에서 두개의 데이터베이스 테스트

안드로이드 시스템에서 두개의 데이터베이스 테스트

둘다 실패였다.

결론은 Endian 즉, Byte Order 문제 일 것 같은 느낌이 있으나.... 소스코드를 좀 더 뜯어 보지 않으면 해결 하지 못할 정도로 어려운 문제임에 틀림없다는 것이다.​

8. 소스코드

 

부록 : 다음은 소스 전문이다.

​▶ 아래코드에서는 위의 암호호 코드가 적용되어 있지 않다.

 

윈도우용 sqlite 라이브러리 만들기

윈도우용 sqlite 라이브러리 만들어 보기 저번 문서1에서 만들었던 안드로이드용 sqlite 빌드를 약간 고쳐...

blog.naver.com

 

#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#define SQL_DB_NAME "cache_data/cache_db.sqlite3"


//LOG LEVELS
typedef enum
{
	LOG_DEFAULT,
	LOG_INFO,
	LOG_ERROR,
	LOG_DEBUG
}LOG_LEVEL;


void LOG_TRACE(LOG_LEVEL lvl, char *fmt, ... );
static int open_sqlite_db(const char *dbname);
static int callback(void *, int, char **, char **);

/* LOG_TRACE(log level, format, args ) */
void LOG_TRACE(LOG_LEVEL lvl, char *fmt, ... )
{
	va_list list;
	char *s, c;
	int i;

	if( (lvl==LOG_INFO) || (lvl==LOG_ERROR))
	{
		va_start( list, fmt );

		while(*fmt)
		{

			if ( *fmt != '%' )
				putc( *fmt, stdout );
			else
			{
				switch ( *++fmt )
				{
				case 's':
					/* set r as the next char in list (string) */
					s = va_arg( list, char * );
					printf("%s", s);
					break;

				case 'd':
					i = va_arg( list, int );
					printf("%d", i);
					break;

				case 'c':
					c = va_arg( list, int);
					printf("%c",c);
					break;

				default:
					putc( *fmt, stdout );
					break;
				}
			}
			++fmt;
		}
		va_end( list );
	}
	fflush( stdout );
}

void log_test()
{
	int i =10;
	char *string="Hello World";
	char c='a';

	LOG_TRACE(LOG_INFO, "String - %s\n", string);
	LOG_TRACE(LOG_INFO, "Integer - %d\n", i);
	LOG_TRACE(LOG_INFO, "Character - %c\n", c);

	LOG_TRACE(LOG_INFO, "\nTOTAL DATA: %s - %d - %c\n", string, i, c);

	LOG_TRACE(LOG_INFO, "Integer - %d\n", i);
}

int callback(void *NotUsed, int argc, char **argv, char **azColName) {
	NotUsed = 0;

	for (int i = 0; i < argc; i++) {
		LOG_TRACE(LOG_INFO, "%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
	}

	LOG_TRACE(LOG_INFO, "\n");

	return 0;
}
 
int insert_query_test(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);


	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;

	}

	char *sql = "DROP TABLE IF EXISTS Cars;"
	"CREATE TABLE Cars(Id INT, Name TEXT, Price INT);"
	"INSERT INTO Cars VALUES(1, 'Audi', 52642);"
	"INSERT INTO Cars VALUES(2, 'Mercedes', 57127);"
	"INSERT INTO Cars VALUES(3, 'Skoda', 9000);"
	"INSERT INTO Cars VALUES(4, 'Volvo', 29000);"
	"INSERT INTO Cars VALUES(5, 'Bentley', 350000);"
	"INSERT INTO Cars VALUES(6, 'Citroen', 21000);"
	"INSERT INTO Cars VALUES(7, 'Hummer', 41400);"
	"INSERT INTO Cars VALUES(8, 'Volkswagen', 21600);";

	rc = sqlite3_exec(db, sql, 0, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);
		return 1;
	}
	else {
		LOG_TRACE(LOG_INFO, "Table Cars created successfully\n");
	}

	sqlite3_close(db);

	return 0;
}

int last_inserted_rowid()
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(":memory:", &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}

	char *sql = "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT);"
	"INSERT INTO Friends(Name) VALUES ('Tom');"
	"INSERT INTO Friends(Name) VALUES ('Rebecca');"
	"INSERT INTO Friends(Name) VALUES ('Jim');"
	"INSERT INTO Friends(Name) VALUES ('Roger');"
	"INSERT INTO Friends(Name) VALUES ('Robert');";


	rc = sqlite3_exec(db, sql, 0, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to create table\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
	} else {
		LOG_TRACE(LOG_INFO, "Table Friends created successfully\n");
	}

	int last_id = sqlite3_last_insert_rowid(db);
	LOG_TRACE(LOG_INFO, "The last Id of the inserted row is %d\n", last_id);
	sqlite3_close(db);

	return 0;
}
 
int select_query_test(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n",
		sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}

	char *sql = "SELECT * FROM Cars";

	rc = sqlite3_exec(db, sql, callback, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to select data\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);

		return 1;
	}

	sqlite3_close(db);
	return 0;
}

int special_query_test()
{

	sqlite3 *db;
	sqlite3_stmt *res;

	int rc = sqlite3_open(":memory:", &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}

	rc = sqlite3_prepare_v2(db, "SELECT SQLITE_VERSION()", -1, &res, 0);

	if (rc != SQLITE_OK) {

		LOG_TRACE(LOG_ERROR, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		return 1;
	}

	rc = sqlite3_step(res);

	if (rc == SQLITE_ROW) {
		LOG_TRACE(LOG_INFO, "%s\n", sqlite3_column_text(res, 0));
	}

	sqlite3_finalize(res);
	sqlite3_close(db);

	return 0;
}

int select_parameterized_query_test(const char *dbname)
{

	sqlite3 *db;
	char *err_msg = 0;
	sqlite3_stmt *res;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}


	char *sql = "SELECT Id, Name FROM Cars WHERE Id = ?";

	rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);


	if (rc == SQLITE_OK) {
		sqlite3_bind_int(res, 1, 3);
	} else {
		LOG_TRACE(LOG_ERROR, "Failed to execute statement: %s\n", sqlite3_errmsg(db));
	}


	int step = sqlite3_step(res);


	if (step == SQLITE_ROW) {
		LOG_TRACE(LOG_INFO, "%s: ", sqlite3_column_text(res, 0));
		LOG_TRACE(LOG_INFO, "%s\n", sqlite3_column_text(res, 1));
	}

	sqlite3_finalize(res);

	sqlite3_close(db);

	return 0;
}
int select_named_parameterized_query_test(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;
	sqlite3_stmt *res;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
	
		return 1;
	}

	char *sql = "SELECT Id, Name FROM Cars WHERE Id = @id";

	rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);

	if (rc == SQLITE_OK) {
		int idx = sqlite3_bind_parameter_index(res, "@id");
		int value = 4;
		sqlite3_bind_int(res, idx, value);
	} else {
		LOG_TRACE(LOG_ERROR, "Failed to execute statement: %s\n", sqlite3_errmsg(db));
	}

	int step = sqlite3_step(res);

	if (step == SQLITE_ROW) {
		LOG_TRACE(LOG_INFO, "%s: ", sqlite3_column_text(res, 0));
		LOG_TRACE(LOG_INFO, "%s\n", sqlite3_column_text(res, 1));
	}

	sqlite3_finalize(res);
	sqlite3_close(db);

	return 0;
}
 
int create_image_table(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}


	char *sql = "DROP TABLE IF EXISTS Images;"
	"CREATE TABLE Images(Id INTEGER PRIMARY KEY, Data BLOB);" ;
	rc = sqlite3_exec(db, sql, 0, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);
		return 1;
	}
	else {
		LOG_TRACE(LOG_INFO, "Table Images created successfully\n");
	}

	sqlite3_close(db);

	return 0;
}
 
int insert_binary(const char* filename, const char* dbname)
{
	FILE *fp = fopen(filename, "rb");

	if (fp == NULL) {
		LOG_TRACE(LOG_ERROR, "Cannot open image file\n");
		return 1;
	}

	fseek(fp, 0, SEEK_END);

	if (ferror(fp)) {
		LOG_TRACE(LOG_ERROR, "fseek() failed\n");
		int r = fclose(fp);
		
		if (r == EOF) {
			LOG_TRACE(LOG_ERROR, "Cannot close file handler\n");
		}
		return 1;
	}

	int flen = ftell(fp);
	
	if (flen == -1) {
		perror("error occurred");
		
		int r = fclose(fp);
		if (r == EOF) {
			LOG_TRACE(LOG_ERROR, "Cannot close file handler\n");
		}

		return 1;
	}

	fseek(fp, 0, SEEK_SET);

	if (ferror(fp)) {
		LOG_TRACE(LOG_ERROR, "fseek() failed\n");
		int r = fclose(fp);
		if (r == EOF) {
			LOG_TRACE(LOG_ERROR, "Cannot close file handler\n");
		}
		return 1;
	}

	char data[flen+1];
	int size = fread(data, 1, flen, fp);

	if (ferror(fp)) {
		LOG_TRACE(LOG_ERROR, "fread() failed\n");
		int r = fclose(fp);
		if (r == EOF) {
			LOG_TRACE(LOG_ERROR, "Cannot close file handler\n");
		}
		return 1;

	}

	int r = fclose(fp);
	if (r == EOF) {
		LOG_TRACE(LOG_ERROR, "Cannot close file handler\n");
	}

	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		return 1;
	}

	sqlite3_stmt *pStmt;
	char *sql = "INSERT INTO Images(Data) VALUES(?)";

	rc = sqlite3_prepare(db, sql, -1, &pStmt, 0);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot prepare statement: %s\n", sqlite3_errmsg(db));
		return 1;
	}

	sqlite3_bind_blob(pStmt, 1, data, size, SQLITE_STATIC);
	rc = sqlite3_step(pStmt);

	if (rc != SQLITE_DONE) {
		LOG_TRACE(LOG_ERROR, "execution failed: %s", sqlite3_errmsg(db));
	}

	sqlite3_finalize(pStmt);
	sqlite3_close(db);
	return 0;
}
 
int retrieve_image(const char *outfile, const char *dbname)
{
	FILE *fp = fopen(outfile, "wb");

	if (fp == NULL) {
		LOG_TRACE(LOG_ERROR, "Cannot open image file\n");
		return 1;
	}


	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		return 1;
	}

	char *sql = "SELECT Data FROM Images WHERE Id = 1";
	sqlite3_stmt *pStmt;

	rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to prepare statement\n");
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		return 1;
	}

	rc = sqlite3_step(pStmt);

	int bytes = 0;

	if (rc == SQLITE_ROW) {
		bytes = sqlite3_column_bytes(pStmt, 0);
	}

	fwrite(sqlite3_column_blob(pStmt, 0), bytes, 1, fp);
	if (ferror(fp)) {
		LOG_TRACE(LOG_ERROR, "fwrite() failed\n");
		return 1;
	}

	int r = fclose(fp);
	if (r == EOF) {
		LOG_TRACE(LOG_ERROR, "Cannot close file handler\n");
	}

	rc = sqlite3_finalize(pStmt);
	sqlite3_close(db);
	
	return 0;

}
 
int retrieve_meta_data(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n",
		sqlite3_errmsg(db));
		sqlite3_close(db);
		return 1;
	}

	char *sql = "PRAGMA table_info(Cars)";

	rc = sqlite3_exec(db, sql, callback, 0, &err_msg);

	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to select data\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);
		return 1;
	}

	sqlite3_close(db);

	return 0;
}

int retrieve_all_meta_data(const char *dbname)
{
	sqlite3 *db;
	char *err_msg = 0;

	int rc = sqlite3_open(dbname, &db);

	if (rc != SQLITE_OK) {
		LOG_TRACE(LOG_ERROR, "Cannot open database: %s\n",
		sqlite3_errmsg(db));
		sqlite3_close(db);

		return 1;
	}


	char *sql = "SELECT name FROM sqlite_master WHERE type='table'";

	rc = sqlite3_exec(db, sql, callback, 0, &err_msg);


	if (rc != SQLITE_OK ) {
		LOG_TRACE(LOG_ERROR, "Failed to select data\n");
		LOG_TRACE(LOG_ERROR, "SQL error: %s\n", err_msg);
		sqlite3_free(err_msg);
		sqlite3_close(db);

		return 1;
	}

	sqlite3_close(db);

	return 0;
}
 
void test_sqlite()
{
	const char* filename = "blob/User-Male-icon.png";
	const char* outfilename = "blob/User-Male-icon_copy.png";

	LOG_TRACE(LOG_INFO, "========> sqlite version - %s\n", sqlite3_libversion());
	LOG_TRACE(LOG_INFO, "========> special query test--result[%d]\n", special_query_test());
	LOG_TRACE(LOG_INFO, "========> insert query test--result[%d]\n", insert_query_test(SQL_DB_NAME));
	LOG_TRACE(LOG_INFO, "========> last inserted row id test--result[%d]\n", last_inserted_rowid());
	LOG_TRACE(LOG_INFO, "========> select car test--result[%d]\n", select_query_test(SQL_DB_NAME));

	//이름없는 바인딩
	LOG_TRACE(LOG_INFO, "========> select parameterized car test--result[%d]\n", select_parameterized_query_test(SQL_DB_NAME));
	//이름이 있는 바인딩
	LOG_TRACE(LOG_INFO, "========> select parameterized car test--result[%d]\n", select_named_parameterized_query_test(SQL_DB_NAME));

	LOG_TRACE(LOG_INFO, "========> create image table--result[%d]\n", create_image_table(SQL_DB_NAME));
	LOG_TRACE(LOG_INFO, "========> insert image--result[%d]\n", insert_binary(filename, SQL_DB_NAME));
	LOG_TRACE(LOG_INFO, "========> retrieve image--result[%d]\n", retrieve_image(outfilename, SQL_DB_NAME));
	LOG_TRACE(LOG_INFO, "========> retrieve meta data Cars--result[%d]\n", retrieve_meta_data(SQL_DB_NAME));
	LOG_TRACE(LOG_INFO, "========> retrieve all meta data--result[%d]\n", retrieve_all_meta_data(SQL_DB_NAME));


	return;
}
 
int main()
{
	test_sqlite();
	/*open_sqlite_db(SQL_DB_NAME);*/
	return 1;
}
 
int open_sqlite_db(const char *dbname)
{
	int ret;
	sqlite3 *ppDb;
	char *errmsg;

	/* OPEN DATABASE */

	ret = sqlite3_open(dbname, &ppDb);

	if (ret != SQLITE_OK)
	{
		LOG_TRACE(LOG_ERROR, "OPEN ERR:%s\n", sqlite3_errmsg(ppDb));
		return -1;
	}


	sqlite3_busy_timeout(ppDb, 500);


	ret = sqlite3_exec(ppDb,
	"PRAGMA synchronous=OFF;"
	"PRAGMA count_changes=OFF;"
	"PRAGMA temp_store=memory;"
	"PRAGMA key = 'secretkey'",
	NULL, NULL, &errmsg);

	return ret;
}
 

이상.

 

 


 

728x90