|
| 1 | +Name |
| 2 | + lua-rds-parser - Resty-DBD-Stream (RDS) parser for Lua written in C |
| 3 | + |
| 4 | +Status |
| 5 | + This module is production ready. |
| 6 | + |
| 7 | +Synopsis |
| 8 | + local parser = require "rds.parser" |
| 9 | + |
| 10 | + local res, err = parser.parse(rds) |
| 11 | + |
| 12 | + if res == nil then |
| 13 | + error("failed to parse: " .. err) |
| 14 | + end |
| 15 | + |
| 16 | + print(res.errcode) |
| 17 | + print(res.errstr) |
| 18 | + print(res.insert_id) |
| 19 | + print(res.affected_rows) |
| 20 | + |
| 21 | + local rows = res.resultset |
| 22 | + if rows then |
| 23 | + for i, row in ipairs(rows) do |
| 24 | + for col, val in pairs(row) do |
| 25 | + if val ~= parser.null then |
| 26 | + print(col .. ": " .. val) |
| 27 | + end |
| 28 | + end |
| 29 | + end |
| 30 | + end |
| 31 | + |
| 32 | +Description |
| 33 | + This Lua library can be used to parse the Resty-DBD-Stream formatted data |
| 34 | + generated by ngx_drizzle (http://wiki.nginx.org/HttpDrizzleModule ) |
| 35 | + and ngx_postgres (http://github.com/FRiCKLE/ngx_postgres/ ) into Lua |
| 36 | + data structures. In the past, we have to use JSON as the intermediate data |
| 37 | + format which is quite inefficient in terms of both memory and CPU time. |
| 38 | + |
| 39 | + To maximize speed and minimize memory footprint, this library is implemented |
| 40 | + in pure C. |
| 41 | + |
| 42 | + Null values in RDS are turned into the light user data "parser.null" |
| 43 | + where "parser" is the module object returned by Lua's "require". |
| 44 | + |
| 45 | +JSON Serialization |
| 46 | + If you want to serialize the parsed result into JSON, please |
| 47 | + use the lua-cjson library (http://www.kyne.com.au/~mark/software/lua-cjson.php ) |
| 48 | + instead of lua-yajl, because lua-cjson is faster than lua-yajl |
| 49 | + in many common cases, and more importantly, |
| 50 | + |
| 51 | + parser.null == cjson.null ~= yajl.null |
| 52 | + |
| 53 | +Using with HttpDrizzleModule |
| 54 | + To use with ngx_drizzle, here is a small example: |
| 55 | + |
| 56 | + upstream backend { |
| 57 | + drizzle_server 127.0.0.1:3306 protocol=mysql |
| 58 | + dbname=ngx_test user=ngx_test password=ngx_test; |
| 59 | + drizzle_keepalive max=10 overflow=ignore mode=single; |
| 60 | + } |
| 61 | + |
| 62 | + server { |
| 63 | + ... |
| 64 | + |
| 65 | + location /mysql { |
| 66 | + drizzle_query $echo_request_body; |
| 67 | + drizzle_pass backend; |
| 68 | + } |
| 69 | + |
| 70 | + location /api { |
| 71 | + content_by_lua ' |
| 72 | + local sql = "select * from cats" |
| 73 | + local resp = ngx.location.capture("/mysql", { |
| 74 | + method = ngx.HTTP_POST, body = sql |
| 75 | + }) |
| 76 | + if resp.status ~= ngx.HTTP_OK or not resp.body then |
| 77 | + error("failed to query mysql") |
| 78 | + end |
| 79 | + |
| 80 | + local parser = require "rds.parser" |
| 81 | + local res, err = parser.parse(resp.body) |
| 82 | + if res == nil then |
| 83 | + error("failed to parse RDS: " .. err) |
| 84 | + end |
| 85 | + |
| 86 | + local rows = res.resultset |
| 87 | + if not rows or #rows == 0 then |
| 88 | + ngx.say("empty resultset") |
| 89 | + ngx.exit(0) |
| 90 | + end |
| 91 | + |
| 92 | + for i, row in ipairs(rows) do |
| 93 | + ngx.print("row ", i, ": ") |
| 94 | + for col, val in pairs(row) do |
| 95 | + if val ~= parser.null then |
| 96 | + ngx.print(col, "=", val, " ") |
| 97 | + else |
| 98 | + ngx.print(col, "=null ") |
| 99 | + end |
| 100 | + end |
| 101 | + ngx.say() |
| 102 | + end |
| 103 | + '; |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + On my machine, GET /api will yield |
| 108 | + |
| 109 | + row 1: id=2 name=null |
| 110 | + row 2: id=3 name=bob |
| 111 | + |
| 112 | + of course, the actual output depends on the structure and contents of the |
| 113 | + "cats" table in the mysql database. |
| 114 | + |
| 115 | + You can use this Lua library with the ngx_postgres module in a similar way. |
| 116 | + |
| 117 | +Installation |
| 118 | + Build requirements |
| 119 | + * Lua (http://www.lua.org/) |
| 120 | + |
| 121 | + * or LuaJIT (http://www.luajit.org/) |
| 122 | + |
| 123 | + Gnu make and gcc is required to build this module. |
| 124 | + |
| 125 | + Linux/BSD/Solaris |
| 126 | + gmake CC=gcc |
| 127 | + gmake install CC=gcc |
| 128 | + |
| 129 | + Mac OS X |
| 130 | + make LDFLAGS='-bundle -undefined dynamic_lookup' CC=gcc |
| 131 | + make install |
| 132 | + |
| 133 | + If your Lua or LuaJIT is not installed into the system, specify its |
| 134 | + include directory like this: |
| 135 | + |
| 136 | + make LUA_INCLUDE_DIR=/opt/luajit/include/luajit-2.0 |
| 137 | + |
| 138 | + You can specify a custom path for the installation target: |
| 139 | + |
| 140 | + make install LUA_LIB_DIR=/opt/lualib |
| 141 | + |
| 142 | + The "DESTDIR" variable is also supported, to ease RPM packaging. |
| 143 | + |
| 144 | +TODO |
| 145 | + * add support for option "compact" to generate a compact |
| 146 | + Lua table for the "resultset" field. |
| 147 | + |
| 148 | +Known Issues |
| 149 | + * The endianness flag in RDS is not supported yet in this library, |
| 150 | + and it will assume it's of the host's endian. So do not |
| 151 | + try parsing the RDS stream that is generated by another |
| 152 | + machine of a different endian. |
| 153 | + |
| 154 | +Author |
| 155 | + Zhang "agentzh" Yichun <agentzh@gmail.com> |
| 156 | + |
| 157 | +Copyright & License |
| 158 | + This module is licenced under the BSD license. |
| 159 | + |
| 160 | + Copyright (C) 2011, Zhang "agentzh" Yichun (章亦春) <agentzh@gmail.com>. |
| 161 | + |
| 162 | + All rights reserved. |
| 163 | + |
| 164 | + Redistribution and use in source and binary forms, with or without |
| 165 | + modification, are permitted provided that the following conditions |
| 166 | + are met: |
| 167 | + |
| 168 | + * Redistributions of source code must retain the above copyright |
| 169 | + notice, this list of conditions and the following disclaimer. |
| 170 | + |
| 171 | + * Redistributions in binary form must reproduce the above copyright |
| 172 | + notice, this list of conditions and the following disclaimer in the |
| 173 | + documentation and/or other materials provided with the distribution. |
| 174 | + |
| 175 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 176 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 177 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 178 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 179 | + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 180 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
| 181 | + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 182 | + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 183 | + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 184 | + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 185 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 186 | + |
0 commit comments