sqlite

1、概述html

  Sqlite 是一種輕量級的跨平臺的開源數據庫,設計目標是爲嵌入式設備服務,它的處理速度比 Mysql、PostgreSQL 都快,而佔用只有幾百KB左右。除了支持基本的SQL語句,還支持事務處理。mysql

 

2、下載安裝redis

  從官網 http://www.sqlite.org/download.html 能夠下載源碼包或自動編譯包,若是在 Linux 下使用,能夠下載 sqlite-autoconf-3080500.tar.gz ,解壓後 ./configure && make && make install 便可;也能夠下載源碼包,裏面只包含四個代碼文件,好比在 cocos2d-x 項目中,就能夠下載這個包添加進去便可使用。sql

 

3、簡單 Demo數據庫

#include "sqlite3.h"
#include <string>
#include <stdio.h>

using namespace std;

int main()
{
    sqlite3 *pdb = NULL;

    std::string path = "/root/test.db";
    int result = sqlite3_open(path.c_str(), &pdb);
    if (result == SQLITE_OK)
    {
        printf("connect mysqlite.db3 ok!");
        result = sqlite3_exec(pdb, "create table if not exists pet(id integer primary key autoincrement,name text,age integer)", NULL, NULL, NULL);
        if (result == SQLITE_OK)
        {
            printf("create table pet ok!");
            result = sqlite3_exec(pdb, "insert into pet(name,age) values('pet01','3');", NULL, NULL, NULL);
            if (result == SQLITE_OK)
            {
                printf("insert table pet ok!");
                char **ds;
                int row, column;
                result = sqlite3_get_table(pdb, "select * from pet", &ds, &row, &column, NULL);
                printf("row=%d,column=%d", row, column);
                for (int i = 0; i < row; i++)
                {
                    std::string str = "";
                    for (int j = 0; j < column; j++)
                    {
                        str += ds[i*column + j];
                        str += "  ";
                    }
                    printf("%s", str.c_str());
                }
            }
            else
            {
                printf("insert table pet faild!");
            }
        }
        else
        {
            printf("create table pet faild! result:%d",result);
        }
    }
    else
    {
        printf("open database failed,  number%d", result);
    }
}

編譯使用:g++ main.cpp -o main -lsqlite3express

 

4、相關工具windows

  Linux 下能夠直接使用 sqlite3 命令行工具來操做 sqlite3 數據庫文件,如 sqlite3 test.db;Windows 下可使用 SqliteBrowser 圖形化工具。xcode

 

5、操做函數封裝app

  默認提供的C版API寫起來很麻煩,網上有各類語言版本的封裝,這裏推薦一個C++版本的:http://www.adp-gmbh.ch/sqlite/wrapper.htmlide

  在 Linux 或其它非 Windows 環境下使用時,請刪除 SQLiteWrapper.cpp 文件中的 #include <windows.h>,而後把全部使用 ::MessageBox 進行的日誌輸出改爲相應平臺的日誌輸出函數便可。另外,此版本存在內存泄露,沒有任何地方調用 sqlite3_close 函數,這裏咱們手動在 SQLiteWrapper.h 文件中添加一個 bool Close(); 聲明,而後在 SQLiteWrapper.cpp 文件中加上:

bool SQLiteWrapper::Close() {
    if (db_)
    {
        if (sqlite3_close(db_) != SQLITE_OK) {
            return false;
        }
    }
    return true;
}

 

這裏備份一下 cocos2d-x 下的修改後文件,方便之後直接使用:

/*
SQLiteWrapper.cpp

Copyright (C) 2004 René Nyffenegger

This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.

3. This notice may not be removed or altered from any source distribution.

René Nyffenegger rene.nyffenegger@adp-gmbh.ch

*/

#include "SQLiteWrapper.h"
// TODO: raus
//#include <windows.h>
#include "cocos2d.h"
USING_NS_CC;

SQLiteWrapper::SQLiteWrapper() : db_(0) {
}

bool SQLiteWrapper::Open(std::string const& db_file) {
    if (sqlite3_open(db_file.c_str(), &db_) != SQLITE_OK) {
        return false;
    }
    return true;
}

bool SQLiteWrapper::Close() {
    if (db_)
    {
        if (sqlite3_close(db_) != SQLITE_OK) {
            return false;
        }
    }
    return true;
}

bool SQLiteWrapper::SelectStmt(std::string const& stmt, ResultTable& res) {
    char *errmsg;
    int   ret;

    res.reset();

    ret = sqlite3_exec(db_, stmt.c_str(), SelectCallback, static_cast<void*> (&res), &errmsg);

    if (ret != SQLITE_OK) {
        return false;
    }
    return true;
    //  if (ret != SQLITE_OK) {
    //    std::cout << stmt << " [" << errmsg << "]" << std::endl;
    //  }
}

// TODO parameter p_col_names
int SQLiteWrapper::SelectCallback(void *p_data, int num_fields, char **p_fields, char** p_col_names) {
    ResultTable* res = reinterpret_cast<ResultTable*>(p_data);

    ResultRecord record;

#ifdef SQLITE_WRAPPER_REPORT_COLUMN_NAMES
    // Hubert Castelain: column names in the first row of res if res is empty

    if (res->records_.size() == 0) {
        ResultRecord col_names;

        for (int i = 0; i < num_fields; i++) {
            if (p_fields[i]) col_names.fields_.push_back(p_col_names[i]);
            else
                col_names.fields_.push_back("(null)"); // or what else ?
        }
        res->records_.push_back(col_names);
    }
#endif

    for (int i = 0; i < num_fields; i++) {
        // Hubert Castelain: special treatment if null
        if (p_fields[i]) record.fields_.push_back(p_fields[i]);
        else             record.fields_.push_back("<null>");
    }

    res->records_.push_back(record);

    return 0;
}

SQLiteStatement* SQLiteWrapper::Statement(std::string const& statement) {
    SQLiteStatement* stmt;
    try {
        stmt = new SQLiteStatement(statement, db_);
        return stmt;
    }
    catch (const char* e) {
        return 0;
    }
}

SQLiteStatement::SQLiteStatement(std::string const& statement, sqlite3* db) {
    if (sqlite3_prepare(
        db,
        statement.c_str(),  // stmt
        -1,                  // If than zero, then stmt is read up to the first nul terminator
        &stmt_,
        0                   // Pointer to unused portion of stmt
        )
        != SQLITE_OK) {
        throw sqlite3_errmsg(db);
    }

    if (!stmt_) {
        throw "stmt_ is 0";
    }
}

SQLiteStatement::~SQLiteStatement() {
    // Hubert Castelain 28/8/2005
    // Prevent the database remaining locked after some statement.
    // syntax: int sqlite3_finalize(sqlite3_stmt *pStmt);
    if (stmt_) sqlite3_finalize(stmt_);
}

SQLiteStatement::SQLiteStatement() :
stmt_(0)
{
}

bool SQLiteStatement::Bind(int pos_zero_indexed, std::string const& value) {
    if (sqlite3_bind_text(
        stmt_,
        pos_zero_indexed + 1,  // Index of wildcard
        value.c_str(),
        value.length(),      // length of text
        SQLITE_TRANSIENT     // SQLITE_TRANSIENT: SQLite makes its own copy
        )
        != SQLITE_OK) {
        return false;
    }
    return true;
}

bool SQLiteStatement::Bind(int pos_zero_indexed, double value) {
    if (sqlite3_bind_double(
        stmt_,
        pos_zero_indexed + 1,  // Index of wildcard
        value
        )
        != SQLITE_OK) {
        return false;
    }
    return true;
}

bool SQLiteStatement::Bind(int pos_zero_indexed, int value) {
    if (sqlite3_bind_int(
        stmt_,
        pos_zero_indexed + 1,  // Index of wildcard
        value
        )
        != SQLITE_OK) {
        return false;
    }
    return true;
}

bool SQLiteStatement::BindNull(int pos_zero_indexed) {
    if (sqlite3_bind_null(
        stmt_,
        pos_zero_indexed + 1  // Index of wildcard
        )
        != SQLITE_OK) {
        return false;
    }
    return true;
}

bool SQLiteStatement::Execute() {
    int rc = sqlite3_step(stmt_);
    if (rc == SQLITE_BUSY) {
        //::MessageBox(0, "SQLITE_BUSY", 0, 0);
        CCLog("%s","SQLITE_BUSY");
        return false;
    }
    if (rc == SQLITE_ERROR) {
        //::MessageBox(0, "SQLITE_ERROR", 0, 0);
        CCLog("%s", "SQLITE_ERROR");
        return false;
    }
    if (rc == SQLITE_MISUSE) {
        //::MessageBox(0, "SQLITE_ERROR", 0, 0);
        CCLog("%s", "SQLITE_ERROR");
        return false;
    }
    if (rc != SQLITE_DONE) {
        //sqlite3_reset(stmt_);
        return false;
    }
    sqlite3_reset(stmt_);
    return true;
}

SQLiteStatement::dataType SQLiteStatement::DataType(int pos_zero_indexed) {
    return dataType(sqlite3_column_type(stmt_, pos_zero_indexed));
}

int SQLiteStatement::ValueInt(int pos_zero_indexed) {
    return sqlite3_column_int(stmt_, pos_zero_indexed);
}

std::string SQLiteStatement::ValueString(int pos_zero_indexed) {
    return std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt_, pos_zero_indexed)));
}

bool SQLiteStatement::RestartSelect() {
    sqlite3_reset(stmt_);
    return true;
}

bool SQLiteStatement::Reset() {
    int rc = sqlite3_step(stmt_);

    sqlite3_reset(stmt_);

    if (rc == SQLITE_ROW) return true;
    return false;
}

bool SQLiteStatement::NextRow() {
    int rc = sqlite3_step(stmt_);

    if (rc == SQLITE_ROW) {
        return true;
    }
    if (rc == SQLITE_DONE) {
        sqlite3_reset(stmt_);
        return false;
    }
    else if (rc == SQLITE_MISUSE) {
        //::MessageBox(0, "SQLiteStatement::NextRow SQLITE_MISUSE", 0, 0);
        CCLog("%s", "SQLiteStatement::NextRow SQLITE_MISUSE");
    }
    else if (rc == SQLITE_BUSY) {
        //::MessageBox(0, "SQLiteStatement::NextRow SQLITE_BUSY", 0, 0);
        CCLog("%s", "SQLiteStatement::NextRow SQLITE_BUSY");
    }
    else if (rc == SQLITE_ERROR) {
        //::MessageBox(0, "SQLiteStatement::NextRow SQLITE_ERROR", 0, 0);
        CCLog("%s", "SQLiteStatement::NextRow SQLITE_ERROR");
    }
    return false;
}

bool SQLiteWrapper::DirectStatement(std::string const& stmt) {
    char *errmsg;
    int   ret;

    ret = sqlite3_exec(db_, stmt.c_str(), 0, 0, &errmsg);

    if (ret != SQLITE_OK) {
        return false;
    }
    return true;

    //if(ret != SQLITE_OK) {
    //  std::cout << stmt << " [" << errmsg << "]" << std::endl;
    //}
}

std::string SQLiteWrapper::LastError() {
    return sqlite3_errmsg(db_);
}

bool SQLiteWrapper::Begin() {
    return DirectStatement("begin");
}

bool SQLiteWrapper::Commit() {
    return DirectStatement("commit");
}

bool SQLiteWrapper::Rollback() {
    return DirectStatement("rollback");
}
View Code

 

  使用方法以下:

#include "SQLiteWrapper.h"
#include <stdio.h>

int main()
{
    SQLiteWrapper sqlite;
    if (sqlite.Open("SQLiteWrapper.db")) {
        printf("%s", "SQLiteWrapper.db created or opened");
    }
    else {
        printf("%s", "couldn't open SQLiteWrapper.db");
    }
    if (sqlite.DirectStatement("create table if not exists foo(id integer primary key autoincrement,name text,age integer)")) {
        printf("%s", "table foo created");
    }
    else {
        printf("%s", "Couldn't create table foo");
    }
    if (sqlite.DirectStatement("insert into foo(name,age) values('2', 3);")) {
        printf("%s", "values (1,2) into foo inserted");
    }
    else {
        printf("%s", "Couldn't insert into foo");
    }
    sqlite.Close();
}

 

 

6、加密

  默認 sqlite3 是不須要用戶名密碼的,並且內置沒有加密功能。但因爲其是開源的,能夠手動添加加密方案,也可使用 wxsqlite3 這個開源的加密版 sqlite3 ,它使用 AES 加密方案。

  下載地址:http://wxcode.sourceforge.net/components/wxsqlite3/

  wxsqlite3 屬於 wxWidgets ,須要先 yum install wxGTK-devel ,不然沒法正確 ./configure ,會提示 wx-config 找不到。

相關文章
相關標籤/搜索