Date: Monday, November 28, 2005 @ 10:20:40
Author: csaba
Path: /cvsroot/carob/libmysequoia
Added: config/controller/controller-mysql.xml (1.1) config/mysql.sh
(1.1) config/virtualdatabase/mysql.xml (1.1) src/Makefile (1.1)
src/hello-libmysequoia.c (1.1) src/libmysequoia.cpp (1.1)
Added the first working prototype and te configuration files.
----------------------------------------+
config/controller/controller-mysql.xml | 11
config/mysql.sh | 14
config/virtualdatabase/mysql.xml | 59 ++++
src/Makefile | 17 +
src/hello-libmysequoia.c | 130 ++++++++
src/libmysequoia.cpp | 451 +++++++++++++++++++++++++++++++
6 files changed, 682 insertions(+)
Index: libmysequoia/config/controller/controller-mysql.xml
diff -u /dev/null libmysequoia/config/controller/controller-mysql.xml:1.1
--- /dev/null Mon Nov 28 10:20:40 2005
+++ libmysequoia/config/controller/controller-mysql.xml Mon Nov 28 10:20:40 2005
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE SEQUOIA-CONTROLLER PUBLIC "-//Continuent//DTD SEQUOIA-CONTROLLER
2.3//EN" "http://sequoia.continuent.org/dtds/sequoia-controller-2.3.dtd">
+<SEQUOIA-CONTROLLER>
+ <Controller port="25322">
+ <Report/>
+ <JmxSettings>
+ <RmiJmxAdaptor/>
+ </JmxSettings>
+ <VirtualDatabase configFile="mysql.xml" virtualDatabaseName="db"
autoEnableBackends="force"/>
+ </Controller>
+</SEQUOIA-CONTROLLER>
Index: libmysequoia/config/mysql.sh
diff -u /dev/null libmysequoia/config/mysql.sh:1.1
--- /dev/null Mon Nov 28 10:20:40 2005
+++ libmysequoia/config/mysql.sh Mon Nov 28 10:20:40 2005
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+SEQUOIA_HOME=/home/secsaba/software/sequoia
+
+cd $SEQUOIA_HOME/bin
+
+sudo /etc/init.d/mysql start
+sleep 5
+
+echo "Starting hsqldb on port 9003 (recovery)"
+./hsqldb.sh -port 9003 &
+
+echo "Starting Controller with MySQL Configuration"
+./controller.sh -f ../config/controller/controller-mysql.xml &
Index: libmysequoia/config/virtualdatabase/mysql.xml
diff -u /dev/null libmysequoia/config/virtualdatabase/mysql.xml:1.1
--- /dev/null Mon Nov 28 10:20:40 2005
+++ libmysequoia/config/virtualdatabase/mysql.xml Mon Nov 28 10:20:40 2005
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF8"?>
+<!DOCTYPE SEQUOIA PUBLIC "-//Continuent//DTD SEQUOIA 2.3//EN"
"http://sequoia.continuent.org/dtds/sequoia-2.3.dtd">
+
+<SEQUOIA>
+
+ <VirtualDatabase name="db">
+
+ <AuthenticationManager>
+ <Admin>
+ <User username="admin" password="adminpass"/>
+ </Admin>
+ <VirtualUsers>
+ <VirtualLogin vLogin="user" vPassword="userpass"/>
+ </VirtualUsers>
+ </AuthenticationManager>
+
+ <DatabaseBackend name="csaba" driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/test" connectionTestStatement="select 1">
+ <ConnectionManager vLogin="user" rLogin="root" rPassword="rootpass">
+ <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5"
maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
+ </ConnectionManager>
+ </DatabaseBackend>
+
+ <RequestManager>
+ <RequestScheduler>
+ <RAIDb-1Scheduler level="passThrough"/>
+ </RequestScheduler>
+
+ <LoadBalancer>
+ <RAIDb-1>
+ <WaitForCompletion policy="first"/>
+ <RAIDb-1-LeastPendingRequestsFirst/>
+ </RAIDb-1>
+ </LoadBalancer>
+
+ <RecoveryLog driver="org.hsqldb.jdbcDriver"
+ url="jdbc:hsqldb:hsql://localhost:9003" login="TEST" password="">
+ <RecoveryLogTable tableName="RECOVERY" idColumnType="BIGINT NOT NULL"
+ vloginColumnType="VARCHAR NOT NULL" sqlColumnType="VARCHAR NOT NULL"
+ extraStatementDefinition=",PRIMARY KEY (id)"/>
+ <CheckpointTable tableName="CHECKPOINT"
+ checkpointNameColumnType="VARCHAR NOT NULL"/>
+ <BackendTable tableName="BACKEND"
+ databaseNameColumnType="VARCHAR NOT NULL"
+ backendNameColumnType="VARCHAR NOT NULL"
+ checkpointNameColumnType="VARCHAR NOT NULL"/>
+ <DumpTable tableName="DUMP" dumpNameColumnType="VARCHAR NOT NULL"
+ dumpDateColumnType="VARCHAR NOT NULL"
+ dumpPathColumnType="VARCHAR NOT NULL"
+ dumpFormatColumnType="VARCHAR NOT NULL"
+ checkpointNameColumnType="VARCHAR NOT NULL"
+ backendNameColumnType="VARCHAR NOT NULL"
+ tablesColumnType="VARCHAR NOT NULL"/>
+ </RecoveryLog>
+
+ </RequestManager>
+
+ </VirtualDatabase>
+
+</SEQUOIA>
Index: libmysequoia/src/Makefile
diff -u /dev/null libmysequoia/src/Makefile:1.1
--- /dev/null Mon Nov 28 10:20:40 2005
+++ libmysequoia/src/Makefile Mon Nov 28 10:20:40 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/src/hello-libmysequoia.c
diff -u /dev/null libmysequoia/src/hello-libmysequoia.c:1.1
--- /dev/null Mon Nov 28 10:20:40 2005
+++ libmysequoia/src/hello-libmysequoia.c Mon Nov 28 10:20:40 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/src/libmysequoia.cpp
diff -u /dev/null libmysequoia/src/libmysequoia.cpp:1.1
--- /dev/null Mon Nov 28 10:20:40 2005
+++ libmysequoia/src/libmysequoia.cpp Mon Nov 28 10:20:40 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