From 2e359b0a6b67060def1a780837f24e5cfcdbdfee Mon Sep 17 00:00:00 2001
From: "Dmitry E. Oboukhov" <unera@debian.org>
Date: Tue, 4 Jun 2013 17:08:51 +0400
Subject: [PATCH] Prototype for Pg driver

---
 CMakeLists.txt          |  6 ++++
 cmake/BuildSQL.cmake    | 41 +++++++++++++++++++++++++
 include/config.h.cmake  |  6 ++++
 src/CMakeLists.txt      |  5 +++
 src/box/CMakeLists.txt  |  1 +
 src/box/box_lua.m       |  4 +--
 src/box/lua/sql.lua     | 55 +++++++++++++++++++++++++++++++++
 src/lua/init.m          |  4 +++
 src/lua/lua_pg.h        |  6 ++++
 src/lua/lua_sql.h       |  7 +++++
 src/lua/lua_sql.m       | 68 +++++++++++++++++++++++++++++++++++++++++
 src/lua/pg.m            | 12 ++++++++
 test/box/net_sql.result |  4 +++
 test/box/net_sql.test   |  4 +++
 14 files changed, 221 insertions(+), 2 deletions(-)
 create mode 100644 cmake/BuildSQL.cmake
 create mode 100644 src/box/lua/sql.lua
 create mode 100644 src/lua/lua_pg.h
 create mode 100644 src/lua/lua_sql.h
 create mode 100644 src/lua/lua_sql.m
 create mode 100644 src/lua/pg.m
 create mode 100644 test/box/net_sql.result
 create mode 100644 test/box/net_sql.test

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a7284e10a..fed52629c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,6 +27,7 @@ find_program(CONFETTI confetti)
 find_program(LD ld)
 find_program(POD2MAN pod2man)
 
+
 #
 # This instructs the rest of the build system what product
 # and what modules to produce.
@@ -266,6 +267,11 @@ else()
     endif()
 endif()
 
+#
+# MySQL & PgSQL
+#
+include(BuildSQL)
+
 
 #
 # LibEV
diff --git a/cmake/BuildSQL.cmake b/cmake/BuildSQL.cmake
new file mode 100644
index 0000000000..ee17721efa
--- /dev/null
+++ b/cmake/BuildSQL.cmake
@@ -0,0 +1,41 @@
+option(ENABLE_PSQL  "Enable postgresql client for box.net.sql" OFF)
+option(ENABLE_MYSQL "Enable mysql client for box.net.sql" OFF)
+
+
+
+if(ENABLE_PSQL)
+	include(FindPostgreSQL)
+	if (PostgreSQL_FOUND)
+		message(STATUS
+			"box.net.sql(pg): INC=${PostgreSQL_INCLUDE_DIR}")
+		message(STATUS
+			"box.net.sql(pg): LIBDIR=${PostgreSQL_LIBRARY_DIR}")
+		message(STATUS
+			"box.net.sql(pg): LIBS=${PostgreSQL_LIBRARIES}")
+
+		add_compile_flags("C;CXX" "-I${PostgreSQL_INCLUDE_DIR}")
+		add_compile_flags("C;CXX" "-L${PostgreSQL_LIBRARY_DIR}")
+		add_compile_flags("C;CXX" "-l${PostgreSQL_LIBRARIES}")
+
+	else()
+		message(STATUS "PostgreSQL client not found")
+		set(ENABLE_PSQL OFF)
+	endif()
+endif()
+
+if(ENABLE_PSQL)
+	set(USE_PSQL_CLIENT "1")
+else()
+	set(USE_PSQL_CLIENT "0")
+endif()
+
+
+if(ENABLE_MYSQL)
+
+endif()
+
+if (ENABLE_MYSQL)
+	set(USE_MYSQL_CLIENT "1")
+else()
+	set(USE_MYSQL_CLIENT "0")
+endif()
diff --git a/include/config.h.cmake b/include/config.h.cmake
index d253758e2e..bc3505171a 100644
--- a/include/config.h.cmake
+++ b/include/config.h.cmake
@@ -98,6 +98,12 @@
 #cmakedefine ENABLE_BUNDLED_LIBEIO 1
 #cmakedefine ENABLE_BUNDLED_LIBCORO 1
 
+/*
+ * SQL clients
+ */
+#define USE_PSQL_CLIENT		@USE_PSQL_CLIENT@
+#define USE_MYSQL_CLIENT	@USE_MYSQL_CLIENT@
+
 /*
  * predefined /etc directory prefix.
  */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8028d32837..a403fd9f31 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -106,8 +106,13 @@ set (common_sources
      lua/lua_socket.m
      lua/session.m
      lua/cjson.m
+     lua/lua_sql.m
 )
 
+if (ENABLE_PSQL)
+    set (common_sources ${common_sources} lua/pg.m)
+endif()
+
 if (ENABLE_TRACE)
     set (common_sources ${common_sources} trace.m)
 endif()
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index a01ab03541..8e88a0a16c 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -22,6 +22,7 @@ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src/box/lua)
 lua_source(lua/box.lua)
 lua_source(lua/box_net.lua)
 lua_source(lua/misc.lua)
+lua_source(lua/sql.lua)
 
 add_custom_target(generate_lua_sources}
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/box
diff --git a/src/box/box_lua.m b/src/box/box_lua.m
index 4ad80347f1..2eedde66b4 100644
--- a/src/box/box_lua.m
+++ b/src/box/box_lua.m
@@ -48,8 +48,8 @@
 #include "tbuf.h"
 
 /* contents of box.lua, misc.lua, box.net.lua respectively */
-extern char box_lua[], box_net_lua[], misc_lua[];
-const char *lua_sources[] = { box_lua, box_net_lua, misc_lua, NULL };
+extern char box_lua[], box_net_lua[], misc_lua[], sql_lua[];
+const char *lua_sources[] = { box_lua, box_net_lua, misc_lua, sql_lua, NULL };
 
 /**
  * All box connections share the same Lua state. We use
diff --git a/src/box/lua/sql.lua b/src/box/lua/sql.lua
new file mode 100644
index 0000000000..f14fb435e5
--- /dev/null
+++ b/src/box/lua/sql.lua
@@ -0,0 +1,55 @@
+box.net.sql = {
+    connect = function(driver, host, port, user, login, db, ...)
+
+        if type(driver) == 'table' then
+            driver = driver.driver
+        end
+
+        local self = {
+            driver      = driver,
+            host        = host,
+            port        = port,
+            login       = login,
+            password    = password,
+            db          = db
+        }
+            
+        local init      = { ... }
+
+        setmetatable(self, box.net.sql)
+
+        -- do_connect is written in C
+        -- it add 'raw' field in the table
+        local c = box.net.sql.do_connect( self )
+
+        -- perform init statements
+        for i, s in pairs(init) do
+            c:execute(unpack(s))
+        end
+        return c
+    end,
+
+
+    __index = {
+        -- main method
+        -- do query and returns: status, resultset
+        execute = function(self, sql, ...)
+            if self.raw == nil then
+                error("Connection was not established")
+            end
+            error("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+            return self.raw.execute(self, sql, ...)
+        end,
+
+        -- quote identifiers
+        ident_quote = function(self, ident)
+            return self.raw.ident_quote(ident)
+        end,
+
+        -- quote variables
+        quote = function(self, value)
+            return self.raw.quote(value)
+        end,
+    }
+
+}
diff --git a/src/lua/init.m b/src/lua/init.m
index 0f39799f8c..2ec936b8ea 100644
--- a/src/lua/init.m
+++ b/src/lua/init.m
@@ -45,6 +45,7 @@
 #include "fiber.h"
 #include "lua_ipc.h"
 #include "lua_socket.h"
+#include "lua_sql.h"
 #include "lua/info.h"
 #include "lua/slab.h"
 #include "lua/stat.h"
@@ -1124,6 +1125,9 @@ tarantool_lua_init()
 
 	mod_lua_init(L);
 
+	/* init after internal luas are processed */
+	tarantool_lua_sql_init(L);
+
 	/* clear possible left-overs of init */
 	lua_settop(L, 0);
 	return L;
