SQL Anywhere 是一个轻量级、自管理、功能完备的关系型数据库,它提供了企业级数据库的所有特性,但可以在普通硬件上运行,且管理成本极低。此外,SQL Anywhere 提供了强大的、高性能的双向同步功能,允许轻松地将 SQL Anywhere 数据库应用与现有的企业数据中心集成。
本文将使用流行的PHP博客应用 Wordpress 作为示例,展示如何构建一个 SQL Anywhere 插件,该插件可以插入到标准的 Wordpress 安装中,无需对 Wordpress 代码进行任何其他更改,即可使用 SQL Anywhere。本文假设已经安装并运行了支持 PHP 的 Web 服务器,并且在机器上安装了 SQL Anywhere。在设置中,使用了 Apache 2、PHP 5、Wordpress 2.3.3 和 SQL Anywhere 10,并在 Windows 和 Linux 上测试了解决方案。
首先,从 Wordpress 的 wp-admin 文件夹中复制 wp-db.php 文件到 wp-content\db.php 文件。这个文件名和位置很重要,因为当访问站点时,Wordpress 软件会寻找这个文件,如果它存在,它将使用它而不是默认的 wp-db.php 文件。这就是允许为 Wordpress 插入自己的数据库访问层的原因。现在,需要修改这个文件,使其能够与 SQL Anywhere 一起工作。
SQL AnywherePHP驱动支持类似于 MySQL 的 API,因此通过快速搜索和替换 mysql_ 为 sqlanywhere_ 完成了大部分迁移工作。例如,mysql_connect() 变为 sqlanywhere_connect()。MySQL 和 SQL Anywhere 的连接字符串格式不同,但两者都使用相同的基本数据(用户、密码、服务器位置、数据库)。转换连接字符串是直接的:
// MySQL 连接
$this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword);
// SQL Anywhere 连接
$connstr=
"eng=" . $dbhost . ";uid=" . $dbuser . ";pwd=" .
$dbpassword . ";dbn=" . $dbname . ";links=shmem,tcpip";
$this->dbh = @sqlanywhere_connect($connstr);
在理想情况下,这就是需要做的一切。然而,在开始写博客之前,还需要进行一些更改。首先是将数据库架构迁移到 SQL Anywhere 格式。这可以通过使用 SQL Anywhere 迁移向导轻松完成。
为了构建一个更通用的解决方案,以便可以在标准 Wordpress 安装中无缝使用 SQL Anywhere,并且任何人都可以在 Wordpress 应用程序中创建新的 Wordpress 博客,需要做更多的工作来使博客创建工作。主要更改是替换 Wordpress 的 wp_install() 函数。对于 SQL Anywhere,创建了现有 wp_install() 函数的克隆,并添加了 2 个函数并从 wp_install 中调用:
function wp_install($blog_title, $user_name, $user_email, $public, $meta='') {
global $wp_rewrite, $wpdb;
wp_cache_flush();
// 重置架构信息
define_sa_schema();
make_db_current_silent();
create_sa_functions();
...
}
define_sa_schema() 过程基本上重新定义了全局变量 $wp_queries,以使用 SQL Anywhere 语法创建 Wordpress 架构表,而不是默认的 MySQL 语法。对于该函数的完整列表,请参见此处。create_sa_functions() 过程创建了一些在 SQL Anywhere 中不存在的内置用户定义函数。SQL Anywhere 支持这些函数的功能,所以简单地将它们作为 UDF 添加,名称相同,并映射到 SQL Anywhere 功能。
function create_sa_functions() {
global $wpdb;
$wpdb->query( "
IF NOT EXISTS( select * from sysprocedure where proc_name = 'MD5' ) THEN
CREATE FUNCTION MD5( str varchar(255) )
RETURNS binary(32)
BEGIN
return HASH( str, 'MD5' );
END;
END IF;");
...
}
此时,可以指向 Wordpress 主页,并成功创建一个新的空博客。现在已经有了新的博客,为了实际创建/查看博客条目并使用其他 Wordpress 博客管理工具,必须修改 MySQL 特定的语法以被 SQL Anywhere 接受。同样,最简单的方法是遍历 Wordpress 安装文件并更改所有不正确的语法。然而,为了一个更通用的解决方案,重写 db.php 文件中的查询允许更容易地在新的 Wordpress 安装中安装 SQL Anywhere 作为 DBMS,也使得 Wordpress 软件的维护和升级更加容易。
幸运的是,问题是一个直接的解决方案,因为 SQL Anywhere 支持 Wordpress 使用的所有 MySQL 功能。然而,SQL Anywhere 使用不同的语法(SQL Anywhere 在大多数情况下遵循 ANSI,并且在没有 ANSI 规范的 SQL 构造中,它更接近 Microsoft SQL Server 语法而不是 MySQL 语法)。所以需要找到一种方法来映射 db.php 文件中的语法。进入搜索和替换以及正则表达式。映射语法的最简单方法是构建一个 "重写" 函数,在执行任何查询之前调用它。
// 查找 LIMIT 子句整数参数并替换为 TOP N START AT m
// MySQL 语法为 LIMIT 是:
// LIMIT {[offset,] row_count | row_count OFFSET offset}]
// 注意 LIMIT 子句在查询的末尾
// 模式是 LIMIT 后跟一个整数,可能
// 后跟一个逗号和另一个整数
$pattern = "/LIMIT\s*(\d+)((\s*,?\s*)(\d+)*)/i";
$matched = preg_match( $pattern, $query, $limitmatches );
if( $matched == 1 ) {
// 移除 LIMIT 语句,将偏移量 0 替换为 1
$query = preg_replace( $pattern, '', $query);
if( count( $limitmatches ) == 5 ) {
if( $limitmatches[1] == '0' ) {
$limitmatches[1] = '1';
}
$replacement = 'SELECT TOP '.$limitmatches[4].' START AT '.$limitmatches[1].' ';
} else {
$replacement = 'SELECT TOP '.$limitmatches[1].' ';
}
$query = preg_replace( '/^\s*SELECT\s*/i', $replacement, $query );
}