一、PHP pdo方式连接PostgreSQL数据库
function pdo_query_postgresql($sql)
{
$num_args = func_num_args();
$args = func_get_args(); //获得传入的所有参数的数组
$args = array_slice($args, 1, --$num_args);
global $POSTGREDB_HOST, $POSTGREDB_PORT, $POSTGREDB_NAME, $POSTGREDB_USER, $POSTGREDB_PASS, $postgre_dbh, $OJ_SAE, $OJ_TEMPLATE;
try {
if (!$postgre_dbh) {
if (isset($OJ_SAE) && $OJ_SAE) {
$OJ_DATA = "saestor://data/";
// for sae.sina.com.cn
$DB_NAME = SAE_POSTGRE_DB;
$postgre_dbh = new PDO("pgsql:host=" . SAE_POSTGRE_HOST_M . ';dbname=' . SAE_POSTGRE_DB, SAE_POSTGRE_USER, SAE_POSTGRE_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8"));
} else {
$postgre_dbh = new PDO("pgsql:host=" . $POSTGREDB_HOST . ';port=' . $POSTGREDB_PORT . ';dbname=' . $POSTGREDB_NAME, $POSTGREDB_USER, $POSTGREDB_PASS, array(PDO::ATTR_PERSISTENT => false));
}
}
$postgre_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $postgre_dbh->query($sql);
$result = array();
if (stripos($sql, "select") === 0) {
$result = $sth->fetchAll(PDO::FETCH_NUM);
} else if (stripos($sql, "insert") === 0) {
$result = $postgre_dbh->lastInsertId();
} else {
$result = $sth->rowCount();
}
$sth->closeCursor();
return $result;
} catch (PDOException $e) {
$result = array();
if (stristr($e->getMessage(), "Access denied")){
$view_errors = array("Database account/password fail, please check db_info");
$exam_error = array("数据库账户密码错误,请联系系统管理员!");
array_push($result, $view_errors);
array_push($result, $exam_error);
} else {
if ($postgre_dbh != null){
$postgre_errorinfo = $postgre_dbh->errorInfo();
if ($postgre_errorinfo != null){
$db_error = extractErrorInfo($postgre_errorinfo);
array_push($result, $db_error);
}
}
$view_errors = array("SQL Exception,".$e->getMessage()."Please check your sql!");
$exam_error = array("请检查SQL语句!");
array_push($result, $view_errors);
array_push($result, $exam_error);
}
return $result;
} catch (Error $error){
$result = array();
if (stristr($error->getMessage(), "Access denied")){
if ($postgre_dbh != null){
$postgre_errorinfo = $postgre_dbh->errorInfo();
if ($postgre_errorinfo != null){
$db_error = extractErrorInfo($postgre_dbh->errorInfo());
array_push($result, $db_error);
}
}
$view_errors = array("Database account/password fail, please check db_info");
$exam_error = array("数据库账户密码错误,请联系系统管理员!");
array_push($result, $view_errors);
array_push($result, $exam_error);
} else {
if ($postgre_dbh != null){
$postgre_errorinfo = $postgre_dbh->errorInfo();
if ($postgre_errorinfo != null){
$db_error = extractErrorInfo($postgre_dbh->errorInfo());
array_push($result, $db_error);
}
}
$view_errors = array("SQL Error,".$error->getMessage()."Please check your sql!");
$exam_error = array("请检查SQL语句!");
array_push($result, $view_errors);
array_push($result, $exam_error);
}
return $result;
}
}
二、连接时发现如下报错
Unable to connect to PostgreSQL server: SCRAM authentication requires libpq version 10 or above in
三、解决办法
参考文章 https://www.douban.com/note/790907337/
中关于R语言连接PostgreSQL的错误,猜测报错原因应该一致。
以下内容来内上面链接中的原文:
之后,猜测问题发生的原因在于, PostgreSQL10 及以后的版本使用 SCRAM-SHA-256 方法取代了 md5 方法进行密码身份验证,而 RPostgreSQL包 (RPostgre包 也一样) 只支持后者、不支持前者。所以,一个简单的解决方法就是把 PostgreSQL 的密码验证方法调回 md5。
解决过程涉及到两个参数文件: postgresql.conf 和 pg_hba.conf,均在 PostgreSQL 的安装目录下。两个文件的具体作用可参考第二篇文章。
具体操作:
pg_hba.conf 中,末尾处类似
local all all scram-sha-256
的,其中的 scram-sha-256 全部改为 md5 即可;
postgresql.conf 中:
password_encryption = scram-sha-256 # md5 or scram-sha-256
改为:
password_encryption = md5 # md5 or scram-sha-256
在完成修改后,重启 PostgreSQL 。此时,新建的用户及其所有的数据库便改为 md5 密码验证方式,可以通过 RPostgreSQL包 正常连接到R;而在此之前建立的使用 scram-sha-256 方法的用户及其数据库则不受影响,依然使用原方法进行验证,因此似乎也无法通过 RPostgreSQL包 连接到R,也许只能换 PostgreSQL10 之前的版本或等待 RPostgreSQL包 更新了。
因此,在这里,我们的比较可操作的解决办法也是有两个:
1.升级libpq.dll的版本至9.6及以上版本
2.修改PostgreSQL的密码验证方式为md5
其实既然是版本问题,那么还有第三个办法,那就是降低PostgreSQL的版本。不过可能一般不会这么做。