2025-12-04

NaviServer: Database

NaviServer 目前提供了二種資料庫介面, nsdb 與 後來擴充一些功能的 nsdbi。 nsdb 為 NaviServer 的內建模組(只是需要自行設定載入模組),而 nsdbi 需要使用者自己編譯並且加入到 NaviServer。

注意:如果想要使用 OpenACS 並且資料庫使用 PostgreSQL,那麼必須安裝 nsdbpg 模組。 下面使用 PostgreSQL 測試 nsdb 以及 nsdbpg 模組。使用者需要編譯 nsdbpg 模組並且加入到 NaviServer。 如果要自己編譯 nsdbpg 模組,注意其 Makefile 中 NAVISERVER 所設定的位置, 以及 dbpg.h 中 pg_config.h 和 libpq-fe.h 標頭檔的位置(openSUSE 安裝的位置放在 /usr/include/pgsql)。 下面是標示差異點的 patch 檔案。

--- dbpg.h.org    2025-12-03 16:37:40.171256167 +0800
+++ dbpg.h    2025-12-03 16:37:58.707205142 +0800
@@ -25,7 +25,7 @@
  * pg_config.h. However, the PACKAGE_* macros conflict with
  * NaviServer's packaging information, so we drop these.
  */
-#include <pg_config.h>
+#include <pgsql/pg_config.h>
 #undef PACKAGE_VERSION
 #undef PACKAGE_TARNAME
 #undef PACKAGE_STRING
@@ -34,7 +34,7 @@
 #undef PACKAGE_URL
 
 #include <nsdb.h>
-#include <libpq-fe.h>
+#include <pgsql/libpq-fe.h>
 
 /*
  * Forward compatibility, in case a new version of the module is compiled
--- Makefile.org    2025-12-03 16:39:07.524319290 +0800
+++ Makefile    2025-12-03 16:39:23.699037548 +0800
@@ -27,7 +27,7 @@
 # version of this file under either the License or the GPL.
 
 ifndef NAVISERVER
-    NAVISERVER  = /usr/local/ns
+    NAVISERVER  = /var/lib/naviserver
 endif
 
 #

不過除了直接修改,也可以使用設定參數的方式,下面就是編譯與安裝的指令:

make NAVISERVER=/var/lib/naviserver PGLIB=/usr/lib64 PGINCLUDE=/usr/include/pgsql
sudo make NAVISERVER=/var/lib/naviserver install

在安裝完 nsdbpb 以後,接下來修改 nsd-config.tcl,首先加入相關的變數:

# For database
dict set defaultConfig db_name           danilo
dict set defaultConfig db_user           danilo
dict set defaultConfig db_password       danilo
dict set defaultConfig db_host           localhost
dict set defaultConfig db_port           5432

加入 nsdb 模組,讓 NaviServer 在啟動時會載入模組。

ns_section ns/server/default/modules {
    if {$nscpport ne ""} {ns_param nscp nscp}
    ns_param    nslog               nslog    
    ns_param    nscgi               nscgi
    ns_param    nsperm              nsperm
    ns_param    nsdb                nsdb
    ns_param    revproxy            tcl
}

然後加入 nsdbpg driver 的設定。

ns_section ns/db/drivers {
    ns_param postgres nsdbpg
}

接下來加入 connection pool 的設定。使用者可以設定不止一個 pool,我在這裡只是驗證如何設定,所以只加入一個。

ns_section ns/server/default/db {
   #ns_param Pools pool1,pool2
   ns_param Pools pool1
   ns_param defaultpool pool1
}

ns_section ns/db/pools {
    ns_param pool1 "This is pool1 for PostgreSQL"
}

ns_section ns/db/pool/pool1 {
   ns_param Connections        10
   ns_param LogMinDuration     10ms
   ns_param LogSQLerrors       false
   ns_param driver             postgres
   ns_param DataSource         ${db_host}:${db_port}:${db_name}
   ns_param user               $db_user
   ns_param password           $db_password
}

最後寫一個簡單的測試程式測試。

<%
     ns_adp_puts "NaviServer nsdbpg module - get PostgreSQL version<br>"

     set db [ns_db gethandle]
     set result [ns_db 1row $db "select version() as version"]
     ns_adp_puts [ns_set get $result version]
%>

下面嘗試安裝 nsdbi 以及 nsdbipg。

首先是 nsdbi,下面就是編譯與安裝的指令:

make NAVISERVER=/var/lib/naviserver
sudo make NAVISERVER=/var/lib/naviserver install

再來是 nsdbipg,下面就是編譯與安裝的指令:

make NAVISERVER=/var/lib/naviserver PGLIB=/usr/lib64 PGINCLUDE=/usr/include/pgsql
sudo make NAVISERVER=/var/lib/naviserver install

接下來修改 nsd-config.tcl,首先是加入模組(有二種方式,一種是全域的加入方法,一種是 per server 的加入方式, 這裡使用後一種):

ns_section ns/server/default/modules {
    if {$nscpport ne ""} {ns_param nscp nscp}
    ns_param    nslog               nslog
    ns_param    nscgi               nscgi
    ns_param    nsperm              nsperm
    ns_param    revproxy            tcl
    ns_param    nsdbipg1            nsdbipg
}

以及 nsdbipg1 的設定:

ns_section ns/server/default/module/nsdbipg1 {
    ns_param   default        true ;# This is the default pool
    ns_param   handles        10   ;# Max open handles to db.
    ns_param   maxwait        10   ;# Seconds to wait if handle unavailable.
    ns_param   maxidle        0    ;# Handle closed after maxidle seconds if unused.
    ns_param   maxopen        0    ;# Handle closed after maxopen seconds, regardless of use.
    ns_param   maxqueries     0    ;# Handle closed after maxqueries SQL queries.
    ns_param   checkinterval  600  ;# Check for idle handles every 10 minutes.

    ns_param   datasource     "user='danilo' password='danilo' dbname='danilo'"
}

最後寫一個簡單的測試程式測試。

<%
     ns_adp_puts "NaviServer nsdbipg module - get PostgreSQL version<br>"

     dbi_1row -array result {select version() as version}
     ns_adp_puts $result(version)
%>

要注意的是,database handle 由 NaviServer 所管理,所以你在測試程式並沒有看到開啟 handle 的動作。

沒有留言: