LPC 语言基础教程:8.2 数据库操作 efun 介绍

本文节选自《LPC语言基础教程:从零学习游戏开发》,版权归@mudren,欢迎转载,但必须注明来源(mud.ren)。

LPC 支持数据库操作,相关的外部函数包括:db_close、db_commit、db_connect、db_exec、db_fetch、db_rollback、db_status。另外还有一个 apply 方法:valid_database。

最核心的几个函数介绍如下:

名称

db_connect() - 打开一个数据库连接

语法

mixed db_connect( string host, string db );
mixed db_connect( string host, string db, string user );
mixed db_connect( string host, string db, string user, int type );

描述

创建一个新的数据库连接到 `host` 上的数据库, `db` 是要连接的数据库,如果不指定用户名 `user` 将使用驱动编译时设置的值做登录ID, `type` 用来选择数据库类型,可用值取决于驱动编译时的配置,如果不指定类型将使用编译时设置的默认数据库类型。数据库密码通过主控对象中的 valid_database() 方法设置。连接成功返回一个新的数据库连接句柄(整型),否则返回失败消息(字符串型)。

名称

db_close() - 关闭一个数据库连接

语法

int db_close( int handle );

描述

通过给定句柄关闭数据库连接。

关闭成功返回 1 ,失败返回 0 ,如果指定句柄不存在会报错。

名称

db_status() - 返回数据库连接状态

语法

string db_status( void );

描述

返回一个描述数据库当前连接状态的字符串(包括所有数据库句柄)。

名称

db_exec() - 执行一个 SQL 语句

语法

mixed db_exec( int handle, string sql_query );

描述

通过指定句柄执行 SQL 语句,如果执行成功会返回结果的行数,否则返回错误消息字符串。

名称

db_fetch() - 从数据库查询结果集中获取数据数组

语法

mixed *db_fetch( int handle, int row );

描述

从数据库查询的结果集中返回指定行的数据列数组,如果失败会返回错误消息字符串。

数据库连接安全验证由主控对象中的 apply 方法 valid_database() 负责,具体说明如下:

名称

valid_database - 保护数据库相关外部函数

语法

mixed valid_database( object caller, string func, mixed *info );

描述

每个数据库操作相关外部函数在执行之前都会调用 valid_database() 方法。如果 valid_database() 返回 0 ,数据库外部函数会执行失败,如果返回 1 ,数据库相关外部函数会尝试执行。第一个参数 `caller` 是调用数据库相关外部函数的对象,第二个参数 `func` 是准备执行的数据库外部函数名(如:db_connect() 或者 db_commit()),第三个参数 'info' (如果适用)是一个附加信息数组,目前被用于 efun::db_connect() 和 efun::db_exec(),前一个函数中 `info` 的格式是 ({ string database, string host, string user }) ,后一个函数中 `info` 的格式是 ({ string sql_query }) 。

如果禁止执行数据库外部函数,valid_database() 返回 0 。但对 efun::db_connect() 应该返回连接数据库的密码,或者返回 1

我们在 /cmds/test/ 目录下新建示例文件 8.2.1.c 演示数据库,具体代码如下:

int main(object me, string arg)
{
#ifdef __PACKAGE_DB__
#ifndef __USE_SQLITE3__
    debug("当前驱动不支持SQLITE3数据库。");
#else
    mixed db, err;

    if (!arg)
        return notify_fail(db_status());

    if (arg == "db_connect")
    {
        db = db_connect("", "/tmp/sqlite.db", "", __USE_SQLITE3__);
        if (stringp(db)) /* error */
            debug("数据库连接失败:" + db);
        else
            debug("数据库连接成功:" + db);
    }
    else
    {
        err = catch(db = db_close(atoi(arg)));
        if (stringp(err)) /* error */
            debug("数据库关闭出错:" + err);
        else if (db)
            debug("数据库关闭成功!");
        else
            debug("数据库关闭失败!");
    }
#endif
#else
    debug("当前驱动不支持数据库。");
#endif
    return 1;
}

再新建 8.2.2.c,示例代码如下:

int main(object me, string arg)
{
#ifdef __PACKAGE_DB__
#ifndef __USE_SQLITE3__
    debug("当前驱动不支持SQLITE3数据库。");
#else
    mixed db, rows, *res;

    db = db_connect("", "/tmp/sqlite.db", "", __USE_SQLITE3__);
    if (stringp(db)) /* error */
        debug("数据库连接失败:" + db);
    else
    {
        rows = db_exec(db, "DROP TABLE IF EXISTS demo");
        rows = db_exec(db, "create table IF NOT EXISTS demo(name varchar(10), value bigint);");
        rows = db_exec(db, "insert into demo values('hello!', 10);");
        rows = db_exec(db, "insert into demo values('goodbye', 20);");
        rows = db_exec(db, "insert into demo values('largeint', 9223372036854775807);");
        rows = db_exec(db, "select * from demo;");

        for (int i = 0; i <= rows; i++)
        {
            res = db_fetch(db, i);
            // printf("%O\n", res);
            debug(res[0] + " " + res[1]);
        }

        db_close(db);
    }
#endif
#else
    debug("当前驱动不支持数据库。");
#endif
    return 1;
}

我们输入指令可体验数据库连接和查询操作,这里使用的是SQLite3数据库测试,需要你编译驱动时开启支持。

提示:本项目已经配置了valid_database 方法允许数据库操作,代码如下:

// database
mixed valid_database(object caller, string func, mixed *info)
{
    if (func == "connect")
        return PASSWD; // mysql数据库密码
    else
        return 1;
}

如果你是在自己的项目中测试注意配置此方法,因为默认不允许操作数据库,连接数据库会报如下错误:

  error("Database security violation attempted\n");

如果你不想自己写原生的SQL增删改查,推荐使用mudcore框架中提供的DB接口,具体使用参考:

京ICP备13031296号-4