Lua 自身并没有提供访问数据库的函数,但是借助外部扩展库我们可以很容易实现对数据库的各种操作,例如LuaSQL,通过它,Lua 可以以统一的方法访问各种流行的数据库(例如PostgreSQL,ODBC,JDBC,MySQL,SQLite,Oracle 和 ADO 等等)。

    达梦数据库并未提供luasql的访问驱动,但是可以通过ODBC连接到达梦数据库,再由LuaSQL访问到ODBC执行数据库操作。

1.安装gcc

检查是否安装,如果有则无需安装

[root@localhost opt]# gcc
gcc: fatal error: no input files
compilation terminated.

安装gcc,直接采用yum安装

yum install gcc

2.安装ODBC

1.采用yum安装

yum install unixODBC.x86_64 unixODBC-devel.x86_64 -y

2.源码编译安装

源码包下载地址:http://www.unixodbc.org

上传到服务器后解压编译安装

tar xzvf unixODBC-2.3.0.tar.gz
cd unixODBC-2.3.0/
./configure
make && make install

查看是否安装完成

[root@localhost unixODBC-2.3.7]# odbc_config
Usage: odbc_config
		[--prefix]
		[--exec-prefix]
		[--include-prefix]
		[--lib-prefix]
		[--bin-prefix]
		[--version]
		[--libs]
		[--static-libs]
		[--libtool-libs]
		[--cflags]
		[--odbcversion]
		[--longodbcversion]
		[--odbcini]
		[--odbcinstini]
		[--header]
		[--ulen]

3.查看配置路径

[root@localhost unixODBC-2.3.7]# odbcinst -j
unixODBC 2.3.7
DRIVERS............: /usr/local/etc/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/etc/odbc.ini
FILE DATA SOURCES..: /usr/local/etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

 4.配置DM数据源及驱动

根据配置路径可知ODBC驱动配置文件odbcinst.ini及数据源配置文件odbc.ini所在路径。

配置odbc.ini

[DM8]
Description = DM ODBC DSN  //描述
DRIVER = DM8 ODBC DRIVER   //驱动名称
SERVER = 127.0.0.1         //dm数据库ip地址 
UID = SYSDBA               //用户名
PWD = SYSDBA               //密码
TCP_PORT = 5236            //连接端口

配置odbcinst.ini

[DM8 ODBC DRIVER]    //注意 这个名称一定要与odbc.ini中的DRIVER保持一致!!
Description = DM ODBC DRIVER FOR DM8   //描述
Driver      = /home/libdodbc.so        //dm数据库驱动
[root@bogon nginx]# ldd /home/libdodbc.so
	linux-vdso.so.1 =>  (0x00007fffa6103000)
	libdmdpi.so => not found
	libdmfldr.so => not found
	librt.so.1 => /lib64/librt.so.1 (0x00007fe48fbdf000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe48f9c3000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007fe48f7be000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fe48f4b6000)
	libm.so.6 => /lib64/libm.so.6 (0x00007fe48f1b4000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fe48ede5000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe48ebcf000)
	/lib64/ld-linux-x86-64.so.2 (0x00005609cf20a000)

如果本机未安装dm数据库驱动,libdodbc.so文件及其依赖链接文件libdmfldr.so,libdmdpi.so可以从达梦所在服务器复制过来,并且配置动态链接库加载路径。在/etc/profile中追加内容

export LD_LIBRARY_PATH=/usr/local/lib
[root@bogon nginx]# vim /etc/profile
[root@bogon nginx]# source /etc/profile

将libdmfldr.so,libdmdpi.so文件拷贝到动态链接库加载路径下。

另外在DM8中,加密模块已不在libdodbc.so中,需要将动态链接库libcrypt.so拷贝到本机目录/usr/lib64或者手动创建软链接。

[root@localhost home]# pwd
/home
[root@localhost home]# ls
 libdodbc.so