diff --git a/src/lua/lua_pg.h b/src/lua/lua_pg.h
new file mode 100644
index 0000000000..6e1a20d37a
--- /dev/null
+++ b/src/lua/lua_pg.h
@@ -0,0 +1,6 @@
+#ifndef TARANTOOL_LUA_SQL_PG_H_INCLUDED
+
+struct lua_State;
+int lbox_net_pg_connect(struct lua_State *L);
+
+#endif /* TARANTOOL_LUA_SQL_PG_H_INCLUDED */
diff --git a/src/lua/lua_sql.h b/src/lua/lua_sql.h
new file mode 100644
index 0000000000..e94946b293
--- /dev/null
+++ b/src/lua/lua_sql.h
@@ -0,0 +1,7 @@
+#ifndef TARANTOOL_LUA_SQL_H_INCLUDED
+
+struct lua_State;
+void tarantool_lua_sql_init(struct lua_State *L);
+
+#endif
+
diff --git a/src/lua/lua_sql.m b/src/lua/lua_sql.m
new file mode 100644
index 0000000000..100ebea756
--- /dev/null
+++ b/src/lua/lua_sql.m
@@ -0,0 +1,68 @@
+#include "lua_sql.h"
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+#include <string.h>
+
+#include <config.h>
+
+#if USE_PSQL_CLIENT
+	#include "lua_pg.h"
+#endif
+
+#if USE_MYSQL_CLIENT
+	#include "lua_mysql.h"
+#endif
+
+int
+lbox_net_sql_do_connect(struct lua_State *L)
+{
+	lua_pushstring(L, "driver");
+	lua_rawget(L, -2);
+
+	const char *drv = lua_tostring(L, -1);
+	lua_pop(L, 1);
+
+
+	if (strcmp(drv, "pg") == 0 || strcmp(drv, "postgresql") == 0)
+		#if USE_PSQL_CLIENT
+			return lbox_net_pg_connect(L);
+		#else
+			luaL_error(L,
+				"Tarantool was not compiled with postgresql. "
+				"Use cmake with '-DENABLE_PSQL=ON' option."
+			);
+		#endif
+
+	if (strcmp(drv, "mysql") == 0)
+		#if USE_MYSQL_CLIENT
+			return lbox_net_mysql_connect(L);
+		#else
+			luaL_error(L,
+				"Tarantool was not compiled with mysqlclient. "
+				"Use cmake with '-DENABLE_MYSQL=ON' option."
+			);
+		#endif
+	return 0;
+}
+
+
+void
+tarantool_lua_sql_init(struct lua_State *L)
+{
+	lua_getfield(L, LUA_GLOBALSINDEX, "box");	/* stack: box */
+
+	lua_pushstring(L, "net");			/* stack: box.net */
+	lua_rawget(L, -2);
+
+	lua_pushstring(L, "sql");			/* stack: box.net.sql */
+	lua_rawget(L, -2);
+
+	/* stack: box, box.net.sql */
+	lua_pushstring(L, "do_connect");
+	lua_pushcfunction(L, lbox_net_sql_do_connect);
+	lua_rawset(L, -3);
+
+	/* cleanup stack */
+	lua_pop(L, 3);
+}
diff --git a/src/lua/pg.m b/src/lua/pg.m
new file mode 100644
index 0000000000..3ff477c507
--- /dev/null
+++ b/src/lua/pg.m
@@ -0,0 +1,12 @@
+#include "lua_pg.h"
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+int
+lbox_net_pg_connect(struct lua_State *L)
+{
+	lua_pushstring(L, "aaaaaaaaaaaaaaaaaaa");
+	return 1;
+}
diff --git a/test/box/net_sql.result b/test/box/net_sql.result
new file mode 100644
index 0000000000..5e5fe3ef33
--- /dev/null
+++ b/test/box/net_sql.result
@@ -0,0 +1,4 @@
+lua 1
+---
+ - 1
+...
diff --git a/test/box/net_sql.test b/test/box/net_sql.test
new file mode 100644
index 0000000000..caafa1bc38
--- /dev/null
+++ b/test/box/net_sql.test
@@ -0,0 +1,4 @@
+# encoding: tarantool
+
+exec admin "lua c = box.net.sql.connect('pg', 'localhost', 5432, 'tarantool', 'tarantool', 'tarantool')"
+exec admin "lua c"
-- 
GitLab