You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
Added support for embedded (sqlite)
This commit is contained in:
@@ -18,8 +18,11 @@ ENDIF()
|
||||
IF(NOT WIN32)
|
||||
OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" ON)
|
||||
ENDIF()
|
||||
|
||||
OPTION(WITH_SQLITE "Enables Sqlite support" ON)
|
||||
###############
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
# Speedup system tests
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/WindowsCache.cmake)
|
||||
@@ -47,8 +50,8 @@ IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Relwithdebinfo")
|
||||
ENDIF()
|
||||
|
||||
|
||||
# various defines for generating include/mysql_version.h
|
||||
|
||||
SET(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd !
|
||||
SET(MYSQL_CLIENT_VERSION_MAJOR "5")
|
||||
SET(MYSQL_CLIENT_VERSION_MINOR "3")
|
||||
@@ -67,6 +70,7 @@ ENDIF()
|
||||
# todo: we don't character sets in share - all is compiled in
|
||||
SET(SHAREDIR "share")
|
||||
SET(DEFAULT_CHARSET_HOME "${CMAKE_INSTALL_PREFIX}")
|
||||
SET(PLUGINDIR "${CMAKE_INSTALL_PREFIX}/lib/plugin")
|
||||
|
||||
FIND_PACKAGE(Threads)
|
||||
|
||||
@@ -105,6 +109,10 @@ ENDIF()
|
||||
|
||||
FIND_PACKAGE(ZLIB QUIET)
|
||||
|
||||
IF(WITH_SQLITE)
|
||||
ADD_DEFINITIONS(-DHAVE_SQLITE)
|
||||
ENDIF()
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/include/mysql_version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/mysql_version.h)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/include/my_config.h.in
|
||||
@@ -112,6 +120,7 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/include/my_config.h.in
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
|
||||
ADD_SUBDIRECTORY(plugins)
|
||||
ADD_SUBDIRECTORY(libmariadb)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
IF(NOT WIN32)
|
||||
|
@@ -71,5 +71,6 @@ extern const char *client_errors[]; /* Error messages */
|
||||
#define CR_NEW_STMT_METADATA 2057
|
||||
#define CR_AUTH_PLUGIN_CANNOT_LOAD 2058
|
||||
#define CR_ALREADY_CONNECTED 2059
|
||||
#define CR_PLUGIN_FUNCTION_NOT_SUPPORTED 2060
|
||||
|
||||
#define SQLSTATE_UNKNOWN "HY000"
|
||||
|
@@ -137,6 +137,7 @@
|
||||
#cmakedefine HAVE_SIGWAIT 1
|
||||
#cmakedefine HAVE_SLEEP 1
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
#cmakedefine HAVE_SQLITE 1
|
||||
#cmakedefine HAVE_STPCPY 1
|
||||
#cmakedefine HAVE_STRERROR 1
|
||||
#cmakedefine HAVE_STRLCPY 1
|
||||
@@ -275,3 +276,4 @@
|
||||
#cmakedefine HAVE_THREADS 1
|
||||
#cmakedefine SHAREDIR "@SHAREDIR@"
|
||||
#cmakedefine DEFAULT_CHARSET_HOME "@DEFAULT_CHARSET_HOME@"
|
||||
#cmakedefine PLUGINDIR "@PLUGINDIR@"
|
||||
|
@@ -198,7 +198,7 @@ struct st_mysql_stmt
|
||||
|
||||
my_bool cursor_exists;
|
||||
|
||||
MYSQL_CMD_BUFFER cmd_buffer;
|
||||
void *ext_stmt;
|
||||
mysql_stmt_fetch_row_func fetch_row_func;
|
||||
unsigned int execute_count;/* count how many times the stmt was executed */
|
||||
mysql_stmt_use_or_store_func default_rset_handler;
|
||||
@@ -217,7 +217,6 @@ extern struct st_mysql_perm_bind mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY +
|
||||
unsigned long net_safe_read(MYSQL *mysql);
|
||||
void mysql_init_ps_subsystem(void);
|
||||
unsigned long net_field_length(unsigned char **packet);
|
||||
int simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, size_t length, my_bool skipp_check);
|
||||
/*
|
||||
* function prototypes
|
||||
*/
|
||||
|
@@ -184,7 +184,8 @@ enum mysql_option
|
||||
MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
|
||||
MYSQL_PLUGIN_DIR,
|
||||
MYSQL_DEFAULT_AUTH,
|
||||
MYSQL_PROGRESS_CALLBACK
|
||||
MYSQL_PROGRESS_CALLBACK,
|
||||
MYSQL_DATABASE_DRIVER=255
|
||||
};
|
||||
|
||||
enum mysql_status { MYSQL_STATUS_READY,
|
||||
@@ -233,9 +234,16 @@ struct st_mysql_options {
|
||||
struct st_mysql_options_extention *extension;
|
||||
};
|
||||
|
||||
typedef struct st_mariadb_db_driver
|
||||
{
|
||||
struct st_mariadb_client_plugin_DB *plugin;
|
||||
char *name;
|
||||
void *buffer;
|
||||
} MARIADB_DB_DRIVER;
|
||||
|
||||
typedef struct st_mysql {
|
||||
NET net; /* Communication parameters */
|
||||
unsigned char *unused;
|
||||
void *unused_0;
|
||||
char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
|
||||
char *info,*db;
|
||||
const struct charset_info_st *charset; /* character set */
|
||||
@@ -283,6 +291,7 @@ struct st_mysql_options_extention {
|
||||
double progress,
|
||||
const char *proc_info,
|
||||
unsigned int proc_info_length);
|
||||
MARIADB_DB_DRIVER *db_driver;
|
||||
};
|
||||
|
||||
typedef struct st_mysql_res {
|
||||
@@ -306,6 +315,7 @@ enum enum_mysql_timestamp_type
|
||||
MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2
|
||||
};
|
||||
|
||||
|
||||
typedef struct st_mysql_time
|
||||
{
|
||||
unsigned int year, month, day, hour, minute, second;
|
||||
@@ -449,7 +459,30 @@ const char * STDCALL mysql_get_server_name(MYSQL *mysql);
|
||||
|
||||
#include <my_stmt.h>
|
||||
|
||||
/* synonyms, alternate functions */
|
||||
/* these methods can be overwritten by db plugins */
|
||||
struct st_mysql_methods {
|
||||
MYSQL *(*db_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);
|
||||
void (*db_close)(MYSQL *mysql);
|
||||
int (*db_command)(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
size_t length, my_bool skipp_check, void *opt_arg);
|
||||
void (*db_skip_result)(MYSQL *mysql);
|
||||
int (*db_read_query_result)(MYSQL *mysql);
|
||||
MYSQL_DATA *(*db_read_rows)(MYSQL *mysql,MYSQL_FIELD *fields, unsigned int field_count);
|
||||
int (*db_read_one_row)(MYSQL *mysql,unsigned int fields,MYSQL_ROW row, unsigned long *lengths);
|
||||
/* prepared statements */
|
||||
my_bool (*db_supported_buffer_type)(enum enum_field_types type);
|
||||
my_bool (*db_read_prepare_response)(MYSQL_STMT *stmt);
|
||||
int (*db_read_stmt_result)(MYSQL *mysql);
|
||||
my_bool (*db_stmt_get_result_metadata)(MYSQL_STMT *stmt);
|
||||
my_bool (*db_stmt_get_param_metadata)(MYSQL_STMT *stmt);
|
||||
int (*db_stmt_read_all_rows)(MYSQL_STMT *stmt);
|
||||
int (*db_stmt_fetch)(MYSQL_STMT *stmt, unsigned char **row);
|
||||
int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row);
|
||||
void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt);
|
||||
};
|
||||
|
||||
/* synonyms/aliases functions */
|
||||
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
|
||||
#define mysql_library_init mysql_server_init
|
||||
#define mysql_library_end mysql_server_end
|
||||
|
@@ -35,11 +35,12 @@
|
||||
#endif
|
||||
|
||||
/* known plugin types */
|
||||
#define MYSQL_CLIENT_reserved1 0
|
||||
#define MYSQL_CLIENT_reserved2 1
|
||||
#define MYSQL_CLIENT_DB_PLUGIN 0
|
||||
#define MYSQL_CLIENT_reserved 1
|
||||
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
|
||||
|
||||
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
|
||||
#define MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION 0x0100
|
||||
|
||||
#define MYSQL_CLIENT_MAX_PLUGINS 3
|
||||
|
||||
@@ -68,6 +69,32 @@ struct st_mysql_client_plugin
|
||||
|
||||
struct st_mysql;
|
||||
|
||||
/********* database api plugin specific declarations **********/
|
||||
typedef struct st_mariadb_client_plugin_DB
|
||||
{
|
||||
MYSQL_CLIENT_PLUGIN_HEADER
|
||||
/* functions */
|
||||
struct st_mysql_methods *methods;
|
||||
/*
|
||||
MYSQL * (*db_connect)(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db, uint port,
|
||||
const char *unix_socket,unsigned long client_flag);
|
||||
void (*db_close)(MYSQL *mysql);
|
||||
int (*db_query)(MYSQL *mysql, const char *query, size_t query_len);
|
||||
int (*db_read_one_row)(MYSQL *mysql, uint fields, MYSQL_ROW row,
|
||||
ulong *lengths);
|
||||
MYSQL_DATA *(*db_read_all_rows)(MYSQL *mysql,
|
||||
MYSQL_FIELD *mysql_fields, uint fields);
|
||||
void (*db_query_end)(MYSQL *mysql);
|
||||
int (*db_stmt_prepare)(MYSQL_STMT *stmt, const char *stmt_str, ulong length);
|
||||
my_bool (*db_stmt_close)(MYSQL_STMT *stmt);
|
||||
my_bool (*is_supported_buffer_type)(enum enum_field_types type);
|
||||
int (*db_stmt_fetch)(MYSQL_STMT *stmt);
|
||||
int (*db_stmt_execute)(MYSQL_STMT *stmt); */
|
||||
} MARIADB_DB_PLUGIN;
|
||||
|
||||
#define MARIADB_DB_DRIVER(a) ((a)->ext_db)
|
||||
|
||||
/******** authentication plugin specific declarations *********/
|
||||
#include <mysql/plugin_auth_common.h>
|
||||
|
||||
|
@@ -102,7 +102,13 @@ ma_secure.c
|
||||
libmariadb_exports.def
|
||||
)
|
||||
|
||||
|
||||
IF(WITH_SQLITE)
|
||||
SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES}
|
||||
${CMAKE_SOURCE_DIR}/plugins/sqlite/sqlite3.c
|
||||
${CMAKE_SOURCE_DIR}/plugins/sqlite/sqlite_client_plugin.c)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/plugins/sqlite)
|
||||
ADD_DEFINITIONS(-DSQLITE_ENABLE_COLUMN_METADATA=1)
|
||||
ENDIF()
|
||||
|
||||
IF(ZLIB_FOUND)
|
||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||
@@ -144,7 +150,6 @@ IF(OPENSSL_FOUND)
|
||||
TARGET_LINK_LIBRARIES(libmariadb ${SSL_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
TARGET_LINK_LIBRARIES(libmariadb ws2_32)
|
||||
TARGET_LINK_LIBRARIES(mariadbclient ws2_32)
|
||||
|
@@ -60,7 +60,7 @@ static MEM_ROOT mem_root;
|
||||
|
||||
static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]=
|
||||
{
|
||||
0, /* these two are taken by Connector/C */
|
||||
MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION, /* these two are taken by Connector/C */
|
||||
0, /* these two are taken by Connector/C */
|
||||
MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION
|
||||
};
|
||||
@@ -264,7 +264,6 @@ int mysql_client_plugin_init()
|
||||
|
||||
for (builtin= mysql_client_builtins; *builtin; builtin++)
|
||||
add_plugin(&mysql, *builtin, 0, 0, unused);
|
||||
|
||||
pthread_mutex_unlock(&LOCK_load_client_plugin);
|
||||
|
||||
load_env_plugins(&mysql);
|
||||
|
@@ -140,6 +140,7 @@ const char *client_errors[]=
|
||||
/* 2057 */ "The number of parameters in bound buffers differs from number of columns in resultset",
|
||||
/* 2058 */ "Plugin %s could not be loaded: %s",
|
||||
/* 2059 */ "Can't connect twice. Already connected",
|
||||
/* 2060 */ "Plugin doesn't support this function",
|
||||
""
|
||||
};
|
||||
#endif
|
||||
|
@@ -72,6 +72,17 @@ extern const CHARSET_INFO * mysql_find_charset_nr(uint charsetnr);
|
||||
extern const CHARSET_INFO * mysql_find_charset_name(const char * const name);
|
||||
extern int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
|
||||
const char *data_plugin, const char *db);
|
||||
|
||||
/* prepare statement methods from my_stmt.c */
|
||||
extern my_bool mthd_supported_buffer_type(enum enum_field_types type);
|
||||
extern my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt);
|
||||
extern my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt);
|
||||
extern my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt);
|
||||
extern int mthd_stmt_fetch_row(MYSQL_STMT *stmt, unsigned char **row);
|
||||
extern int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row);
|
||||
extern int mthd_stmt_read_all_rows(MYSQL_STMT *stmt);
|
||||
extern void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt);
|
||||
|
||||
uint mysql_port=0;
|
||||
my_string mysql_unix_port=0;
|
||||
|
||||
@@ -81,6 +92,8 @@ my_string mysql_unix_port=0;
|
||||
#define CONNECT_TIMEOUT 0
|
||||
#endif
|
||||
|
||||
struct st_mysql_methods MARIADB_DEFAULT_METHODS;
|
||||
|
||||
#if defined(MSDOS) || defined(_WIN32)
|
||||
// socket_errno is defined in my_global.h for all platforms
|
||||
#define perror(A)
|
||||
@@ -94,10 +107,6 @@ my_string mysql_unix_port=0;
|
||||
#define native_password_plugin_name "mysql_native_password"
|
||||
const char *unknown_sqlstate= "HY000";
|
||||
|
||||
MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields,
|
||||
uint field_count);
|
||||
static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
|
||||
ulong *lengths);
|
||||
static void end_server(MYSQL *mysql);
|
||||
static void mysql_close_memory(MYSQL *mysql);
|
||||
void read_user_name(char *name);
|
||||
@@ -125,6 +134,7 @@ extern void mysql_client_plugin_deinit();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* A modified version of connect(). connect2() allows you to specify
|
||||
* a timeout value, in seconds, that we should wait until we
|
||||
@@ -523,14 +533,14 @@ void free_rows(MYSQL_DATA *cur)
|
||||
|
||||
|
||||
int
|
||||
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
size_t length, my_bool skipp_check)
|
||||
mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
size_t length, my_bool skipp_check, void *opt_arg)
|
||||
{
|
||||
NET *net= &mysql->net;
|
||||
int result= -1;
|
||||
init_sigpipe_variables
|
||||
|
||||
DBUG_ENTER("simple_command");
|
||||
DBUG_ENTER("mthd_my_send_command");
|
||||
|
||||
DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length));
|
||||
|
||||
@@ -591,6 +601,12 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
int
|
||||
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
size_t length, my_bool skipp_check, void *opt_arg)
|
||||
{
|
||||
return mysql->methods->db_command(mysql, command, arg, length, skipp_check, opt_arg);
|
||||
}
|
||||
|
||||
static void free_old_query(MYSQL *mysql)
|
||||
{
|
||||
@@ -762,6 +778,18 @@ end_server(MYSQL *mysql)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void mthd_my_skip_result(MYSQL *mysql)
|
||||
{
|
||||
ulong pkt_len;
|
||||
DBUG_ENTER("madb_skip_result");
|
||||
|
||||
do {
|
||||
pkt_len= net_safe_read(mysql);
|
||||
if (pkt_len == packet_error)
|
||||
break;
|
||||
} while (pkt_len > 8 || mysql->net.read_pos[0] != 254);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void STDCALL
|
||||
mysql_free_result(MYSQL_RES *result)
|
||||
@@ -772,14 +800,7 @@ mysql_free_result(MYSQL_RES *result)
|
||||
{
|
||||
if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
|
||||
{
|
||||
ulong pkt_len;
|
||||
DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
|
||||
|
||||
do {
|
||||
pkt_len= net_safe_read(result->handle);
|
||||
if (pkt_len == packet_error)
|
||||
break;
|
||||
} while (pkt_len > 8 || result->handle->net.read_pos[0] != 254);
|
||||
result->handle->methods->db_skip_result(result->handle);
|
||||
result->handle->status=MYSQL_STATUS_READY;
|
||||
}
|
||||
free_rows(result->data);
|
||||
@@ -806,7 +827,7 @@ static const char *default_options[]=
|
||||
"connect-timeout", "local-infile", "disable-local-infile",
|
||||
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
|
||||
"multi-results", "multi-statements", "multi-queries", "secure-auth",
|
||||
"report-data-truncation", "plugin-dir", "default-auth",
|
||||
"report-data-truncation", "plugin-dir", "default-auth", "database-type",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -820,7 +841,7 @@ enum option_val
|
||||
OPT_connect_timeout, OPT_local_infile, OPT_disable_local_infile,
|
||||
OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
|
||||
OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
|
||||
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth
|
||||
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, OPT_db_type
|
||||
};
|
||||
|
||||
#define OPT_SET_EXTENDED_VALUE(OPTS, KEY, VAL, IS_STRING) \
|
||||
@@ -829,8 +850,8 @@ enum option_val
|
||||
my_malloc(sizeof(struct st_mysql_options_extention), \
|
||||
MYF(MY_WME | MY_ZEROFILL)); \
|
||||
if (IS_STRING) { \
|
||||
my_free((OPTS)->extension->KEY, MYF(MY_ALLOW_ZERO_PTR)); \
|
||||
(OPTS)->extension->KEY= my_strdup((VAL), MYF(MY_WME)); \
|
||||
my_free((char *)(OPTS)->extension->KEY, MYF(MY_ALLOW_ZERO_PTR)); \
|
||||
(OPTS)->extension->KEY= my_strdup((char *)(VAL), MYF(MY_WME)); \
|
||||
} else \
|
||||
(OPTS)->extension->KEY= (VAL);
|
||||
|
||||
@@ -1139,7 +1160,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
||||
|
||||
/* Read all rows (fields or data) from server */
|
||||
|
||||
MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
uint fields)
|
||||
{
|
||||
uint field;
|
||||
@@ -1150,7 +1171,7 @@ MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
MYSQL_DATA *result;
|
||||
MYSQL_ROWS **prev_ptr,*cur;
|
||||
NET *net = &mysql->net;
|
||||
DBUG_ENTER("read_rows");
|
||||
DBUG_ENTER("madb_read_rows");
|
||||
|
||||
if ((pkt_len= net_safe_read(mysql)) == packet_error)
|
||||
DBUG_RETURN(0);
|
||||
@@ -1235,8 +1256,7 @@ MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
*/
|
||||
|
||||
|
||||
static int
|
||||
read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
|
||||
int mthd_my_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
|
||||
{
|
||||
uint field;
|
||||
ulong pkt_len,len;
|
||||
@@ -1395,6 +1415,17 @@ MYSQL * STDCALL
|
||||
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
uint port, const char *unix_socket,unsigned long client_flag)
|
||||
{
|
||||
if (!mysql->methods)
|
||||
mysql->methods= &MARIADB_DEFAULT_METHODS;
|
||||
|
||||
return mysql->methods->db_connect(mysql, host, user, passwd,
|
||||
db, port, unix_socket, client_flag);
|
||||
}
|
||||
|
||||
MYSQL *mthd_my_real_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
uint port, const char *unix_socket,unsigned long client_flag)
|
||||
{
|
||||
char buff[NAME_LEN+USERNAME_LENGTH+100];
|
||||
char *end, *end_pkt, *host_info,
|
||||
@@ -1944,7 +1975,7 @@ mysql_select_db(MYSQL *mysql, const char *db)
|
||||
DBUG_ENTER("mysql_select_db");
|
||||
DBUG_PRINT("enter",("db: '%s'",db));
|
||||
|
||||
if ((error=simple_command(mysql,MYSQL_COM_INIT_DB,db,(uint) strlen(db),0)))
|
||||
if ((error=simple_command(mysql,MYSQL_COM_INIT_DB,db,(uint) strlen(db),0,0)))
|
||||
DBUG_RETURN(error);
|
||||
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
|
||||
mysql->db=my_strdup(db,MYF(MY_WME));
|
||||
@@ -1989,6 +2020,7 @@ static void mysql_close_options(MYSQL *mysql)
|
||||
{
|
||||
my_free(mysql->options.extension->plugin_dir, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.extension->default_auth, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free((gptr)mysql->options.extension->db_driver, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2025,6 +2057,18 @@ void my_set_error(MYSQL *mysql,
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void mthd_my_close(MYSQL *mysql)
|
||||
{
|
||||
if (mysql->net.vio)
|
||||
{
|
||||
free_old_query(mysql);
|
||||
mysql->status=MYSQL_STATUS_READY; /* Force command */
|
||||
mysql->reconnect=0;
|
||||
simple_command(mysql,MYSQL_COM_QUIT,NullS,0,1,0);
|
||||
end_server(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
void STDCALL
|
||||
mysql_close(MYSQL *mysql)
|
||||
{
|
||||
@@ -2032,14 +2076,9 @@ mysql_close(MYSQL *mysql)
|
||||
if (mysql) /* Some simple safety */
|
||||
{
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
if (mysql->net.vio)
|
||||
{
|
||||
free_old_query(mysql);
|
||||
mysql->status=MYSQL_STATUS_READY; /* Force command */
|
||||
mysql->reconnect=0;
|
||||
simple_command(mysql,MYSQL_COM_QUIT,NullS,0,1);
|
||||
end_server(mysql);
|
||||
}
|
||||
|
||||
if (mysql->methods)
|
||||
mysql->methods->db_close(mysql);
|
||||
|
||||
/* reset the connection in all active statements
|
||||
todo: check stmt->mysql in mysql_stmt* functions ! */
|
||||
@@ -2082,10 +2121,10 @@ mysql_query(MYSQL *mysql, const char *query)
|
||||
int STDCALL
|
||||
mysql_send_query(MYSQL* mysql, const char* query, uint length)
|
||||
{
|
||||
return simple_command(mysql, MYSQL_COM_QUERY, query, length, 1);
|
||||
return simple_command(mysql, MYSQL_COM_QUERY, query, length, 1,0);
|
||||
}
|
||||
|
||||
int STDCALL mysql_read_query_result(MYSQL *mysql)
|
||||
int mthd_my_read_query_result(MYSQL *mysql)
|
||||
{
|
||||
uchar *pos;
|
||||
ulong field_count;
|
||||
@@ -2122,7 +2161,7 @@ get_info:
|
||||
mysql->server_status|= SERVER_STATUS_IN_TRANS;
|
||||
|
||||
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
|
||||
if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,8)))
|
||||
if (!(fields=mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,8)))
|
||||
DBUG_RETURN(-1);
|
||||
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
|
||||
(uint) field_count,1,
|
||||
@@ -2141,9 +2180,11 @@ mysql_real_query(MYSQL *mysql, const char *query, uint length)
|
||||
DBUG_PRINT("enter",("handle: %lx",mysql));
|
||||
DBUG_PRINT("query",("Query = \"%.255s\" length=%u",query, length));
|
||||
|
||||
if (simple_command(mysql,MYSQL_COM_QUERY,query,length,1))
|
||||
free_old_query(mysql);
|
||||
|
||||
if (simple_command(mysql,MYSQL_COM_QUERY,query,length,1,0))
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(mysql_read_query_result(mysql));
|
||||
DBUG_RETURN(mysql->methods->db_read_query_result(mysql));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@@ -2174,7 +2215,7 @@ mysql_store_result(MYSQL *mysql)
|
||||
}
|
||||
result->eof=1; /* Marker for buffered */
|
||||
result->lengths=(ulong*) (result+1);
|
||||
if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count)))
|
||||
if (!(result->data=mysql->methods->db_read_rows(mysql,mysql->fields,mysql->field_count)))
|
||||
{
|
||||
my_free((gptr) result,MYF(0));
|
||||
DBUG_RETURN(0);
|
||||
@@ -2254,24 +2295,23 @@ MYSQL_ROW STDCALL
|
||||
mysql_fetch_row(MYSQL_RES *res)
|
||||
{
|
||||
DBUG_ENTER("mysql_fetch_row");
|
||||
if (!res)
|
||||
return 0;
|
||||
if (!res->data)
|
||||
{ /* Unbufferred fetch */
|
||||
if (!res->eof)
|
||||
{
|
||||
if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths)))
|
||||
if (!(res->handle->methods->db_read_one_row(res->handle,res->field_count,res->row, res->lengths)))
|
||||
{
|
||||
res->row_count++;
|
||||
DBUG_RETURN(res->current_row=res->row);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info",("end of data"));
|
||||
res->eof=1;
|
||||
res->handle->status=MYSQL_STATUS_READY;
|
||||
/* Don't clear handle in mysql_free_results */
|
||||
res->handle=0;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN((MYSQL_ROW) NULL);
|
||||
}
|
||||
{
|
||||
@@ -2416,8 +2456,8 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
|
||||
LINT_INIT(query);
|
||||
|
||||
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
|
||||
if (simple_command(mysql,MYSQL_COM_FIELD_LIST,buff,(uint) (end-buff),1) ||
|
||||
!(query = read_rows(mysql,(MYSQL_FIELD*) 0,8)))
|
||||
if (simple_command(mysql,MYSQL_COM_FIELD_LIST,buff,(uint) (end-buff),1,0) ||
|
||||
!(query = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,8)))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
free_old_query(mysql);
|
||||
@@ -2449,12 +2489,12 @@ mysql_list_processes(MYSQL *mysql)
|
||||
DBUG_ENTER("mysql_list_processes");
|
||||
|
||||
LINT_INIT(fields);
|
||||
if (simple_command(mysql,MYSQL_COM_PROCESS_INFO,0,0,0))
|
||||
if (simple_command(mysql,MYSQL_COM_PROCESS_INFO,0,0,0,0))
|
||||
DBUG_RETURN(0);
|
||||
free_old_query(mysql);
|
||||
pos=(uchar*) mysql->net.read_pos;
|
||||
field_count=(uint) net_field_length(&pos);
|
||||
if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0,5)))
|
||||
if (!(fields = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,5)))
|
||||
DBUG_RETURN(NULL);
|
||||
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
|
||||
(my_bool) test(mysql->server_capabilities &
|
||||
@@ -2471,7 +2511,7 @@ mysql_create_db(MYSQL *mysql, const char *db)
|
||||
{
|
||||
DBUG_ENTER("mysql_createdb");
|
||||
DBUG_PRINT("enter",("db: %s",db));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_CREATE_DB,db, (uint) strlen(db),0));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_CREATE_DB,db, (uint) strlen(db),0,0));
|
||||
}
|
||||
|
||||
|
||||
@@ -2480,7 +2520,7 @@ mysql_drop_db(MYSQL *mysql, const char *db)
|
||||
{
|
||||
DBUG_ENTER("mysql_drop_db");
|
||||
DBUG_PRINT("enter",("db: %s",db));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_DROP_DB,db,(uint) strlen(db),0));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_DROP_DB,db,(uint) strlen(db),0,0));
|
||||
}
|
||||
|
||||
/* In 5.0 this version became an additional parameter shutdown_level */
|
||||
@@ -2490,7 +2530,7 @@ mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
|
||||
uchar s_level[2];
|
||||
DBUG_ENTER("mysql_shutdown");
|
||||
s_level[0]= (uchar)shutdown_level;
|
||||
DBUG_RETURN(simple_command(mysql, MYSQL_COM_SHUTDOWN, (char *)s_level, 1, 0));
|
||||
DBUG_RETURN(simple_command(mysql, MYSQL_COM_SHUTDOWN, (char *)s_level, 1, 0, 0));
|
||||
}
|
||||
|
||||
int STDCALL
|
||||
@@ -2499,7 +2539,7 @@ mysql_refresh(MYSQL *mysql,uint options)
|
||||
uchar bits[1];
|
||||
DBUG_ENTER("mysql_refresh");
|
||||
bits[0]= (uchar) options;
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_REFRESH,(char*) bits,1,0));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_REFRESH,(char*) bits,1,0,0));
|
||||
}
|
||||
|
||||
int STDCALL
|
||||
@@ -2509,7 +2549,7 @@ mysql_kill(MYSQL *mysql,ulong pid)
|
||||
DBUG_ENTER("mysql_kill");
|
||||
int4store(buff,pid);
|
||||
/* if we kill our own thread, reading the response packet will fail */
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_PROCESS_KILL,buff,4,0));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_PROCESS_KILL,buff,4,0,0));
|
||||
}
|
||||
|
||||
|
||||
@@ -2517,14 +2557,14 @@ int STDCALL
|
||||
mysql_dump_debug_info(MYSQL *mysql)
|
||||
{
|
||||
DBUG_ENTER("mysql_dump_debug_info");
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_DEBUG,0,0,0));
|
||||
DBUG_RETURN(simple_command(mysql,MYSQL_COM_DEBUG,0,0,0,0));
|
||||
}
|
||||
|
||||
char * STDCALL
|
||||
mysql_stat(MYSQL *mysql)
|
||||
{
|
||||
DBUG_ENTER("mysql_stat");
|
||||
if (simple_command(mysql,MYSQL_COM_STATISTICS,0,0,0))
|
||||
if (simple_command(mysql,MYSQL_COM_STATISTICS,0,0,0,0))
|
||||
return mysql->net.last_error;
|
||||
mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
|
||||
if (!mysql->net.read_pos[0])
|
||||
@@ -2541,11 +2581,11 @@ mysql_ping(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
DBUG_ENTER("mysql_ping");
|
||||
rc= simple_command(mysql,MYSQL_COM_PING,0,0,0);
|
||||
rc= simple_command(mysql,MYSQL_COM_PING,0,0,0,0);
|
||||
|
||||
/* if connection was terminated and reconnect is true, try again */
|
||||
if (rc!=0 && mysql->reconnect)
|
||||
rc= simple_command(mysql,MYSQL_COM_PING,0,0,0);
|
||||
rc= simple_command(mysql,MYSQL_COM_PING,0,0,0,0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2668,11 +2708,34 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
|
||||
(void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg;
|
||||
break;
|
||||
case MYSQL_PLUGIN_DIR:
|
||||
OPT_SET_EXTENDED_VALUE(&mysql->options, plugin_dir, (char *)arg , 1);
|
||||
OPT_SET_EXTENDED_VALUE(&mysql->options, plugin_dir, (char *)arg, 1);
|
||||
break;
|
||||
case MYSQL_DEFAULT_AUTH:
|
||||
OPT_SET_EXTENDED_VALUE(&mysql->options, default_auth, (char *)arg, 1);
|
||||
break;
|
||||
case MYSQL_DATABASE_DRIVER:
|
||||
{
|
||||
MARIADB_DB_PLUGIN *db_plugin;
|
||||
if (!(db_plugin= (MARIADB_DB_PLUGIN *)mysql_client_find_plugin(mysql, (char *)arg,
|
||||
MYSQL_CLIENT_DB_PLUGIN)))
|
||||
break;
|
||||
if (!mysql->options.extension)
|
||||
mysql->options.extension= (struct st_mysql_options_extention *)
|
||||
my_malloc(sizeof(struct st_mysql_options_extention),
|
||||
MYF(MY_WME | MY_ZEROFILL));
|
||||
if (!mysql->options.extension->db_driver)
|
||||
mysql->options.extension->db_driver= (MARIADB_DB_DRIVER *)
|
||||
my_malloc(sizeof(MARIADB_DB_DRIVER), MYF(MY_WME | MY_ZEROFILL));
|
||||
if (mysql->options.extension &&
|
||||
mysql->options.extension->db_driver)
|
||||
{
|
||||
mysql->options.extension->db_driver->plugin = db_plugin;
|
||||
mysql->options.extension->db_driver->buffer= NULL;
|
||||
mysql->options.extension->db_driver->name= (char *)db_plugin->name;
|
||||
mysql->methods= db_plugin->methods;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
@@ -2795,7 +2858,7 @@ int STDCALL mysql_next_result(MYSQL *mysql)
|
||||
|
||||
if (mysql->server_status & SERVER_MORE_RESULTS_EXIST)
|
||||
{
|
||||
DBUG_RETURN(mysql_read_query_result(mysql));
|
||||
DBUG_RETURN(mysql->methods->db_read_query_result(mysql));
|
||||
}
|
||||
|
||||
DBUG_RETURN(-1);
|
||||
@@ -3018,7 +3081,7 @@ int STDCALL mysql_set_server_option(MYSQL *mysql,
|
||||
char buffer[2];
|
||||
DBUG_ENTER("mysql_set_server_option");
|
||||
int2store(buffer, (uint)option);
|
||||
DBUG_RETURN(simple_command(mysql, MYSQL_COM_SET_OPTION, buffer, sizeof(buffer), 0));
|
||||
DBUG_RETURN(simple_command(mysql, MYSQL_COM_SET_OPTION, buffer, sizeof(buffer), 0, 0));
|
||||
}
|
||||
|
||||
ulong STDCALL mysql_get_client_version(void)
|
||||
@@ -3051,5 +3114,48 @@ my_bool STDCALL mariadb_connection(MYSQL *mysql)
|
||||
const char * STDCALL
|
||||
mysql_get_server_name(MYSQL *mysql)
|
||||
{
|
||||
if (mysql->options.extension &&
|
||||
mysql->options.extension->db_driver != NULL)
|
||||
return mysql->options.extension->db_driver->name;
|
||||
return mariadb_connection(mysql) ? "MariaDB" : "MySQL";
|
||||
}
|
||||
|
||||
/*
|
||||
* Default methods for a connection. These methods are
|
||||
* stored in mysql->methods and can be overwritten by
|
||||
* a plugin, e.g. for using another database
|
||||
*/
|
||||
struct st_mysql_methods MARIADB_DEFAULT_METHODS = {
|
||||
/* open a connection */
|
||||
mthd_my_real_connect,
|
||||
/* close connection */
|
||||
mthd_my_close,
|
||||
/* send command to server */
|
||||
mthd_my_send_cmd,
|
||||
/* skip result set */
|
||||
mthd_my_skip_result,
|
||||
/* read response packet */
|
||||
mthd_my_read_query_result,
|
||||
/* read all rows from a result set */
|
||||
mthd_my_read_rows,
|
||||
/* read one/next row */
|
||||
mthd_my_read_one_row,
|
||||
/* check if datatype is supported */
|
||||
mthd_supported_buffer_type,
|
||||
/* read response packet from prepare */
|
||||
mthd_stmt_read_prepare_response,
|
||||
/* read response from stmt execute */
|
||||
mthd_my_read_query_result,
|
||||
/* get result set metadata for a prepared statement */
|
||||
mthd_stmt_get_result_metadata,
|
||||
/* get param metadata for a prepared statement */
|
||||
mthd_stmt_get_param_metadata,
|
||||
/* read all rows (buffered) */
|
||||
mthd_stmt_read_all_rows,
|
||||
/* fetch one row (unbuffered) */
|
||||
mthd_stmt_fetch_row,
|
||||
/* store values in bind buffer */
|
||||
mthd_stmt_fetch_to_bind,
|
||||
/* skip unbuffered stmt result */
|
||||
mthd_stmt_flush_unbuffered
|
||||
};
|
||||
|
@@ -57,7 +57,6 @@ EXPORTS
|
||||
mysql_ping
|
||||
mysql_stmt_result_metadata
|
||||
mysql_query
|
||||
mysql_read_query_result
|
||||
mysql_real_connect
|
||||
mysql_real_escape_string
|
||||
mysql_real_query
|
||||
@@ -105,4 +104,3 @@ EXPORTS
|
||||
mysql_stmt_next_result
|
||||
mariadb_connection
|
||||
mysql_get_server_name
|
||||
|
||||
|
@@ -45,11 +45,19 @@ static auth_plugin_t old_password_client_plugin=
|
||||
NULL,
|
||||
old_password_auth_client
|
||||
};
|
||||
typedef struct st_mariadb_client_plugin_DBAPI dbapi_plugin_t;
|
||||
|
||||
#ifdef HAVE_SQLITE
|
||||
extern dbapi_plugin_t sqlite3_plugin;
|
||||
#endif
|
||||
|
||||
struct st_mysql_client_plugin *mysql_client_builtins[]=
|
||||
{
|
||||
(struct st_mysql_client_plugin *)&old_password_client_plugin,
|
||||
(struct st_mysql_client_plugin *)&native_password_client_plugin,
|
||||
#ifdef HAVE_SQLITE
|
||||
(struct st_mysql_client_plugin *)&sqlite3_plugin,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
|
@@ -57,11 +57,12 @@
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <mysql/client_plugin.h>
|
||||
|
||||
static my_bool is_not_null= 0;
|
||||
static my_bool is_null= 1;
|
||||
|
||||
my_bool is_supported_buffer_type(enum enum_field_types type)
|
||||
my_bool mthd_supported_buffer_type(enum enum_field_types type)
|
||||
{
|
||||
switch (type) {
|
||||
case MYSQL_TYPE_BIT:
|
||||
@@ -143,7 +144,7 @@ static int stmt_buffered_fetch(MYSQL_STMT *stmt, uchar **row)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmt_read_all_rows(MYSQL_STMT *stmt)
|
||||
int mthd_stmt_read_all_rows(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_DATA *result= &stmt->result;
|
||||
MYSQL_ROWS *current, **pprevious;
|
||||
@@ -251,7 +252,7 @@ static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row)
|
||||
int4store(buf, stmt->stmt_id);
|
||||
int4store(buf + STMT_ID_LENGTH, stmt->prefetch_rows);
|
||||
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_FETCH, (char *)buf, sizeof(buf), 1))
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_FETCH, (char *)buf, sizeof(buf), 1, stmt))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/* free previously allocated buffer */
|
||||
@@ -259,13 +260,13 @@ static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row)
|
||||
result->data= 0;
|
||||
result->rows= 0;
|
||||
|
||||
if (stmt_read_all_rows(stmt))
|
||||
if (stmt->mysql->methods->db_stmt_read_all_rows(stmt))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
DBUG_RETURN(stmt_buffered_fetch(stmt, row));
|
||||
}
|
||||
|
||||
static void stmt_flush_unbuffered(MYSQL_STMT *stmt)
|
||||
void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt)
|
||||
{
|
||||
ulong packet_len;
|
||||
while ((packet_len = net_safe_read(stmt->mysql)) != packet_error)
|
||||
@@ -273,7 +274,7 @@ static void stmt_flush_unbuffered(MYSQL_STMT *stmt)
|
||||
return;
|
||||
}
|
||||
|
||||
static int stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row)
|
||||
int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row)
|
||||
{
|
||||
uint i;
|
||||
size_t truncations= 0;
|
||||
@@ -728,6 +729,12 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
|
||||
for (i=0; i < stmt->param_count; i++)
|
||||
{
|
||||
if (stmt->mysql->methods->db_supported_buffer_type &&
|
||||
!stmt->mysql->methods->db_supported_buffer_type(stmt->params[i].buffer_type))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!stmt->params[i].is_null)
|
||||
stmt->params[i].is_null= &is_not_null;
|
||||
|
||||
@@ -824,7 +831,8 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
|
||||
for (i=0; i < stmt->field_count; i++)
|
||||
{
|
||||
if (!is_supported_buffer_type(bind[i].buffer_type))
|
||||
if (stmt->mysql->methods->db_supported_buffer_type &&
|
||||
!stmt->mysql->methods->db_supported_buffer_type(bind[i].buffer_type))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
@@ -892,13 +900,13 @@ my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
|
||||
/* check if all data are fetched */
|
||||
if (stmt->mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
stmt_flush_unbuffered(stmt);
|
||||
stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
if (stmt->state > MYSQL_STMT_INITTED)
|
||||
{
|
||||
int4store(stmt_id, stmt->stmt_id);
|
||||
if (simple_command(stmt->mysql,MYSQL_COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1))
|
||||
if (simple_command(stmt->mysql,MYSQL_COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1, stmt))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate, stmt->mysql->net.last_error);
|
||||
return 1;
|
||||
@@ -944,6 +952,11 @@ const char * STDCALL mysql_stmt_error(MYSQL_STMT *stmt)
|
||||
return (const char *)stmt->last_error;
|
||||
}
|
||||
|
||||
int mthd_stmt_fetch_row(MYSQL_STMT *stmt, unsigned char **row)
|
||||
{
|
||||
return stmt->fetch_row_func(stmt, row);
|
||||
}
|
||||
|
||||
int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
||||
{
|
||||
unsigned char *row;
|
||||
@@ -967,11 +980,9 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
||||
}
|
||||
|
||||
if (stmt->state == MYSQL_STMT_FETCH_DONE)
|
||||
{
|
||||
DBUG_RETURN(MYSQL_NO_DATA);
|
||||
}
|
||||
|
||||
if ((rc= stmt->fetch_row_func(stmt, &row)))
|
||||
if ((rc= stmt->mysql->methods->db_stmt_fetch(stmt, &row)))
|
||||
{
|
||||
stmt->state= MYSQL_STMT_FETCH_DONE;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
@@ -979,10 +990,11 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(MYSQL_NO_DATA);
|
||||
}
|
||||
|
||||
if ((rc= stmt_fetch_to_bind(stmt, row)))
|
||||
if ((rc= stmt->mysql->methods->db_stmt_fetch_to_bind(stmt, row)))
|
||||
{
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
stmt->state= MYSQL_STMT_USER_FETCHING;
|
||||
CLEAR_CLIENT_ERROR(stmt->mysql);
|
||||
CLEAR_CLIENT_STMT_ERROR(stmt);
|
||||
@@ -1066,7 +1078,7 @@ MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql)
|
||||
DBUG_RETURN(stmt);
|
||||
}
|
||||
|
||||
my_bool stmt_read_prepare_response(MYSQL_STMT *stmt)
|
||||
my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt)
|
||||
{
|
||||
ulong packet_length;
|
||||
uchar *p;
|
||||
@@ -1099,25 +1111,25 @@ my_bool stmt_read_prepare_response(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
my_bool stmt_get_param_metadata(MYSQL_STMT *stmt)
|
||||
my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_DATA *result;
|
||||
|
||||
DBUG_ENTER("stmt_get_param_metadata");
|
||||
|
||||
if (!(result= read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
free_rows(result);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
my_bool stmt_read_result_metadata(MYSQL_STMT *stmt)
|
||||
my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_DATA *result;
|
||||
DBUG_ENTER("stmt_read_result_metadata");
|
||||
|
||||
if (!(result= read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
DBUG_RETURN(1);
|
||||
if (!(stmt->fields= unpack_fields(result,&stmt->mem_root,
|
||||
stmt->field_count, 0,
|
||||
@@ -1157,28 +1169,30 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon
|
||||
stmt->field_count= 0;
|
||||
|
||||
int4store(stmt_id, stmt->stmt_id);
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1))
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1, stmt))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (simple_command(stmt->mysql,MYSQL_COM_STMT_PREPARE, query, length, 1))
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_PREPARE, query, length, 1, stmt))
|
||||
goto fail;
|
||||
|
||||
if (stmt_read_prepare_response(stmt))
|
||||
if (stmt->mysql->methods->db_read_prepare_response &&
|
||||
stmt->mysql->methods->db_read_prepare_response(stmt))
|
||||
goto fail;
|
||||
|
||||
/* metadata not supported yet */
|
||||
if (stmt->param_count && stmt_get_param_metadata(stmt))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (stmt->field_count && stmt_read_result_metadata(stmt))
|
||||
if (stmt->param_count &&
|
||||
stmt->mysql->methods->db_stmt_get_param_metadata(stmt))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* allocated bind buffer for parameters */
|
||||
if (stmt->field_count &&
|
||||
stmt->mysql->methods->db_stmt_get_result_metadata(stmt))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
if (stmt->param_count)
|
||||
{
|
||||
if (!(stmt->params= (MYSQL_BIND *)alloc_root(&stmt->mem_root, stmt->param_count * sizeof(MYSQL_BIND))))
|
||||
@@ -1237,7 +1251,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
int4store(buff, stmt->stmt_id);
|
||||
int4store(buff + STMT_ID_LENGTH, (int)~0);
|
||||
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_FETCH, buff, sizeof(buff), 1))
|
||||
if (simple_command(stmt->mysql, MYSQL_COM_STMT_FETCH, buff, sizeof(buff), 1, stmt))
|
||||
DBUG_RETURN(1);
|
||||
/* todo: cursor */
|
||||
}
|
||||
@@ -1248,7 +1262,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (stmt_read_all_rows(stmt))
|
||||
if (stmt->mysql->methods->db_stmt_read_all_rows(stmt))
|
||||
{
|
||||
/* error during read - reset stmt->data */
|
||||
free_root(&stmt->result.alloc, 0);
|
||||
@@ -1304,7 +1318,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
}
|
||||
if (stmt->state > MYSQL_STMT_WAITING_USE_OR_STORE && stmt->state < MYSQL_STMT_FETCH_DONE && !stmt->result.data)
|
||||
{
|
||||
stmt_flush_unbuffered(stmt);
|
||||
stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
@@ -1316,12 +1330,11 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
stmt->result_cursor= stmt->result.data= 0;
|
||||
stmt->result.rows= 0;
|
||||
}
|
||||
|
||||
request= (char *)mysql_stmt_execute_generate_request(stmt, &request_len);
|
||||
DBUG_PRINT("info",("request_len=%ld", request_len));
|
||||
|
||||
ret= test(simple_command(stmt->mysql, MYSQL_COM_STMT_EXECUTE, request, request_len, 1) ||
|
||||
mysql_read_query_result(stmt->mysql));
|
||||
ret= test(simple_command(stmt->mysql, MYSQL_COM_STMT_EXECUTE, request, request_len, 1, stmt) ||
|
||||
(stmt->mysql->methods->db_read_stmt_result && stmt->mysql->methods->db_read_stmt_result(stmt->mysql)));
|
||||
|
||||
if (request)
|
||||
my_free(request, MYF(0));
|
||||
@@ -1367,11 +1380,17 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
|
||||
for (i=0; i < stmt->field_count; i++)
|
||||
{
|
||||
if (stmt->mysql->fields[i].db)
|
||||
stmt->fields[i].db= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].db);
|
||||
if (stmt->mysql->fields[i].table)
|
||||
stmt->fields[i].table= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].table);
|
||||
if (stmt->mysql->fields[i].org_table)
|
||||
stmt->fields[i].org_table= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].org_table);
|
||||
if (stmt->mysql->fields[i].name)
|
||||
stmt->fields[i].name= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].name);
|
||||
if (stmt->mysql->fields[i].org_name)
|
||||
stmt->fields[i].org_name= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].org_name);
|
||||
if (stmt->mysql->fields[i].catalog)
|
||||
stmt->fields[i].catalog= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].catalog);
|
||||
stmt->fields[i].def= stmt->mysql->fields[i].def ? strdup_root(&stmt->mem_root, stmt->mysql->fields[i].def) : NULL;
|
||||
}
|
||||
@@ -1455,7 +1474,7 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->mysql->status!= MYSQL_STATUS_READY && stmt->field_count)
|
||||
{
|
||||
stmt_flush_unbuffered(stmt);
|
||||
stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
|
||||
@@ -1463,7 +1482,7 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
if (stmt->mysql->status == MYSQL_STATUS_READY)
|
||||
{
|
||||
int4store(cmd_buf, stmt->stmt_id);
|
||||
if ((ret= simple_command(stmt->mysql,MYSQL_COM_STMT_RESET, (char *)cmd_buf, sizeof(cmd_buf), 0)))
|
||||
if ((ret= simple_command(stmt->mysql,MYSQL_COM_STMT_RESET, (char *)cmd_buf, sizeof(cmd_buf), 0, stmt)))
|
||||
SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate,
|
||||
stmt->mysql->net.last_error);
|
||||
|
||||
@@ -1562,7 +1581,7 @@ my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
||||
int2store(cmd_buff + STMT_ID_LENGTH, param_number);
|
||||
memcpy(cmd_buff + STMT_ID_LENGTH + 2, data, length);
|
||||
stmt->params[param_number].long_data_used= 1;
|
||||
ret= simple_command(stmt->mysql,MYSQL_COM_STMT_SEND_LONG_DATA, (char *)cmd_buff, packet_len, 1);
|
||||
ret= simple_command(stmt->mysql,MYSQL_COM_STMT_SEND_LONG_DATA, (char *)cmd_buff, packet_len, 1, stmt);
|
||||
my_free((gptr)cmd_buff, MYF(MY_WME));
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
@@ -19,6 +19,9 @@ IF(UNIX)
|
||||
IF(MATH_LIBRARY)
|
||||
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -lm")
|
||||
ENDIF(MATH_LIBRARY)
|
||||
IF(WITH_SQLITE)
|
||||
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -lsqlite")
|
||||
ENDIF()
|
||||
ENDIF(UNIX)
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mariadb_config.c.in
|
||||
|
6
plugins/CMakeLists.txt
Normal file
6
plugins/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
FILE(GLOB plugin_dirs ${CMAKE_SOURCE_DIR}/plugins/*)
|
||||
FOREACH(dir ${plugin_dirs})
|
||||
IF (EXISTS ${dir}/CMakeLists.txt)
|
||||
ADD_SUBDIRECTORY(${dir})
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
22
plugins/sqlite/CMakeLists.txt
Normal file
22
plugins/sqlite/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
# If option WITH_SQLITE was specified, we build this plugin
|
||||
# as an internal plugin.
|
||||
|
||||
IF(NOT WITH_SQLITE)
|
||||
# ADD_DEFINITIONS(-DSQLITE_ENABLE_COLUMN_METADATA)
|
||||
#
|
||||
#ADD_LIBRARY(sqlite SHARED sqlite3.c)
|
||||
#ADD_LIBRARY(sqlite_client_plugin SHARED sqlite_client_plugin.c)
|
||||
#TARGET_LINK_LIBRARIES(sqlite_client_plugin sqlite)
|
||||
#
|
||||
#INSTALL(TARGETS
|
||||
# sqlite
|
||||
# RUNTIME DESTINATION "lib/mariadb"
|
||||
# LIBRARY DESTINATION "lib/mariadb"
|
||||
# ARCHIVE DESTINATION "lib/mariadb")
|
||||
#
|
||||
#INSTALL(TARGETS
|
||||
# sqlite_client_plugin
|
||||
# RUNTIME DESTINATION "plugins"
|
||||
# LIBRARY DESTINATION "plugins"
|
||||
# ARCHIVE DESTINATION "plugins")
|
||||
ENDIF()
|
137413
plugins/sqlite/sqlite3.c
Normal file
137413
plugins/sqlite/sqlite3.c
Normal file
File diff suppressed because it is too large
Load Diff
7160
plugins/sqlite/sqlite3.h
Normal file
7160
plugins/sqlite/sqlite3.h
Normal file
File diff suppressed because it is too large
Load Diff
447
plugins/sqlite/sqlite3ext.h
Normal file
447
plugins/sqlite/sqlite3ext.h
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
** 2006 June 7
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This header file defines the SQLite interface for use by
|
||||
** shared libraries that want to be imported as extensions into
|
||||
** an SQLite instance. Shared libraries that intend to be loaded
|
||||
** as extensions by SQLite should #include this file instead of
|
||||
** sqlite3.h.
|
||||
*/
|
||||
#ifndef _SQLITE3EXT_H_
|
||||
#define _SQLITE3EXT_H_
|
||||
#include "sqlite3.h"
|
||||
|
||||
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||
|
||||
/*
|
||||
** The following structure holds pointers to all of the SQLite API
|
||||
** routines.
|
||||
**
|
||||
** WARNING: In order to maintain backwards compatibility, add new
|
||||
** interfaces to the end of this structure only. If you insert new
|
||||
** interfaces in the middle of this structure, then older different
|
||||
** versions of SQLite will not be able to load each others' shared
|
||||
** libraries!
|
||||
*/
|
||||
struct sqlite3_api_routines {
|
||||
void * (*aggregate_context)(sqlite3_context*,int nBytes);
|
||||
int (*aggregate_count)(sqlite3_context*);
|
||||
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
|
||||
int (*bind_double)(sqlite3_stmt*,int,double);
|
||||
int (*bind_int)(sqlite3_stmt*,int,int);
|
||||
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
|
||||
int (*bind_null)(sqlite3_stmt*,int);
|
||||
int (*bind_parameter_count)(sqlite3_stmt*);
|
||||
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
|
||||
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
|
||||
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
|
||||
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
|
||||
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
|
||||
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
|
||||
int (*busy_timeout)(sqlite3*,int ms);
|
||||
int (*changes)(sqlite3*);
|
||||
int (*close)(sqlite3*);
|
||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const char*));
|
||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const void*));
|
||||
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
||||
int (*column_count)(sqlite3_stmt*pStmt);
|
||||
const char * (*column_database_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_database_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_decltype)(sqlite3_stmt*,int i);
|
||||
const void * (*column_decltype16)(sqlite3_stmt*,int);
|
||||
double (*column_double)(sqlite3_stmt*,int iCol);
|
||||
int (*column_int)(sqlite3_stmt*,int iCol);
|
||||
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
|
||||
const char * (*column_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_origin_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_origin_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_table_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_table_name16)(sqlite3_stmt*,int);
|
||||
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
|
||||
const void * (*column_text16)(sqlite3_stmt*,int iCol);
|
||||
int (*column_type)(sqlite3_stmt*,int iCol);
|
||||
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
|
||||
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
||||
int (*complete)(const char*sql);
|
||||
int (*complete16)(const void*sql);
|
||||
int (*create_collation)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
||||
int (*data_count)(sqlite3_stmt*pStmt);
|
||||
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
||||
int (*declare_vtab)(sqlite3*,const char*);
|
||||
int (*enable_shared_cache)(int);
|
||||
int (*errcode)(sqlite3*db);
|
||||
const char * (*errmsg)(sqlite3*);
|
||||
const void * (*errmsg16)(sqlite3*);
|
||||
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
|
||||
int (*expired)(sqlite3_stmt*);
|
||||
int (*finalize)(sqlite3_stmt*pStmt);
|
||||
void (*free)(void*);
|
||||
void (*free_table)(char**result);
|
||||
int (*get_autocommit)(sqlite3*);
|
||||
void * (*get_auxdata)(sqlite3_context*,int);
|
||||
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
|
||||
int (*global_recover)(void);
|
||||
void (*interruptx)(sqlite3*);
|
||||
sqlite_int64 (*last_insert_rowid)(sqlite3*);
|
||||
const char * (*libversion)(void);
|
||||
int (*libversion_number)(void);
|
||||
void *(*malloc)(int);
|
||||
char * (*mprintf)(const char*,...);
|
||||
int (*open)(const char*,sqlite3**);
|
||||
int (*open16)(const void*,sqlite3**);
|
||||
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
|
||||
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
|
||||
void *(*realloc)(void*,int);
|
||||
int (*reset)(sqlite3_stmt*pStmt);
|
||||
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_double)(sqlite3_context*,double);
|
||||
void (*result_error)(sqlite3_context*,const char*,int);
|
||||
void (*result_error16)(sqlite3_context*,const void*,int);
|
||||
void (*result_int)(sqlite3_context*,int);
|
||||
void (*result_int64)(sqlite3_context*,sqlite_int64);
|
||||
void (*result_null)(sqlite3_context*);
|
||||
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
|
||||
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
||||
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||
const char*,const char*),void*);
|
||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||
char * (*snprintf)(int,char*,const char*,...);
|
||||
int (*step)(sqlite3_stmt*);
|
||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||
char const**,char const**,int*,int*,int*);
|
||||
void (*thread_cleanup)(void);
|
||||
int (*total_changes)(sqlite3*);
|
||||
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
||||
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
||||
sqlite_int64),void*);
|
||||
void * (*user_data)(sqlite3_context*);
|
||||
const void * (*value_blob)(sqlite3_value*);
|
||||
int (*value_bytes)(sqlite3_value*);
|
||||
int (*value_bytes16)(sqlite3_value*);
|
||||
double (*value_double)(sqlite3_value*);
|
||||
int (*value_int)(sqlite3_value*);
|
||||
sqlite_int64 (*value_int64)(sqlite3_value*);
|
||||
int (*value_numeric_type)(sqlite3_value*);
|
||||
const unsigned char * (*value_text)(sqlite3_value*);
|
||||
const void * (*value_text16)(sqlite3_value*);
|
||||
const void * (*value_text16be)(sqlite3_value*);
|
||||
const void * (*value_text16le)(sqlite3_value*);
|
||||
int (*value_type)(sqlite3_value*);
|
||||
char *(*vmprintf)(const char*,va_list);
|
||||
/* Added ??? */
|
||||
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
|
||||
/* Added by 3.3.13 */
|
||||
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
int (*clear_bindings)(sqlite3_stmt*);
|
||||
/* Added by 3.4.1 */
|
||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
||||
void (*xDestroy)(void *));
|
||||
/* Added by 3.5.0 */
|
||||
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
||||
int (*blob_bytes)(sqlite3_blob*);
|
||||
int (*blob_close)(sqlite3_blob*);
|
||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
||||
int,sqlite3_blob**);
|
||||
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
||||
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*),
|
||||
void(*)(void*));
|
||||
int (*file_control)(sqlite3*,const char*,int,void*);
|
||||
sqlite3_int64 (*memory_highwater)(int);
|
||||
sqlite3_int64 (*memory_used)(void);
|
||||
sqlite3_mutex *(*mutex_alloc)(int);
|
||||
void (*mutex_enter)(sqlite3_mutex*);
|
||||
void (*mutex_free)(sqlite3_mutex*);
|
||||
void (*mutex_leave)(sqlite3_mutex*);
|
||||
int (*mutex_try)(sqlite3_mutex*);
|
||||
int (*open_v2)(const char*,sqlite3**,int,const char*);
|
||||
int (*release_memory)(int);
|
||||
void (*result_error_nomem)(sqlite3_context*);
|
||||
void (*result_error_toobig)(sqlite3_context*);
|
||||
int (*sleep)(int);
|
||||
void (*soft_heap_limit)(int);
|
||||
sqlite3_vfs *(*vfs_find)(const char*);
|
||||
int (*vfs_register)(sqlite3_vfs*,int);
|
||||
int (*vfs_unregister)(sqlite3_vfs*);
|
||||
int (*xthreadsafe)(void);
|
||||
void (*result_zeroblob)(sqlite3_context*,int);
|
||||
void (*result_error_code)(sqlite3_context*,int);
|
||||
int (*test_control)(int, ...);
|
||||
void (*randomness)(int,void*);
|
||||
sqlite3 *(*context_db_handle)(sqlite3_context*);
|
||||
int (*extended_result_codes)(sqlite3*,int);
|
||||
int (*limit)(sqlite3*,int,int);
|
||||
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
|
||||
const char *(*sql)(sqlite3_stmt*);
|
||||
int (*status)(int,int*,int*,int);
|
||||
int (*backup_finish)(sqlite3_backup*);
|
||||
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
|
||||
int (*backup_pagecount)(sqlite3_backup*);
|
||||
int (*backup_remaining)(sqlite3_backup*);
|
||||
int (*backup_step)(sqlite3_backup*,int);
|
||||
const char *(*compileoption_get)(int);
|
||||
int (*compileoption_used)(const char*);
|
||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*),
|
||||
void(*xDestroy)(void*));
|
||||
int (*db_config)(sqlite3*,int,...);
|
||||
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
||||
int (*db_status)(sqlite3*,int,int*,int*,int);
|
||||
int (*extended_errcode)(sqlite3*);
|
||||
void (*log)(int,const char*,...);
|
||||
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
|
||||
const char *(*sourceid)(void);
|
||||
int (*stmt_status)(sqlite3_stmt*,int,int);
|
||||
int (*strnicmp)(const char*,const char*,int);
|
||||
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
|
||||
int (*wal_autocheckpoint)(sqlite3*,int);
|
||||
int (*wal_checkpoint)(sqlite3*,const char*);
|
||||
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
||||
int (*vtab_config)(sqlite3*,int op,...);
|
||||
int (*vtab_on_conflict)(sqlite3*);
|
||||
};
|
||||
|
||||
/*
|
||||
** The following macros redefine the API routines so that they are
|
||||
** redirected throught the global sqlite3_api structure.
|
||||
**
|
||||
** This header file is also used by the loadext.c source file
|
||||
** (part of the main SQLite library - not an extension) so that
|
||||
** it can get access to the sqlite3_api_routines structure
|
||||
** definition. But the main library does not want to redefine
|
||||
** the API. So the redefinition macros are only valid if the
|
||||
** SQLITE_CORE macros is undefined.
|
||||
*/
|
||||
#ifndef SQLITE_CORE
|
||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
||||
#endif
|
||||
#define sqlite3_bind_blob sqlite3_api->bind_blob
|
||||
#define sqlite3_bind_double sqlite3_api->bind_double
|
||||
#define sqlite3_bind_int sqlite3_api->bind_int
|
||||
#define sqlite3_bind_int64 sqlite3_api->bind_int64
|
||||
#define sqlite3_bind_null sqlite3_api->bind_null
|
||||
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
|
||||
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
|
||||
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
|
||||
#define sqlite3_bind_text sqlite3_api->bind_text
|
||||
#define sqlite3_bind_text16 sqlite3_api->bind_text16
|
||||
#define sqlite3_bind_value sqlite3_api->bind_value
|
||||
#define sqlite3_busy_handler sqlite3_api->busy_handler
|
||||
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
|
||||
#define sqlite3_changes sqlite3_api->changes
|
||||
#define sqlite3_close sqlite3_api->close
|
||||
#define sqlite3_collation_needed sqlite3_api->collation_needed
|
||||
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
|
||||
#define sqlite3_column_blob sqlite3_api->column_blob
|
||||
#define sqlite3_column_bytes sqlite3_api->column_bytes
|
||||
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
|
||||
#define sqlite3_column_count sqlite3_api->column_count
|
||||
#define sqlite3_column_database_name sqlite3_api->column_database_name
|
||||
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
|
||||
#define sqlite3_column_decltype sqlite3_api->column_decltype
|
||||
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
|
||||
#define sqlite3_column_double sqlite3_api->column_double
|
||||
#define sqlite3_column_int sqlite3_api->column_int
|
||||
#define sqlite3_column_int64 sqlite3_api->column_int64
|
||||
#define sqlite3_column_name sqlite3_api->column_name
|
||||
#define sqlite3_column_name16 sqlite3_api->column_name16
|
||||
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
|
||||
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
|
||||
#define sqlite3_column_table_name sqlite3_api->column_table_name
|
||||
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
|
||||
#define sqlite3_column_text sqlite3_api->column_text
|
||||
#define sqlite3_column_text16 sqlite3_api->column_text16
|
||||
#define sqlite3_column_type sqlite3_api->column_type
|
||||
#define sqlite3_column_value sqlite3_api->column_value
|
||||
#define sqlite3_commit_hook sqlite3_api->commit_hook
|
||||
#define sqlite3_complete sqlite3_api->complete
|
||||
#define sqlite3_complete16 sqlite3_api->complete16
|
||||
#define sqlite3_create_collation sqlite3_api->create_collation
|
||||
#define sqlite3_create_collation16 sqlite3_api->create_collation16
|
||||
#define sqlite3_create_function sqlite3_api->create_function
|
||||
#define sqlite3_create_function16 sqlite3_api->create_function16
|
||||
#define sqlite3_create_module sqlite3_api->create_module
|
||||
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
|
||||
#define sqlite3_data_count sqlite3_api->data_count
|
||||
#define sqlite3_db_handle sqlite3_api->db_handle
|
||||
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
|
||||
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
|
||||
#define sqlite3_errcode sqlite3_api->errcode
|
||||
#define sqlite3_errmsg sqlite3_api->errmsg
|
||||
#define sqlite3_errmsg16 sqlite3_api->errmsg16
|
||||
#define sqlite3_exec sqlite3_api->exec
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_expired sqlite3_api->expired
|
||||
#endif
|
||||
#define sqlite3_finalize sqlite3_api->finalize
|
||||
#define sqlite3_free sqlite3_api->free
|
||||
#define sqlite3_free_table sqlite3_api->free_table
|
||||
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
|
||||
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
|
||||
#define sqlite3_get_table sqlite3_api->get_table
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_global_recover sqlite3_api->global_recover
|
||||
#endif
|
||||
#define sqlite3_interrupt sqlite3_api->interruptx
|
||||
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
|
||||
#define sqlite3_libversion sqlite3_api->libversion
|
||||
#define sqlite3_libversion_number sqlite3_api->libversion_number
|
||||
#define sqlite3_malloc sqlite3_api->malloc
|
||||
#define sqlite3_mprintf sqlite3_api->mprintf
|
||||
#define sqlite3_open sqlite3_api->open
|
||||
#define sqlite3_open16 sqlite3_api->open16
|
||||
#define sqlite3_prepare sqlite3_api->prepare
|
||||
#define sqlite3_prepare16 sqlite3_api->prepare16
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
#define sqlite3_profile sqlite3_api->profile
|
||||
#define sqlite3_progress_handler sqlite3_api->progress_handler
|
||||
#define sqlite3_realloc sqlite3_api->realloc
|
||||
#define sqlite3_reset sqlite3_api->reset
|
||||
#define sqlite3_result_blob sqlite3_api->result_blob
|
||||
#define sqlite3_result_double sqlite3_api->result_double
|
||||
#define sqlite3_result_error sqlite3_api->result_error
|
||||
#define sqlite3_result_error16 sqlite3_api->result_error16
|
||||
#define sqlite3_result_int sqlite3_api->result_int
|
||||
#define sqlite3_result_int64 sqlite3_api->result_int64
|
||||
#define sqlite3_result_null sqlite3_api->result_null
|
||||
#define sqlite3_result_text sqlite3_api->result_text
|
||||
#define sqlite3_result_text16 sqlite3_api->result_text16
|
||||
#define sqlite3_result_text16be sqlite3_api->result_text16be
|
||||
#define sqlite3_result_text16le sqlite3_api->result_text16le
|
||||
#define sqlite3_result_value sqlite3_api->result_value
|
||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
||||
#define sqlite3_snprintf sqlite3_api->snprintf
|
||||
#define sqlite3_step sqlite3_api->step
|
||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
||||
#define sqlite3_total_changes sqlite3_api->total_changes
|
||||
#define sqlite3_trace sqlite3_api->trace
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
|
||||
#endif
|
||||
#define sqlite3_update_hook sqlite3_api->update_hook
|
||||
#define sqlite3_user_data sqlite3_api->user_data
|
||||
#define sqlite3_value_blob sqlite3_api->value_blob
|
||||
#define sqlite3_value_bytes sqlite3_api->value_bytes
|
||||
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
|
||||
#define sqlite3_value_double sqlite3_api->value_double
|
||||
#define sqlite3_value_int sqlite3_api->value_int
|
||||
#define sqlite3_value_int64 sqlite3_api->value_int64
|
||||
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
|
||||
#define sqlite3_value_text sqlite3_api->value_text
|
||||
#define sqlite3_value_text16 sqlite3_api->value_text16
|
||||
#define sqlite3_value_text16be sqlite3_api->value_text16be
|
||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
||||
#define sqlite3_value_type sqlite3_api->value_type
|
||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
|
||||
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
|
||||
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
|
||||
#define sqlite3_blob_close sqlite3_api->blob_close
|
||||
#define sqlite3_blob_open sqlite3_api->blob_open
|
||||
#define sqlite3_blob_read sqlite3_api->blob_read
|
||||
#define sqlite3_blob_write sqlite3_api->blob_write
|
||||
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
|
||||
#define sqlite3_file_control sqlite3_api->file_control
|
||||
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
|
||||
#define sqlite3_memory_used sqlite3_api->memory_used
|
||||
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
|
||||
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
|
||||
#define sqlite3_mutex_free sqlite3_api->mutex_free
|
||||
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
|
||||
#define sqlite3_mutex_try sqlite3_api->mutex_try
|
||||
#define sqlite3_open_v2 sqlite3_api->open_v2
|
||||
#define sqlite3_release_memory sqlite3_api->release_memory
|
||||
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
|
||||
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
|
||||
#define sqlite3_sleep sqlite3_api->sleep
|
||||
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
|
||||
#define sqlite3_vfs_find sqlite3_api->vfs_find
|
||||
#define sqlite3_vfs_register sqlite3_api->vfs_register
|
||||
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
|
||||
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
|
||||
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
|
||||
#define sqlite3_result_error_code sqlite3_api->result_error_code
|
||||
#define sqlite3_test_control sqlite3_api->test_control
|
||||
#define sqlite3_randomness sqlite3_api->randomness
|
||||
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
|
||||
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
|
||||
#define sqlite3_limit sqlite3_api->limit
|
||||
#define sqlite3_next_stmt sqlite3_api->next_stmt
|
||||
#define sqlite3_sql sqlite3_api->sql
|
||||
#define sqlite3_status sqlite3_api->status
|
||||
#define sqlite3_backup_finish sqlite3_api->backup_finish
|
||||
#define sqlite3_backup_init sqlite3_api->backup_init
|
||||
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
|
||||
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
|
||||
#define sqlite3_backup_step sqlite3_api->backup_step
|
||||
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
|
||||
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
|
||||
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
|
||||
#define sqlite3_db_config sqlite3_api->db_config
|
||||
#define sqlite3_db_mutex sqlite3_api->db_mutex
|
||||
#define sqlite3_db_status sqlite3_api->db_status
|
||||
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
|
||||
#define sqlite3_log sqlite3_api->log
|
||||
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
|
||||
#define sqlite3_sourceid sqlite3_api->sourceid
|
||||
#define sqlite3_stmt_status sqlite3_api->stmt_status
|
||||
#define sqlite3_strnicmp sqlite3_api->strnicmp
|
||||
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
|
||||
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
||||
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
||||
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
||||
#endif /* SQLITE_CORE */
|
||||
|
||||
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
|
||||
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
|
||||
|
||||
#endif /* _SQLITE3EXT_H_ */
|
870
plugins/sqlite/sqlite_client_plugin.c
Normal file
870
plugins/sqlite/sqlite_client_plugin.c
Normal file
@@ -0,0 +1,870 @@
|
||||
/************************************************************************************
|
||||
Copyright (C) 2012 Monty Program AB
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||
|
||||
*************************************************************************************/
|
||||
#include <my_global.h>
|
||||
#include <my_sys.h>
|
||||
#include <m_string.h>
|
||||
#include <errmsg.h>
|
||||
#include <mysql.h>
|
||||
#include <mysql/client_plugin.h>
|
||||
#include <mysql.h>
|
||||
#include <mysql_com.h>
|
||||
#include <sqlite3.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errmsg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CLEAR_ERROR(a) my_set_error((a), 0, "", "");
|
||||
|
||||
enum enum_s3_status {S3_OK= 0, S3_RESULT_WAIT, S3_RESULT_FETCH, S3_FETCH_DONE};
|
||||
|
||||
typedef struct st_mariadb_sqlite
|
||||
{
|
||||
enum enum_s3_status status;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *stmt;
|
||||
ulong last_stmt_id;
|
||||
MYSQL_ROW row;
|
||||
} MARIADB_SQLT;
|
||||
|
||||
unsigned long s3_connection_id= 0;
|
||||
|
||||
void s3_close(MYSQL *mysql);
|
||||
|
||||
/**
|
||||
opens a sqlite connection, the parameter db (database name)
|
||||
must be specified. If db doesn't exist, it will be created.
|
||||
|
||||
@param MYSQL mysql handle
|
||||
@param host unused
|
||||
@param user unused
|
||||
@param passwd unused
|
||||
@param db database name (must be specified)
|
||||
@param port unused
|
||||
@param unix_socket unused
|
||||
@param client_flag unused (todo, support open flag)
|
||||
|
||||
@retval Pointer to a MYSQL connection handle
|
||||
or NULL if error
|
||||
**/
|
||||
MYSQL *s3_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
uint port, const char *unix_socket,unsigned long client_flag)
|
||||
{
|
||||
MARIADB_SQLT *dbhdl;
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
int rc;
|
||||
size_t len;
|
||||
|
||||
DBUG_ASSERT(s3_driver != NULL);
|
||||
|
||||
if (!db)
|
||||
return 0;
|
||||
|
||||
/* make sure that we don't leak in case s3_close was not called */
|
||||
if (s3_driver->name)
|
||||
s3_close(mysql);
|
||||
|
||||
if (!(s3_driver->buffer= my_malloc(sizeof(MARIADB_SQLT), MYF(MY_ZEROFILL))))
|
||||
{
|
||||
my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return 0;
|
||||
}
|
||||
dbhdl= (MARIADB_SQLT*)s3_driver->buffer;
|
||||
|
||||
if ((rc= sqlite3_open(db, (sqlite3 **)&dbhdl->db)))
|
||||
{
|
||||
my_set_error(mysql, sqlite3_errcode(dbhdl->db), SQLSTATE_UNKNOWN, sqlite3_errmsg(dbhdl->db));
|
||||
sqlite3_close(dbhdl->db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* connection settings */
|
||||
len= strlen(SQLITE_VERSION) + strlen(sqlite3_sourceid()) + 10;
|
||||
if (mysql->server_version= (char *)my_malloc(len, MYF(0)))
|
||||
{
|
||||
my_snprintf(mysql->server_version, len, "%s Sqlite %s", SQLITE_VERSION, sqlite3_sourceid());
|
||||
}
|
||||
mysql->db= my_strdup(db,MYF(MY_WME));
|
||||
|
||||
sqlite3_mutex_enter(sqlite3_db_mutex(dbhdl->db));
|
||||
mysql->thread_id= ++s3_connection_id;
|
||||
sqlite3_mutex_leave(sqlite3_db_mutex(dbhdl->db));
|
||||
|
||||
return mysql;
|
||||
}
|
||||
|
||||
void s3_skip_result(MYSQL *mysql)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
|
||||
sqlite3_finalize(db->stmt);
|
||||
db->stmt= NULL;
|
||||
}
|
||||
/**
|
||||
read field information and map information to
|
||||
MYSQL_FIELD
|
||||
|
||||
@param MYSQL connection handle
|
||||
|
||||
@retval Array of MYSQL_FIELD or NULL on
|
||||
error
|
||||
**/
|
||||
MYSQL_FIELD *s3_get_fields(MYSQL *mysql, sqlite3_stmt *stmt)
|
||||
{
|
||||
MYSQL_FIELD *field;
|
||||
int i, column_count;
|
||||
|
||||
if (!stmt ||
|
||||
!(column_count = sqlite3_column_count(stmt)))
|
||||
return NULL;
|
||||
|
||||
field= (MYSQL_FIELD*) alloc_root(&mysql->field_alloc,sizeof(MYSQL_FIELD)* column_count);
|
||||
memset(field, 0, sizeof(MYSQL_FIELD) * column_count);
|
||||
|
||||
for (i=0; i < column_count; i++)
|
||||
{
|
||||
/* map column types */
|
||||
switch(sqlite3_column_type(stmt, i)) {
|
||||
case SQLITE_NULL:
|
||||
field[i].type= MYSQL_TYPE_NULL;
|
||||
field[i].length= 0;
|
||||
field[i].charsetnr= 63; /* binary */
|
||||
break;
|
||||
case SQLITE_BLOB:
|
||||
field[i].type= MYSQL_TYPE_BLOB;
|
||||
field[i].length= sqlite3_column_bytes(stmt, i);
|
||||
field[i].charsetnr= 63; /* binary */
|
||||
break;
|
||||
case SQLITE_INTEGER:
|
||||
field[i].type= MYSQL_TYPE_LONG;
|
||||
field[i].length= 11;
|
||||
field[i].charsetnr= 63; /* binary */
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
field[i].type= MYSQL_TYPE_VAR_STRING;
|
||||
field[i].length= sqlite3_column_bytes(stmt, i);
|
||||
field[i].charsetnr= 33; /* utf8 */
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
field[i].type= MYSQL_TYPE_DOUBLE;
|
||||
field[i].length= 22;
|
||||
field[i].charsetnr= 63; /* binary */
|
||||
break;
|
||||
}
|
||||
/* we will update max_length in store/use result */
|
||||
field[i].max_length= 0;
|
||||
field[i].table= (char *)sqlite3_column_table_name(stmt, i);
|
||||
field[i].name= (char *)sqlite3_column_name(stmt, i);
|
||||
field[i].org_name= (char *)sqlite3_column_origin_name(stmt, i);
|
||||
field[i].db= (char *)sqlite3_column_database_name(stmt, i);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
return next row from a previous sqlite3_prepare
|
||||
call.
|
||||
|
||||
@param MYSQL connection handle
|
||||
@param length total length of row
|
||||
**/
|
||||
MYSQL_ROW s3_get_row(MYSQL *mysql, size_t *length)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
int rc= SQLITE_ROW;
|
||||
|
||||
*length= 0;
|
||||
|
||||
if (!mysql->field_count || db->status == S3_FETCH_DONE)
|
||||
return NULL;
|
||||
|
||||
if (db->status == S3_RESULT_WAIT) {
|
||||
db->row= (MYSQL_ROW)my_malloc(mysql->field_count * sizeof(char *), MYF(0));
|
||||
db->status= S3_RESULT_FETCH;
|
||||
}
|
||||
else
|
||||
rc= sqlite3_step(db->stmt);
|
||||
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < mysql->field_count; i++)
|
||||
{
|
||||
if ((db->row[i]= (char *)sqlite3_column_text(db->stmt, i)))
|
||||
{
|
||||
size_t slen= strlen(db->row[i]);
|
||||
*length += slen + 1;
|
||||
if (mysql->fields)
|
||||
if (slen > mysql->fields[i].max_length)
|
||||
mysql->fields[i].max_length= slen;
|
||||
}
|
||||
}
|
||||
return db->row;
|
||||
}
|
||||
/* nothing to fetch or error */
|
||||
db->status= S3_FETCH_DONE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
frees up memory and close db->stmt.
|
||||
|
||||
@param MYSQL connection handle
|
||||
|
||||
@retval void
|
||||
**/
|
||||
void db_query_end(MYSQL *mysql)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
|
||||
if (!db || !db->db)
|
||||
return;
|
||||
|
||||
if (db->stmt)
|
||||
{
|
||||
sqlite3_finalize(db->stmt);
|
||||
db->stmt= NULL;
|
||||
}
|
||||
if (db->row)
|
||||
{
|
||||
my_free((gptr)db->row, MYF(0));
|
||||
db->row= NULL;
|
||||
}
|
||||
db->status= S3_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
read one row. This function is used for unbuffered
|
||||
result sets and will be called from mysql_fetch_row()
|
||||
|
||||
@param mysql connection handle
|
||||
@param fields number of fields
|
||||
@param row row
|
||||
@param lengths total length of row
|
||||
|
||||
@return int 0 on success, != 0 on error
|
||||
**/
|
||||
int s3_read_one_row(MYSQL *mysql, uint fields,
|
||||
MYSQL_ROW row, ulong *lengths)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
uint field;
|
||||
size_t length;
|
||||
MYSQL_ROW s3row;
|
||||
|
||||
if (!mysql->field_count ||
|
||||
(db->status != S3_RESULT_WAIT && db->status != S3_RESULT_FETCH) ||
|
||||
!db->stmt)
|
||||
return -1;
|
||||
|
||||
if ((s3row= s3_get_row(mysql, &length)))
|
||||
{
|
||||
for (field=0 ; field < fields ; field++)
|
||||
{
|
||||
if (s3row[field] == NULL)
|
||||
*lengths++=0;
|
||||
else
|
||||
{
|
||||
row[field] = (char*) s3row[field];
|
||||
*lengths++=strlen(row[field]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* all rows fetched */
|
||||
sqlite3_finalize(db->stmt);
|
||||
db->stmt= NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
read all rows. This function will be called from
|
||||
mysql_store_result()
|
||||
|
||||
@param mysql connection handle
|
||||
@param mysql_fields array of field descriptors
|
||||
@param fields number of fields
|
||||
|
||||
@return MYSQL_DATA MYSQL_DATA array or NULL on error
|
||||
**/
|
||||
MYSQL_DATA *s3_read_all_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields,
|
||||
uint fields)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
MYSQL_DATA *result;
|
||||
MYSQL_ROW row;
|
||||
MYSQL_ROWS **prev_ptr, *cur;
|
||||
uint field;
|
||||
size_t length;
|
||||
char *to;
|
||||
|
||||
if (!mysql->field_count || db->status != S3_RESULT_WAIT || !db->stmt)
|
||||
return NULL;
|
||||
|
||||
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
|
||||
MYF(MY_ZEROFILL))))
|
||||
{
|
||||
my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return NULL;
|
||||
}
|
||||
init_alloc_root(&result->alloc, 8192, 0); /* Assume rowlength < 8192 */
|
||||
result->alloc.min_malloc=sizeof(MYSQL_ROWS);
|
||||
prev_ptr= &result->data;
|
||||
result->rows=0;
|
||||
result->fields= fields;
|
||||
|
||||
while ((row= s3_get_row(mysql, &length)))
|
||||
{
|
||||
result->rows++;
|
||||
if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
|
||||
sizeof(MYSQL_ROWS))) ||
|
||||
!(cur->data= ((MYSQL_ROW)
|
||||
alloc_root(&result->alloc,
|
||||
(fields+1)*sizeof(char *)+length))))
|
||||
{
|
||||
free_rows(result);
|
||||
my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return 0;
|
||||
}
|
||||
*prev_ptr=cur;
|
||||
prev_ptr= &cur->next;
|
||||
to= (char*) (cur->data+fields+1);
|
||||
for (field=0 ; field < fields ; field++)
|
||||
{
|
||||
if (row[field] == NULL)
|
||||
{ /* null field */
|
||||
cur->data[field] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len= strlen(row[field]);
|
||||
cur->data[field] = to;
|
||||
memcpy(to,(char*) row[field], len); to[len]=0;
|
||||
to+=len+1;
|
||||
}
|
||||
}
|
||||
cur->data[field]=to; /* End of last field */
|
||||
}
|
||||
*prev_ptr=0; /* last pointer is null */
|
||||
sqlite3_finalize(db->stmt);
|
||||
db->stmt= NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
db_query()
|
||||
|
||||
Executes a SQL query. Will be called from mysql_real_query
|
||||
|
||||
@param mysql connection handle
|
||||
@param query SQL statement
|
||||
@param length length of statement
|
||||
|
||||
@return int 0 on success, !=0 on error
|
||||
**/
|
||||
int s3_query(MYSQL *mysql, const char *query, size_t length)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
int rc;
|
||||
|
||||
CLEAR_ERROR(mysql);
|
||||
|
||||
rc= sqlite3_prepare_v2(db->db, query, (int)length, &db->stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
my_set_error(mysql, sqlite3_errcode(db->db), SQLSTATE_UNKNOWN, sqlite3_errmsg(db->db));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* since mariadb client library has different calls and logic
|
||||
for queries and prepared statements, we need to check for
|
||||
parameter markers */
|
||||
if (sqlite3_bind_parameter_count(db->stmt) > 0)
|
||||
{
|
||||
my_set_error(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN,
|
||||
"SQL statement contains parameter markers");
|
||||
db_query_end(mysql);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
s3_close()
|
||||
|
||||
terminates connection and frees previously allocated
|
||||
memory. Will be called from mysql_close().
|
||||
|
||||
@param mysql connection handle
|
||||
|
||||
@return void
|
||||
**/
|
||||
void s3_close(MYSQL *mysql)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
|
||||
if (!db)
|
||||
return;
|
||||
/* cleanup */
|
||||
if (db->db)
|
||||
{
|
||||
db_query_end(mysql);
|
||||
sqlite3_close_v2(db->db);
|
||||
}
|
||||
my_free((gptr)s3_driver->buffer, MYF(0));
|
||||
s3_driver->buffer= NULL;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
!! Experimental !!
|
||||
|
||||
Prepared statement (PS) support
|
||||
|
||||
!! Experimental !!
|
||||
|
||||
Todo:
|
||||
- Error handling: clear errors, handle stmt_execute return codes
|
||||
- bind_result not implemented yet
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
s3_stmt_prepare()
|
||||
|
||||
Prepares a statement for execution
|
||||
|
||||
@param MYSQL_STMT a stmt handle
|
||||
@param stmt_str statement SQL string
|
||||
@param length length of statement string
|
||||
|
||||
@return 0 on success, non-zero on error
|
||||
|
||||
**/
|
||||
int s3_stmt_prepare(MYSQL_STMT *stmt, const char *stmt_str, ulong length)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= stmt->mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
int rc;
|
||||
sqlite3_stmt *s3_stmt;
|
||||
|
||||
rc= sqlite3_prepare_v2(db->db, (char *)stmt_str, (int)length, &s3_stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, sqlite3_errcode(db->db), SQLSTATE_UNKNOWN, sqlite3_errmsg(db->db));
|
||||
return 1;
|
||||
}
|
||||
|
||||
stmt->ext_stmt= s3_stmt;
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
my_bool s3_read_prepare_response(MYSQL_STMT *stmt)
|
||||
{
|
||||
MARIADB_DB_DRIVER *s3_driver= stmt->mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
sqlite3_stmt *s3_stmt= stmt->ext_stmt;
|
||||
|
||||
/* set statement id */
|
||||
sqlite3_mutex_enter(sqlite3_db_mutex(db->db));
|
||||
stmt->stmt_id= ++db->last_stmt_id;
|
||||
sqlite3_mutex_leave(sqlite3_db_mutex(db->db));
|
||||
|
||||
stmt->param_count= sqlite3_bind_parameter_count(s3_stmt);
|
||||
stmt->field_count= sqlite3_column_count(s3_stmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
bind parameters to a prepared statement.
|
||||
This function has to be called before
|
||||
db_stmt_execute since sqlite doesn't support
|
||||
binding of addresses, so we need to rebind
|
||||
values for every statement execution.
|
||||
|
||||
@paran NYSQL_STMT
|
||||
@param MYSQL_BIND
|
||||
|
||||
@return bool
|
||||
**/
|
||||
my_bool s3_set_bind_params(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < stmt->param_count; i++)
|
||||
{
|
||||
switch(bind[i].buffer_type) {
|
||||
case MYSQL_TYPE_NULL:
|
||||
sqlite3_bind_null(stmt->ext_stmt, i + 1);
|
||||
break;
|
||||
case MYSQL_TYPE_TINY:
|
||||
sqlite3_bind_int(stmt->ext_stmt, i + 1, *(uchar *)stmt->params[i].buffer);
|
||||
break;
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
sqlite3_bind_int(stmt->ext_stmt, i + 1, *(short *)stmt->params[i].buffer);
|
||||
break;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
sqlite3_bind_double(stmt->ext_stmt, i + 1, *(double *)stmt->params[i].buffer);
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
sqlite3_bind_int(stmt->ext_stmt, i + 1, *(int32 *)stmt->params[i].buffer);
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
sqlite3_bind_int64(stmt->ext_stmt, i + 1, *(my_ulonglong *)stmt->params[i].buffer);
|
||||
break;
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
sqlite3_bind_blob(stmt->ext_stmt, i + 1, stmt->params[i].buffer,
|
||||
stmt->params[i].buffer_length, NULL);
|
||||
break;
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
sqlite3_bind_text(stmt->ext_stmt, i + 1, (char *)stmt->params[i].buffer,
|
||||
stmt->params[i].buffer_length, NULL);
|
||||
break;
|
||||
default:
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
check if the field type of bind variable is compatible.
|
||||
|
||||
@param type buffer type
|
||||
@retval int 1 if type is compatible, 0 if not
|
||||
**/
|
||||
my_bool s3_supported_buffer_type(enum enum_field_types type)
|
||||
{
|
||||
switch(type) {
|
||||
case MYSQL_TYPE_NULL:
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int s3_stmt_execute(MYSQL_STMT *stmt)
|
||||
{
|
||||
int rc;
|
||||
MARIADB_DB_DRIVER *s3_driver= stmt->mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
|
||||
/* Opposed to MariaDB sqlite doesn't support binding of variables/addresses, so
|
||||
* we need to reassign values before executing the statement */
|
||||
if (stmt->param_count)
|
||||
{
|
||||
sqlite3_reset(stmt->ext_stmt);
|
||||
if (s3_set_bind_params(stmt, stmt->params))
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc= sqlite3_step(stmt->ext_stmt);
|
||||
|
||||
switch(rc) {
|
||||
case SQLITE_ROW:
|
||||
stmt->mysql->field_count= sqlite3_column_count(stmt->ext_stmt);
|
||||
stmt->mysql->fields= s3_get_fields(stmt->mysql, stmt->ext_stmt);
|
||||
stmt->upsert_status.affected_rows= 0;
|
||||
rc= 0;
|
||||
break;
|
||||
case SQLITE_DONE: /* no rows returned */
|
||||
stmt->upsert_status.affected_rows= sqlite3_changes(db->db);
|
||||
stmt->upsert_status.last_insert_id= sqlite3_last_insert_rowid(db->db);
|
||||
rc= 0;
|
||||
break;
|
||||
case SQLITE_ERROR:
|
||||
SET_CLIENT_STMT_ERROR(stmt, sqlite3_errcode(db->db), SQLSTATE_UNKNOWN, sqlite3_errmsg(db->db));
|
||||
rc= 1;
|
||||
break;
|
||||
default:
|
||||
rc= 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int s3_stmt_fetch(MYSQL_STMT *stmt, unsigned char **row)
|
||||
{
|
||||
int rc= 0;
|
||||
|
||||
if (stmt->state != MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
rc= sqlite3_step(stmt->ext_stmt);
|
||||
|
||||
if (rc == SQLITE_DONE)
|
||||
{
|
||||
stmt->state= MYSQL_STMT_FETCH_DONE;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
/* to fetch data again, stmt must be executed again */
|
||||
return MYSQL_NO_DATA;
|
||||
}
|
||||
}
|
||||
return (rc != SQLITE_ROW) ? rc : 0;
|
||||
}
|
||||
|
||||
int s3_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row)
|
||||
{
|
||||
int i;
|
||||
longlong lval;
|
||||
double dval;
|
||||
char *buf;
|
||||
size_t s;
|
||||
|
||||
for (i=0; i < stmt->field_count; i++)
|
||||
{
|
||||
switch (stmt->bind[i].buffer_type) {
|
||||
case MYSQL_TYPE_NULL:
|
||||
*stmt->bind[i].is_null= 1;
|
||||
case MYSQL_TYPE_TINY:
|
||||
lval= sqlite3_column_int64(stmt->ext_stmt, i);
|
||||
if (stmt->bind[i].is_unsigned)
|
||||
*(uchar *)stmt->bind[i].buffer= (uchar)lval;
|
||||
else
|
||||
*(char *)stmt->bind[i].buffer= (char)lval;
|
||||
break;
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
lval= sqlite3_column_int64(stmt->ext_stmt, i);
|
||||
if (stmt->bind[i].is_unsigned)
|
||||
*(ushort *)stmt->bind[i].buffer= (ushort)lval;
|
||||
else
|
||||
*(short *)stmt->bind[i].buffer= (short)lval;
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
lval= sqlite3_column_int64(stmt->ext_stmt, i);
|
||||
if (stmt->bind[i].is_unsigned)
|
||||
*(ulong *)stmt->bind[i].buffer= (ulong)lval;
|
||||
else
|
||||
*(long *)stmt->bind[i].buffer= (long)lval;
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
lval= sqlite3_column_int64(stmt->ext_stmt, i);
|
||||
break;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
dval= sqlite3_column_double(stmt->ext_stmt, i);
|
||||
*(double *)stmt->bind[i].buffer= dval;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
buf= (char *)sqlite3_column_text(stmt->ext_stmt, i);
|
||||
if ((s= MIN(stmt->bind[i].buffer_length, sqlite3_column_bytes(stmt->ext_stmt, i))))
|
||||
memcpy(stmt->bind[i].buffer, buf, s);
|
||||
((char *)stmt->bind[i].buffer)[s]= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
my_bool s3_stmt_close(MYSQL_STMT *stmt)
|
||||
{
|
||||
int rc= sqlite3_finalize(stmt->ext_stmt);
|
||||
return (rc == SQLITE_OK) ? 0 : 1;
|
||||
}
|
||||
|
||||
int
|
||||
s3_db_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
size_t length, my_bool skipp_check, void *opt_arg)
|
||||
{
|
||||
int rc= 1;
|
||||
|
||||
switch (command) {
|
||||
case MYSQL_COM_QUERY:
|
||||
rc= s3_query(mysql, arg, length);
|
||||
break;
|
||||
case MYSQL_COM_STMT_PREPARE:
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)opt_arg;
|
||||
rc= s3_stmt_prepare(stmt, arg, length);
|
||||
}
|
||||
break;
|
||||
case MYSQL_COM_STMT_EXECUTE:
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)opt_arg;
|
||||
rc= s3_stmt_execute(stmt);
|
||||
}
|
||||
break;
|
||||
case MYSQL_COM_STMT_CLOSE:
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)opt_arg;
|
||||
s3_stmt_close(stmt);
|
||||
}
|
||||
break;
|
||||
case MYSQL_COM_STMT_RESET:
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)opt_arg;
|
||||
sqlite3_reset(stmt->ext_stmt);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!opt_arg)
|
||||
my_set_error(mysql, CR_PLUGIN_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN, 0);
|
||||
else
|
||||
SET_CLIENT_STMT_ERROR((MYSQL_STMT *)opt_arg, CR_PLUGIN_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN, 0);
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int s3_read_query_result(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
MARIADB_DB_DRIVER *s3_driver= mysql->options.extension->db_driver;
|
||||
MARIADB_SQLT *db= (MARIADB_SQLT *)s3_driver->buffer;
|
||||
|
||||
mysql->field_count= sqlite3_column_count(db->stmt);
|
||||
rc= sqlite3_step(db->stmt);
|
||||
|
||||
switch(rc) {
|
||||
case SQLITE_ERROR:
|
||||
case SQLITE_MISUSE:
|
||||
case SQLITE_BUSY:
|
||||
my_set_error(mysql, sqlite3_errcode(db->db), SQLSTATE_UNKNOWN, sqlite3_errmsg(db->db));
|
||||
sqlite3_finalize(db->stmt);
|
||||
db->stmt= NULL;
|
||||
rc= 1;
|
||||
break;
|
||||
|
||||
case SQLITE_ROW:
|
||||
db->status= S3_RESULT_WAIT;
|
||||
mysql->status = MYSQL_STATUS_GET_RESULT;
|
||||
mysql->fields= s3_get_fields(mysql, db->stmt);
|
||||
mysql->affected_rows= 0;
|
||||
rc= 0;
|
||||
break;
|
||||
case SQLITE_DONE: /* no rows returned */
|
||||
mysql->affected_rows= sqlite3_changes(db->db);
|
||||
mysql->insert_id= sqlite3_last_insert_rowid(db->db);
|
||||
mysql->status=MYSQL_STATUS_READY;
|
||||
if (!mysql->field_count)
|
||||
{
|
||||
sqlite3_finalize(db->stmt);
|
||||
db->stmt= NULL;
|
||||
}
|
||||
rc= 0;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
my_bool s3_get_param_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
my_bool s3_get_result_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
if (!(stmt->fields= s3_get_fields(stmt->mysql, stmt->ext_stmt)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s3_read_all_stmt_rows(MYSQL_STMT *stmt)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_PLUGIN_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void s3_stmt_flush_unbuffered(MYSQL_STMT *stmt)
|
||||
{
|
||||
sqlite3_reset(stmt->ext_stmt);
|
||||
}
|
||||
|
||||
int s3_read_stmt_result(MYSQL *mysql)
|
||||
{
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct st_mariadb_client_plugin_DB dbapi_plugin_t;
|
||||
|
||||
struct st_mysql_methods s3_methods = {
|
||||
s3_connect,
|
||||
s3_close,
|
||||
s3_db_command,
|
||||
s3_skip_result,
|
||||
s3_read_query_result,
|
||||
s3_read_all_rows,
|
||||
s3_read_one_row,
|
||||
s3_supported_buffer_type,
|
||||
s3_read_prepare_response,
|
||||
s3_read_stmt_result,
|
||||
s3_get_result_metadata,
|
||||
s3_get_param_metadata,
|
||||
s3_read_all_stmt_rows,
|
||||
s3_stmt_fetch,
|
||||
s3_stmt_fetch_to_bind
|
||||
};
|
||||
|
||||
dbapi_plugin_t sqlite3_plugin=
|
||||
{
|
||||
MYSQL_CLIENT_DB_PLUGIN,
|
||||
MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION,
|
||||
"sqlite",
|
||||
"Georg Richter",
|
||||
"Sqlite3 plugin for MariaDB client library",
|
||||
{1, 0, 0},
|
||||
NULL,
|
||||
NULL,
|
||||
&s3_methods
|
||||
};
|
@@ -21,7 +21,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/unittest/mytap)
|
||||
|
||||
SET(API_TESTS "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs"
|
||||
"sp" "result" "connection" "misc" "ssl" "ps_new")
|
||||
"sp" "result" "connection" "misc" "ssl" "ps_new" "sqlite3")
|
||||
|
||||
FOREACH(API_TEST ${API_TESTS})
|
||||
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
|
||||
|
@@ -33,6 +33,7 @@ static int basic_connect(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_FIELD *field;
|
||||
int rc;
|
||||
|
||||
MYSQL *my= mysql_init(NULL);
|
||||
@@ -45,6 +46,7 @@ static int basic_connect(MYSQL *mysql)
|
||||
check_mysql_rc(rc, my);
|
||||
|
||||
res= mysql_store_result(my);
|
||||
field= mysql_fetch_fields(res);
|
||||
FAIL_IF(!res, mysql_error(my));
|
||||
|
||||
while ((row= mysql_fetch_row(res)) != NULL)
|
||||
|
@@ -815,7 +815,7 @@ struct my_tests_st my_tests[] = {
|
||||
{"test_bug29692", test_bug29692, TEST_CONNECTION_NEW, CLIENT_FOUND_ROWS, NULL, NULL},
|
||||
{"test_bug31418", test_bug31418, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
{"test_bug6081", test_bug6081, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
{"test_frm_bug", test_frm_bug, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
// {"test_frm_bug", test_frm_bug, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"test_wl4166_1", test_wl4166_1, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"test_wl4166_2", test_wl4166_2, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"test_wl4166_3", test_wl4166_3, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
|
@@ -365,13 +365,14 @@ int check_variable(MYSQL *mysql, char *variable, char *value)
|
||||
MYSQL *test_connect(struct my_tests_st *test) {
|
||||
MYSQL *mysql;
|
||||
char query[255];
|
||||
|
||||
int i= 1;
|
||||
if (!(mysql = mysql_init(NULL))) {
|
||||
diag("%s", "mysql_init failed - exiting");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, "1");
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&i);
|
||||
|
||||
/* option handling */
|
||||
if (test && test->options) {
|
||||
@@ -388,9 +389,8 @@ MYSQL *test_connect(struct my_tests_st *test) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mysql_real_connect(mysql, hostname, username, password,
|
||||
NULL, port, socketname, (test) ? test->connect_flags:0)))
|
||||
schema, port, socketname, (test) ? test->connect_flags:0)))
|
||||
{
|
||||
diag("Couldn't establish connection to server %s. Error (%d): %s",
|
||||
hostname, mysql_errno(mysql), mysql_error(mysql));
|
||||
|
@@ -3709,6 +3709,55 @@ static int test_bug53311(MYSQL *mysql)
|
||||
|
||||
return OK;
|
||||
}
|
||||
#define PREPARE_SQL "EXPLAIN SELECT t1.*, t2.* FROM test AS t1, test AS t2"
|
||||
static int test_metadata(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test");
|
||||
check_mysql_rc(rc, mysql);
|
||||
rc= mysql_query(mysql, "CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=MYISAM");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
rc= mysql_query(mysql, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')");
|
||||
check_mysql_rc(rc, mysql);
|
||||
printf("Client=%s\n", mysql_get_client_info());
|
||||
printf("Server=%s\n", mysql_get_server_info(mysql));
|
||||
|
||||
{
|
||||
MYSQL_STMT * stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
fprintf(stderr, "Failed to init stmt: Error: %s\n", mysql_error(mysql));
|
||||
goto end;
|
||||
}
|
||||
if (mysql_stmt_prepare(stmt, PREPARE_SQL, sizeof(PREPARE_SQL) - 1)) {
|
||||
fprintf(stderr, "Failed to prepare stmt: Error: %s\n", mysql_stmt_error(stmt));
|
||||
goto end2;
|
||||
}
|
||||
if (mysql_stmt_execute(stmt)) {
|
||||
fprintf(stderr, "Failed to execute stmt: Error: %s\n", mysql_stmt_error(stmt));
|
||||
goto end2;
|
||||
}
|
||||
{
|
||||
MYSQL_FIELD * field = NULL;
|
||||
MYSQL_RES * res = mysql_stmt_result_metadata(stmt);
|
||||
if (!res) {
|
||||
fprintf(stderr, "Failed to get metadata: Error: %s\n", mysql_stmt_error(stmt));
|
||||
goto end2;
|
||||
}
|
||||
while ((field = mysql_fetch_field(res))) {
|
||||
printf("name=%s\n", field->name);
|
||||
printf("catalog=%s\n", field->catalog);
|
||||
}
|
||||
mysql_free_result(res);
|
||||
|
||||
}
|
||||
end2:
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_conc_5(MYSQL *mysql)
|
||||
{
|
||||
|
@@ -215,7 +215,6 @@ static int test_ssl_threads(MYSQL *mysql)
|
||||
|
||||
static int test_phpbug51647(MYSQL *my)
|
||||
{
|
||||
int rc;
|
||||
MYSQL* mysql;
|
||||
|
||||
if (check_skip_ssl())
|
||||
|
Reference in New Issue
Block a user