[root@localhost lib64]# ls -l /usr/lib64/libcrypt.so
lrwxrwxrwx. 1 root root 25 Mar 30 21:31 /usr/lib64/libcrypt.so -> ../../lib64/libcrypt.so.1

再次通过ldd工具查看libdodbc.so依赖动态库

[root@localhost home]# ldd libdodbc.so
	linux-vdso.so.1 =>  (0x00007ffd003c4000)
	libdmdpi.so => ./libdmdpi.so (0x00007f7609512000)
	libdmfldr.so => ./libdmfldr.so (0x00007f76091f5000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f7608fe7000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f7608dcb000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f7608bc6000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f76088be000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f76085bc000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f76081ed000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f7607fd7000)
	/lib64/ld-linux-x86-64.so.2 (0x000055f54d7aa000)

如果没有not found,进行下一步;找不到则继续从服务器上copy;

5.ODBC连接达梦数据库

执行isql -v dm8,其中 -v 参数可查看执行失败的报错信息

[root@localhost lib64]# isql -v dm8
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL>

连接成功!

3.安装LuaSQL

1.下载源码

Lua Github 源码地址:GitHub - lunarmodules/luasql: LuaSQL is a simple interface from Lua to a DBMS.

2.修改配置文件

解压进入目录

[root@localhost opt]# unzip luasql-master.zip
[root@localhost opt]# cd luasql-master
[root@localhost luasql-master]# ls
config  Makefile        Makefile.win      Makefile.win.firebird  Makefile.win.odbc     README    src    vc6
doc     Makefile.mingw  Makefile.win.ado  Makefile.win.mysql     Makefile.win.sqlite3  rockspec  tests

修改配置文件config

[root@localhost luasql-master]# cat config
# Installation directories

# Default prefix
PREFIX ?=/usr/local/openresty/luajit   //前缀
# Lua version and dirs
LUA_SYS_VER ?= 5.1
LUA_LIBDIR ?= $(PREFIX)/lib           //lua链接库
LUA_DIR ?= $(PREFIX)/bin              //lua命令参数
LUA_INC ?= $(PREFIX)/include          //lua头文件所在目录

# OS dependent
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin) # MacOS
	LIB_OPTION ?= -bundle -undefined dynamic_lookup -mmacosx-version-min=10.3
else # Linux/BSD
	LIB_OPTION ?= -shared
endif

# - ODBC
DRIVER_LIBS_odbc ?= -L/usr/local/lib -lodbc   //odbc动态链接库
DRIVER_INCS_odbc ?= -DUNIXODBC -I/usr/local/include  //c头文件目录

# general compilation parameters
WARN= -fPIC $(OPTFLAGS) -Wmissing-prototypes -Wmissing-declarations -ansi -pedantic
INCS = -I$(LUA_INC)
DEFS = -std=gnu99 -fPIC
CFLAGS=$(WARN) $(DRIVER_INCS) $(INCS) -DLUASQL_VERSION_NUMBER='"$V"' $(DEFS)
CC= gcc

仅需要找到对应的数据库修改参数,这里其他数据库参数我删掉了。

本文采用的编译器为集成在openresty中的luajit,因此填写相关安装目录,如果安装的是Lua则相关参数配置可以用whereis lua查找,odbc相关参数如果按上述步骤安装的跟我一样即可。

修改完成后保存退出。

3.生成C程序库

[root@localhost luasql-master]# make odbc install
make: Nothing to be done for `odbc'.
mkdir -p /usr/local/openresty/luajit/lib/luasql
cp src/*.so /usr/local/openresty/luajit/lib/luasql

执行安装命令,生成C 程序库odbc.so文件至相应目录。

4.lua连接达梦数据库

1.编写脚本

编写lua脚本如下,关于luasql数据库api可在安装包的doc文档中查询

local luasql =  require "luasql.odbc"
env = luasql.odbc()
con = assert(env:connect ("DM8",--配置odbc的dsn /usr/local/etc/odbc.ini
"SYSDBA", --用户名
"SYSDBA")) --密码
cur = con:execute ("SELECT NAME FROM SYSDBA.TEST1")
row = cur:fetch ({}, "a")
while row do
for k,v in pairs(row) do
ngx.say(v)
end
row=cur:fetch (row, "a")
end
cur:close()
con:close()
env:close()

执行脚本,查看报错信息。

2023/03/31 04:57:25 [error] 81313#0: *1 lua entry thread aborted: runtime error: /usr/local/openresty/nginx/cache_dm.lua:1: module 'luasql.odbc' not found:
	no field package.preload['luasql.odbc']
	no file '/usr/local/openresty/site/lualib/luasql/odbc.ljbc'
	no file '/usr/local/openresty/site/lualib/luasql/odbc/init.ljbc'
	no file '/usr/local/openresty/lualib/luasql/odbc.ljbc'
	no file '/usr/local/openresty/lualib/luasql/odbc/init.ljbc'
	no file '/usr/local/openresty/site/lualib/luasql/odbc.lua'
	no file '/usr/local/openresty/site/lualib/luasql/odbc/init.lua'
	no file '/usr/local/openresty/lualib/luasql/odbc.lua'
	no file '/usr/local/openresty/lualib/luasql/odbc/init.lua'
	no file './luasql/odbc.lua'
	no file '/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/luasql/odbc.lua'
	no file '/usr/local/share/lua/5.1/luasql/odbc.lua'
	no file '/usr/local/share/lua/5.1/luasql/odbc/init.lua'
	no file '/usr/local/openresty/luajit/share/lua/5.1/luasql/odbc.lua'
	no file '/usr/local/openresty/luajit/share/lua/5.1/luasql/odbc/init.lua'
	no file '/usr/local/openresty/site/lualib/luasql/odbc.so'
	no file '/usr/local/openresty/lualib/luasql/odbc.so'
	no file './luasql/odbc.so'
	no file '/usr/local/lib/lua/5.1/luasql/odbc.so'
	no file '/usr/local/openresty/luajit/lib/lua/5.1/luasql/odbc.so'
	no file '/usr/local/lib/lua/5.1/loadall.so'
	no file '/usr/local/openresty/site/lualib/luasql.so'
	no file '/usr/local/openresty/lualib/luasql.so'
	no file './luasql.so'
	no file '/usr/local/lib/lua/5.1/luasql.so'
	no file '/usr/local/openresty/luajit/lib/lua/5.1/luasql.so'
	no file '/usr/local/lib/lua/5.1/loadall.so'

基本意思就是在指定路径下找不到对应文件~~

2.Lua模块加载机制

Lua模块文件不是放在哪个文件目录都行,函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。

require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中,当 Lua 启动后,会以环境变量 LUA_PATH 的值来初始这个环境变量。如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化。默认路径可以打印出来查看:

[root@localhost nginx]# /usr/bin/lua 
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print(package.path)
./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua

如果找过目标文件,则会调用 package.loadfile 来加载模块。否则,就会去找 C 程序库。

搜索的文件路径是从全局变量 package.cpath 获取,而这个变量则是通过环境变量 LUA_CPATH 来初始。

[root@localhost nginx]# /usr/bin/lua 
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print(package.cpath)
./?.so;/usr/lib64/lua/5.1/?.so;/usr/lib64/lua/5.1/loadall.so

搜索的策略跟上面的一样,只不过现在换成搜索的是 so 或 dll 类型的文件。如果找得到,那么 require 就会通过 package.loadlib 来加载它。

因此上面的错误是因为没有在指定路径找到我们安装好的odbc.so文件。只要把它拷贝到查找C程序库的第一个路径下即可。

[root@bogon nginx]# find / -name odbc.so
/usr/local/openresty/luajit/lib/luasql/odbc.so
[root@bogon nginx]# cp /usr/local/openresty/luajit/lib/luasql/odbc.so /usr/local/openresty/site/lualib/luasql/

再次执行脚本,成功访问到数据库~~

[root@bogon nginx]# curl http://127.0.0.1:14001
sjw_in_SADASD
xsq
lhx