Date: Monday, November 28, 2005 @ 10:13:57
Author: csaba
Path: /cvsroot/carob/libmysequoia
Added: Makefile (1.1) hello-libmysequoia.c (1.1) libmysequoia.cpp (1.1)
Modified: README.txt (1.1 -> 1.2)
Added the initial prototype.
----------------------+
Makefile | 17 +
README.txt | 4
hello-libmysequoia.c | 130 ++++++++++++++
libmysequoia.cpp | 451 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 601 insertions(+), 1 deletion(-)
Index: libmysequoia/Makefile
diff -u /dev/null libmysequoia/Makefile:1.1
--- /dev/null Mon Nov 28 10:13:57 2005
+++ libmysequoia/Makefile Mon Nov 28 10:13:57 2005
@@ -0,0 +1,17 @@
+all: hello-libmysequoia libmysqlclient.so.15.1
+
+hello-libmysequoia: hello-libmysequoia.c
+ cc -Wall -g `mysql_config --include` -o $@ $< `mysql_config --libs`
+
+libmysqlclient.so.15.1: libmysql.o
+ c++ -Wall -g -fPIC --shared -L../carob -lcarobcpp -o $@ $<
+ ln -sf $@ libmysqlclient.so.15
+
+libmysql.o: libmysequoia.cpp
+ c++ -Wall -g -o $@ -I../carob/include -I/usr/include/mysql -c $<
+
+clean:
+ rm -f libmysqlclient.so.15.1 libmysqlclient.so.15 libmysql.o
hello-libmysequoia
+
+run: all
+ LD_LIBRARY_PATH=.:../carob ./hello-libmysequoia
Index: libmysequoia/README.txt
diff -u libmysequoia/README.txt:1.1 libmysequoia/README.txt:1.2
--- libmysequoia/README.txt:1.1 Tue Nov 22 15:13:57 2005
+++ libmysequoia/README.txt Mon Nov 28 10:13:57 2005
@@ -1 +1,3 @@
-Initial libmysql module.
+Initial libmysequoia module.
+
+This library will reimplement the libmysqlclient library, using Carob to
benefit from clustering. So native mysql client programs can use the Sequoia
clustering product without changing any line in the application.
Index: libmysequoia/hello-libmysequoia.c
diff -u /dev/null libmysequoia/hello-libmysequoia.c:1.1
--- /dev/null Mon Nov 28 10:13:57 2005
+++ libmysequoia/hello-libmysequoia.c Mon Nov 28 10:13:57 2005
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+
+/*
+ * To create the table and insert some data:
+ * $ mysql -uroot -prootpass
+ * > USE test;
+ * > CREATE table t1 ( `a` int(11) NOT NULL auto_increment,
+ * `b` int(11) default NULL,
+ * PRIMARY KEY (`a`)
+ * ) ENGINE=InnoDB;
+ * > INSERT INTO t1 (b) VALUES (1),(2),(3)
+ * > exit
+ */
+
+static void
+print_error (MYSQL * conn, char *message)
+{
+ fprintf (stderr, "%s\n", message);
+ if (conn != NULL)
+ {
+ fprintf (stderr, "Error %u (%s): %s\n",
+ mysql_errno (conn), mysql_sqlstate (conn), mysql_error (conn));
+ }
+}
+
+
+void
+process_result_set (MYSQL * conn, MYSQL_RES * res_set)
+{
+ MYSQL_ROW row;
+ unsigned int i;
+
+ while ((row = mysql_fetch_row (res_set)) != NULL)
+ {
+ for (i = 0; i < mysql_num_fields (res_set); i++)
+ {
+ if (i > 0)
+ {
+ fputc ('\t', stdout);
+ }
+ printf ("%s", row[i] != NULL ? row[i] : "NULL");
+ }
+ fputc ('\n', stdout);
+ }
+ if (mysql_errno (conn) != 0)
+ print_error (conn, "mysql_fetch_row() failed");
+ else
+ printf ("%lu rows returned\n", (unsigned long) mysql_num_rows (res_set));
+}
+
+
+int
+main ()
+{
+ char *opt_host_name = "localhost"; /* server host (default=localhost) */
+ char *opt_user_name = "user"; /* username (default=login name) */
+ char *opt_password = "userpass"; /* password (default=none) */
+ unsigned int opt_port_num = 0; /* port number (use built-in value) */
+ char *opt_socket_name = NULL; /* socket name (use built-in value) */
+ char *opt_db_name = "db"; /* database name (default=none) */
+ unsigned int opt_flags = 0; /* connection flags (none) */
+ MYSQL *conn; /* pointer to connection handler */
+ MYSQL_RES *res_set;
+
+ /* initialize connection handler */
+ conn = mysql_init (NULL);
+ if (conn == NULL)
+ {
+ fprintf (stderr, "mysql_init() failed (probably out of memory)\n");
+ exit (1);
+ }
+
+ /* connect to server */
+ if (mysql_real_connect (conn, opt_host_name, opt_user_name, opt_password,
+ opt_db_name, opt_port_num, opt_socket_name,
+ opt_flags) == NULL)
+ {
+ fprintf (stderr, "mysql_real_connect() failed\n");
+ mysql_close (conn);
+ exit (1);
+ }
+
+ /* the insert must succed */
+ if (mysql_query (conn, "INSERT INTO t1(b) VALUES (4)") != 0)
+ {
+ print_error (conn, "INSERT statement failed");
+ }
+ else
+ {
+ printf ("INSERT statement succeeded: %lu rows affected\n",
+ (unsigned long) mysql_affected_rows (conn));
+ }
+
+ /* the insert must fail (duplicate key) */
+/* if (mysql_query (conn, "INSERT INTO t1 (a,b) VALUES (1,2)") != 0)
+ {
+ print_error (conn, "INSERT statement failed");
+ }
+ else
+ {
+ printf ("INSERT statement succeeded: %lu rows affected\n",
+ (unsigned long) mysql_affected_rows (conn));
+ }*/
+
+ /* simple query */
+ if (mysql_query (conn, "SELECT * from t1") != 0)
+ print_error (conn, "mysql_query() failed");
+ else
+ {
+ res_set = mysql_store_result (conn); /* generate result set */
+ if (res_set == NULL)
+ print_error (conn, "mysql_store_result() failed");
+ else
+ {
+ /* process result set, and then deallocate it */
+ process_result_set (conn, res_set);
+// mysql_free_result (res_set);
+ }
+ }
+
+ /* disconnect from server */
+ mysql_close (conn);
+
+ return 0;
+}
Index: libmysequoia/libmysequoia.cpp
diff -u /dev/null libmysequoia/libmysequoia.cpp:1.1
--- /dev/null Mon Nov 28 10:13:57 2005
+++ libmysequoia/libmysequoia.cpp Mon Nov 28 10:13:57 2005
@@ -0,0 +1,451 @@
+/**
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2005 Emic Networks
+ * Contact: [EMAIL PROTECTED]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Zsolt Simon, Csaba Simon
+ * Contributor(s):
+ */
+
+ /**
+ * This is only a first prototype that is demonstrating that
+ * the libmysequoia project is doable.
+ * There is no error checking nor exception handling and no
+ * comment on the code.
+ */
+
+/* C includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* MySQL includes */
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+#include <errmsg.h>
+
+/* Carob includes */
+#include <ConnectionParameters.hpp>
+#include <ConnectionPool.hpp>
+#include <DriverResultSet.hpp>
+#include <Statement.hpp>
+
+/* C++ includes */
+#include <string>
+#include <vector>
+#include <locale>
+
+void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);
+
+const char *client_errors[]=
+{
+ "Unknown MySQL error",
+ "Can't create UNIX socket (%d)",
+ "Can't connect to local MySQL server through socket '%-.100s' (%d)",
+ "Can't connect to MySQL server on '%-.100s' (%d)",
+ "Can't create TCP/IP socket (%d)",
+ "Unknown MySQL server host '%-.100s' (%d)",
+ "MySQL server has gone away",
+ "Protocol mismatch; server version = %d, client version = %d",
+ "MySQL client ran out of memory",
+ "Wrong host info",
+ "Localhost via UNIX socket",
+ "%-.100s via TCP/IP",
+ "Error in server handshake",
+ "Lost connection to MySQL server during query",
+ "Commands out of sync; you can't run this command now",
+ "Named pipe: %-.32s",
+ "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
+ "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
+ "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
+ "Can't initialize character set %-.32s (path: %-.100s)",
+ "Got packet bigger than 'max_allowed_packet' bytes",
+ "Embedded server",
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:",
+ "SSL connection error",
+ "Malformed packet",
+ "This client library is licensed only for use with MySQL servers having '%s'
license",
+ "Invalid use of null pointer",
+ "Statement not prepared",
+ "No data supplied for parameters in prepared statement",
+ "Data truncated",
+ "No parameters exist in the statement",
+ "Invalid parameter number",
+ "Can't send long data for non-string/non-binary data types (parameter: %d)",
+ "Using unsupported buffer type: %d (parameter: %d)",
+ "Shared memory: %-.100s",
+ "Can't open shared memory; client could not create request event (%lu)",
+ "Can't open shared memory; no answer event received from server (%lu)",
+ "Can't open shared memory; server could not allocate file mapping (%lu)",
+ "Can't open shared memory; server could not get pointer to file mapping
(%lu)",
+ "Can't open shared memory; client could not allocate file mapping (%lu)",
+ "Can't open shared memory; client could not get pointer to file mapping
(%lu)",
+ "Can't open shared memory; client could not create %s event (%lu)",
+ "Can't open shared memory; no answer from server (%lu)",
+ "Can't open shared memory; cannot send request event to server (%lu)",
+ "Wrong or unknown protocol",
+ "Invalid connection handle",
+ "Connection using old (pre-4.1.1) authentication protocol refused (client
option 'secure_auth' enabled)",
+ "Row retrieval was canceled by mysql_stmt_close() call",
+ "Attempt to read column without prior row fetch",
+ "Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the
statement",
+ "This feature is not implemented yet",
+ ""
+};
+
+const char *unknown_sqlstate= "HY000";
+const char *not_error_sqlstate= "00000";
+
+class CarobMYSQL;
+
+typedef struct st_cmysql {
+ MYSQL my;
+ CarobMYSQL *carob;
+} CMYSQL;
+
+class CarobMYSQL
+{
+public:
+ CarobMYSQL();
+ ~CarobMYSQL();
+
+ bool connect(const char *host, const char *user,
+ const char *passwd, const char *db, unsigned int port,
+ const char *unix_socket, unsigned long clientflag);
+ bool real_query(const char *query, ulong length);
+ MYSQL_RES *get_results(int size);
+ MYSQL_ROW fetch_row();
+
+ MYSQL *getMYSQL();
+
+private:
+ CMYSQL *mysqlPtr;
+ Connection *connectionPtr;
+ ConnectionPool *connectionPool;
+ Statement *stmtPtr;
+ DriverResultSet* drsPtr;
+ MYSQL_ROW row;
+ int nfields;
+
+ void allocRow(int no);
+ void deleteRow();
+};
+
+CarobMYSQL::CarobMYSQL() : connectionPtr(NULL), stmtPtr(NULL), drsPtr(NULL)
+{
+ mysqlPtr = new CMYSQL();
+ memset(&mysqlPtr->my, 0, sizeof(MYSQL));
+ mysqlPtr->carob = this;
+ connectionPool = &ConnectionPool::getInstance();
+}
+
+CarobMYSQL::~CarobMYSQL()
+{
+ delete mysqlPtr;
+ if (connectionPtr) delete connectionPtr;
+ if (stmtPtr) delete stmtPtr;
+// if (drsPtr) delete drsPtr;
+ deleteRow();
+}
+
+bool CarobMYSQL::connect(const char *host, const char *user,
+ const char *passwd, const char *db, unsigned int port,
+ const char *unix_socket, unsigned long clientflag)
+{
+ if (unix_socket)
+ {
+ set_mysql_error((MYSQL *)mysqlPtr, CR_NOT_IMPLEMENTED,
unknown_sqlstate);
+ return false;
+ }
+
+//TODO Fill the mysqlPtr structure
+ ConnectionParameters connectionParameters(toWString(host), port ? port
: 25322, toWString(db), toWString(user), toWString(passwd), DEBUG_LEVEL_DEBUG);
+
+ try {
+ connectionPtr =
connectionPool->connectToController(connectionParameters);
+ stmtPtr = connectionPtr->createStatement();
+ } catch (...) {
+ set_mysql_error((MYSQL *)mysqlPtr, CR_CONNECTION_ERROR,
unknown_sqlstate);
+ return false;
+ }
+
+ return true;
+}
+
+bool CarobMYSQL::real_query(const char *query, ulong length)
+{
+ try {
+ if (drsPtr) delete drsPtr;
+
+ if (stmtPtr->execute(toWString(query)))
+ mysqlPtr->my.affected_rows = 0;
+ else
+ mysqlPtr->my.affected_rows = stmtPtr->getUpdateCount();
+
+ return true;
+ } catch (...) {
+ //TODO Error : connectionPtr(NULL), stmtPtr(NULL),
drsPtr(NULL)handling
+ return false;
+ }
+}
+
+MYSQL_RES * CarobMYSQL::get_results(int size)
+{
+ try {
+ if (stmtPtr)
+ {
+ stmtPtr->setFetchSize(size);
+ drsPtr = stmtPtr->getResultSet();
+ if (drsPtr)
+ {
+ mysqlPtr->my.field_count =
drsPtr->getNumberOfColumns();
+ mysqlPtr->my.affected_rows =
drsPtr->getNumberOfRowsInMemory();
+ }
+ return (MYSQL_RES *) this;
+ }
+ return NULL;
+ } catch (...) {
+ //TODO error handling
+ return NULL;
+ }
+}
+
+MYSQL_ROW CarobMYSQL::fetch_row()
+{
+ if (drsPtr)
+ {
+ deleteRow();
+ if (drsPtr->next())
+ {
+ allocRow(mysqlPtr->my.field_count);
+ for (unsigned i=0; i<mysqlPtr->my.field_count; i++)
+ {
+ char s[200];
+ int32_t *iPtr = drsPtr->getInt(i+1);
+ if (iPtr) {
+ sprintf(s,"%d",*iPtr);
+ row[i] = new char[strlen(s)+1];
+ strcpy(row[i],s);
+ }
+ }
+
+ mysqlPtr->my.affected_rows =
drsPtr->getNumberOfRowsInMemory();
+
+ return row;
+ }
+ return 0;
+ }
+ else
+ return 0;
+}
+
+MYSQL *CarobMYSQL::getMYSQL()
+{
+ return (MYSQL *) mysqlPtr;
+}
+
+typedef char *PCHAR;
+
+void CarobMYSQL::allocRow(int no)
+{
+ row = new PCHAR[no];
+ nfields = no;
+ memset(row, sizeof(PCHAR)*no, 0);
+}
+
+void CarobMYSQL::deleteRow()
+{
+ if (row)
+ {
+ for (int i=0; i<nfields; i++)
+ if (row[i]) delete row[i];
+ delete row;
+ row = NULL;
+ }
+}
+
+/***********************************
+ * MySQL functions
+ ***********************************/
+
+MYSQL *STDCALL
+mysql_init(MYSQL * mysql)
+{
+ if (!mysql)
+ {
+ CarobMYSQL *tmp = new CarobMYSQL();
+ mysql = tmp->getMYSQL();
+ }
+
+ return mysql;
+}
+
+MYSQL *STDCALL
+mysql_real_connect (MYSQL * mysql, const char *host, const char *user,
+ const char *passwd, const char *db, unsigned int port,
+ const char *unix_socket, unsigned long clientflag)
+{
+ if (mysql) {
+ return ((CMYSQL *)mysql)->carob->connect(host, user, passwd,
db, port, unix_socket, clientflag) ? mysql : 0;
+ }
+ else
+ {
+ set_mysql_error(mysql, CR_NULL_POINTER, unknown_sqlstate);
+ return 0;
+ }
+}
+
+void STDCALL
+mysql_close (MYSQL *sock)
+{
+ if (sock)
+ delete ((CMYSQL *)sock)->carob;
+}
+
+/* error handling functions */
+void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
+{
+ NET *net;
+
+ net= &mysql->net;
+ net->last_errno= errcode;
+ strcpy(net->last_error, ER(errcode));
+ strcpy(net->sqlstate, sqlstate);
+}
+
+unsigned int STDCALL
+mysql_errno(MYSQL *mysql)
+{
+ return mysql->net.last_errno;
+}
+
+const char * STDCALL
+mysql_error(MYSQL *mysql)
+{
+ return mysql->net.last_error;
+}
+
+const char *STDCALL
+mysql_sqlstate(MYSQL *mysql)
+{
+ return mysql->net.sqlstate;
+}
+
+int STDCALL
+mysql_query(MYSQL *mysql, const char *q)
+{
+ return mysql_real_query(mysql, q, 0);
+}
+
+int STDCALL
+mysql_real_query(MYSQL *mysql, const char *query, ulong length)
+{
+ if (mysql) {
+ //FIXME handle special strings which can contains '\0'
+ if ( ((CMYSQL *)mysql)->carob->real_query(query, length) )
+ {
+ return 0;
+ }
+ else
+ {
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR,
unknown_sqlstate);
+ return CR_UNKNOWN_ERROR;
+ }
+ }
+ else
+ {
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return CR_UNKNOWN_ERROR;
+ }
+}
+
+MYSQL_RES * STDCALL
+mysql_store_result(MYSQL *mysql)
+{
+ if (mysql) {
+ return ((CMYSQL *)mysql)->carob->get_results(0);
+ }
+ else
+ {
+ set_mysql_error(mysql, CR_NULL_POINTER, unknown_sqlstate);
+ return 0;
+ }
+}
+
+MYSQL_RES * STDCALL
+mysql_use_result(MYSQL *mysql)
+{
+ if (mysql) {
+ return ((CMYSQL *)mysql)->carob->get_results(1);
+ }
+ else
+ {
+ set_mysql_error(mysql, CR_NULL_POINTER, unknown_sqlstate);
+ return 0;
+ }
+}
+
+MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result)
+{
+ if (result) {
+ return ((CarobMYSQL *)result)->fetch_row();
+ }
+ else
+ {
+ //TODO set error
+ return 0;
+ }
+}
+
+unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
+{
+ if (res) {
+ return ((CarobMYSQL *)res)->getMYSQL()->field_count; //
get_num_fields();
+ }
+ else
+ {
+ //TODO set error
+ return 0;
+ }
+}
+
+my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
+{
+ if (mysql) {
+ return mysql->affected_rows;
+ }
+ else
+ {
+ //TODO set error
+ return 0;
+ }
+}
+
+my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)
+{
+ if (res) {
+ return ((CarobMYSQL *)res)->getMYSQL()->affected_rows;
+ }
+ else
+ {
+ //TODO set error
+ return 0;
+ }
+}
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits