From d7e47a3f2da222d1923bf7d1a6077e32621ac46d Mon Sep 17 00:00:00 2001 From: oldmoe Date: Wed, 27 Aug 2008 02:05:20 +0300 Subject: [PATCH] extracted from neverblock-mysql --- README | 10 + ext/Makefile | 166 +++ ext/error_const.h | 536 ++++++++++ ext/extconf.rb | 70 ++ ext/mysql.c | 2322 +++++++++++++++++++++++++++++++++++++++++ mysqlplus.gemspec | 25 + test/test_evented.rb | 49 + test/test_threaded.rb | 22 + 8 files changed, 3200 insertions(+) create mode 100644 README create mode 100644 ext/Makefile create mode 100644 ext/error_const.h create mode 100644 ext/extconf.rb create mode 100644 ext/mysql.c create mode 100755 mysqlplus.gemspec create mode 100644 test/test_evented.rb create mode 100644 test/test_threaded.rb diff --git a/README b/README new file mode 100644 index 0000000..bafa2c5 --- /dev/null +++ b/README @@ -0,0 +1,10 @@ +== MySQLPlus + +An enhanced MySQL database driver. With support for async operations and threaded database access. + +=== Credits + +Roger Pack, for helping in the file descriptor hunt :) + +=== License +Ruby License, http://www.ruby-lang.org/en/LICENSE.txt. diff --git a/ext/Makefile b/ext/Makefile new file mode 100644 index 0000000..cac97bb --- /dev/null +++ b/ext/Makefile @@ -0,0 +1,166 @@ + +SHELL = /bin/sh + +#### Start of system configuration section. #### + +srcdir = . +topdir = /usr/local/include/ruby-1.9.0 +hdrdir = /usr/local/include/ruby-1.9.0 +arch_hdrdir = /usr/local/include/ruby-1.9.0/$(arch) +VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby +prefix = $(DESTDIR)/usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +sbindir = $(exec_prefix)/sbin +libexecdir = $(exec_prefix)/libexec +datarootdir = $(prefix)/share +datadir = $(datarootdir) +sysconfdir = $(prefix)/etc +sharedstatedir = $(prefix)/com +localstatedir = $(prefix)/var +includedir = $(prefix)/include +oldincludedir = $(DESTDIR)/usr/include +docdir = $(datarootdir)/doc/$(PACKAGE) +infodir = $(datarootdir)/info +htmldir = $(docdir) +dvidir = $(docdir) +pdfdir = $(docdir) +psdir = $(docdir) +libdir = $(exec_prefix)/lib +localedir = $(datarootdir)/locale +mandir = $(datarootdir)/man +sitedir = $(prefix)/lib/ruby/site_ruby +vendordir = $(prefix)/lib/ruby/vendor_ruby +rubyhdrdir = $(includedir)/ruby-$(MAJOR).$(MINOR).$(TEENY) +sitehdrdir = $(rubyhdrdir)/site_ruby +vendorhdrdir = $(rubyhdrdir)/vendor_ruby +rubylibdir = $(libdir)/ruby/$(ruby_version) +archdir = $(rubylibdir)/$(arch) +sitelibdir = $(sitedir)/$(ruby_version) +sitearchdir = $(sitelibdir)/$(sitearch) +vendorlibdir = $(vendordir)/$(ruby_version) +vendorarchdir = $(vendorlibdir)/$(sitearch) + +CC = gcc +CXX = g++ +LIBRUBY = $(LIBRUBY_A) +LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a +LIBRUBYARG_SHARED = -Wl,-R -Wl,$(libdir) -L$(libdir) +LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static +OUTFLAG = -o +COUTFLAG = -o + +RUBY_EXTCONF_H = +CFLAGS = -fPIC -g -O2 $(cflags) +INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) +DEFS = -D_FILE_OFFSET_BITS=64 +CPPFLAGS = -DHAVE_MYSQL_SSL_SET -DHAVE_RB_STR_SET_LEN -DHAVE_MYSQL_MYSQL_H -I/usr/local/include $(DEFS) $(cppflags) +CXXFLAGS = $(CFLAGS) -g -O2 +ldflags = -L. -rdynamic -Wl,-export-dynamic +dldflags = +archflag = +DLDFLAGS = $(ldflags) $(dldflags) $(archflag) +LDSHARED = $(CC) -shared +LDSHAREDXX = $(CXX) -shared +AR = ar +EXEEXT = + +RUBY_INSTALL_NAME = ruby +RUBY_SO_NAME = ruby +arch = i686-linux +sitearch = i686-linux +ruby_version = 1.9.0 +ruby = /usr/local/bin/ruby +RUBY = $(ruby) +RM = rm -f +MAKEDIRS = mkdir -p +INSTALL = /usr/bin/install -c +INSTALL_PROG = $(INSTALL) -m 0755 +INSTALL_DATA = $(INSTALL) -m 644 +COPY = cp + +#### End of system configuration section. #### + +preload = + +libpath = . $(libdir) /usr/local/lib +LIBPATH = -L. -L$(libdir) -Wl,-R$(libdir) -L/usr/local/lib -Wl,-R/usr/local/lib +DEFFILE = + +CLEANFILES = mkmf.log +DISTCLEANFILES = + +extout = +extout_prefix = +target_prefix = +LOCAL_LIBS = +LIBS = -lmysqlclient -lpthread -lrt -ldl -lcrypt -lm -lc +SRCS = mysql.c +OBJS = mysql.o +TARGET = mysqlplus +DLLIB = $(TARGET).so +EXTSTATIC = +STATIC_LIB = + +RUBYCOMMONDIR = $(sitedir)$(target_prefix) +RUBYLIBDIR = $(sitelibdir)$(target_prefix) +RUBYARCHDIR = $(sitearchdir)$(target_prefix) +HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) +ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) + +TARGET_SO = $(DLLIB) +CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map +CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak + +all: $(DLLIB) +static: $(STATIC_LIB) + +clean: + @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) + +distclean: clean + @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log + @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) + +realclean: distclean +install: install-so install-rb + +install-so: $(RUBYARCHDIR) +install-so: $(RUBYARCHDIR)/$(DLLIB) +$(RUBYARCHDIR)/$(DLLIB): $(DLLIB) + $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) +install-rb: pre-install-rb install-rb-default +install-rb-default: pre-install-rb-default +pre-install-rb: Makefile +pre-install-rb-default: Makefile +$(RUBYARCHDIR): + $(MAKEDIRS) $@ + +site-install: site-install-so site-install-rb +site-install-so: install-so +site-install-rb: install-rb + +.SUFFIXES: .c .m .cc .cxx .cpp .C .o + +.cc.o: + $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cxx.o: + $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cpp.o: + $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.C.o: + $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.c.o: + $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< + +$(DLLIB): $(OBJS) + @-$(RM) $(@) + $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) + + + +$(OBJS): ruby.h defines.h diff --git a/ext/error_const.h b/ext/error_const.h new file mode 100644 index 0000000..bd3583d --- /dev/null +++ b/ext/error_const.h @@ -0,0 +1,536 @@ + rb_define_mysql_const(CR_MIN_ERROR); + rb_define_mysql_const(CR_MAX_ERROR); + rb_define_mysql_const(CR_ERROR_FIRST); + rb_define_mysql_const(CR_UNKNOWN_ERROR); + rb_define_mysql_const(CR_SOCKET_CREATE_ERROR); + rb_define_mysql_const(CR_CONNECTION_ERROR); + rb_define_mysql_const(CR_CONN_HOST_ERROR); + rb_define_mysql_const(CR_IPSOCK_ERROR); + rb_define_mysql_const(CR_UNKNOWN_HOST); + rb_define_mysql_const(CR_SERVER_GONE_ERROR); + rb_define_mysql_const(CR_VERSION_ERROR); + rb_define_mysql_const(CR_OUT_OF_MEMORY); + rb_define_mysql_const(CR_WRONG_HOST_INFO); + rb_define_mysql_const(CR_LOCALHOST_CONNECTION); + rb_define_mysql_const(CR_TCP_CONNECTION); + rb_define_mysql_const(CR_SERVER_HANDSHAKE_ERR); + rb_define_mysql_const(CR_SERVER_LOST); + rb_define_mysql_const(CR_COMMANDS_OUT_OF_SYNC); + rb_define_mysql_const(CR_NAMEDPIPE_CONNECTION); + rb_define_mysql_const(CR_NAMEDPIPEWAIT_ERROR); + rb_define_mysql_const(CR_NAMEDPIPEOPEN_ERROR); + rb_define_mysql_const(CR_NAMEDPIPESETSTATE_ERROR); + rb_define_mysql_const(CR_CANT_READ_CHARSET); + rb_define_mysql_const(CR_NET_PACKET_TOO_LARGE); + rb_define_mysql_const(CR_EMBEDDED_CONNECTION); + rb_define_mysql_const(CR_PROBE_SLAVE_STATUS); + rb_define_mysql_const(CR_PROBE_SLAVE_HOSTS); + rb_define_mysql_const(CR_PROBE_SLAVE_CONNECT); + rb_define_mysql_const(CR_PROBE_MASTER_CONNECT); + rb_define_mysql_const(CR_SSL_CONNECTION_ERROR); + rb_define_mysql_const(CR_MALFORMED_PACKET); + rb_define_mysql_const(CR_WRONG_LICENSE); + rb_define_mysql_const(CR_NULL_POINTER); + rb_define_mysql_const(CR_NO_PREPARE_STMT); + rb_define_mysql_const(CR_PARAMS_NOT_BOUND); + rb_define_mysql_const(CR_DATA_TRUNCATED); + rb_define_mysql_const(CR_NO_PARAMETERS_EXISTS); + rb_define_mysql_const(CR_INVALID_PARAMETER_NO); + rb_define_mysql_const(CR_INVALID_BUFFER_USE); + rb_define_mysql_const(CR_UNSUPPORTED_PARAM_TYPE); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECTION); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECT_MAP_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_FILE_MAP_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_MAP_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_EVENT_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR); + rb_define_mysql_const(CR_SHARED_MEMORY_CONNECT_SET_ERROR); + rb_define_mysql_const(CR_CONN_UNKNOW_PROTOCOL); + rb_define_mysql_const(CR_INVALID_CONN_HANDLE); + rb_define_mysql_const(CR_SECURE_AUTH); + rb_define_mysql_const(CR_FETCH_CANCELED); + rb_define_mysql_const(CR_NO_DATA); + rb_define_mysql_const(CR_NO_STMT_METADATA); + rb_define_mysql_const(CR_NO_RESULT_SET); + rb_define_mysql_const(CR_NOT_IMPLEMENTED); + rb_define_mysql_const(CR_SERVER_LOST_EXTENDED); + rb_define_mysql_const(CR_ERROR_LAST); + rb_define_mysql_const(ER_ERROR_FIRST); + rb_define_mysql_const(ER_HASHCHK); + rb_define_mysql_const(ER_NISAMCHK); + rb_define_mysql_const(ER_NO); + rb_define_mysql_const(ER_YES); + rb_define_mysql_const(ER_CANT_CREATE_FILE); + rb_define_mysql_const(ER_CANT_CREATE_TABLE); + rb_define_mysql_const(ER_CANT_CREATE_DB); + rb_define_mysql_const(ER_DB_CREATE_EXISTS); + rb_define_mysql_const(ER_DB_DROP_EXISTS); + rb_define_mysql_const(ER_DB_DROP_DELETE); + rb_define_mysql_const(ER_DB_DROP_RMDIR); + rb_define_mysql_const(ER_CANT_DELETE_FILE); + rb_define_mysql_const(ER_CANT_FIND_SYSTEM_REC); + rb_define_mysql_const(ER_CANT_GET_STAT); + rb_define_mysql_const(ER_CANT_GET_WD); + rb_define_mysql_const(ER_CANT_LOCK); + rb_define_mysql_const(ER_CANT_OPEN_FILE); + rb_define_mysql_const(ER_FILE_NOT_FOUND); + rb_define_mysql_const(ER_CANT_READ_DIR); + rb_define_mysql_const(ER_CANT_SET_WD); + rb_define_mysql_const(ER_CHECKREAD); + rb_define_mysql_const(ER_DISK_FULL); + rb_define_mysql_const(ER_DUP_KEY); + rb_define_mysql_const(ER_ERROR_ON_CLOSE); + rb_define_mysql_const(ER_ERROR_ON_READ); + rb_define_mysql_const(ER_ERROR_ON_RENAME); + rb_define_mysql_const(ER_ERROR_ON_WRITE); + rb_define_mysql_const(ER_FILE_USED); + rb_define_mysql_const(ER_FILSORT_ABORT); + rb_define_mysql_const(ER_FORM_NOT_FOUND); + rb_define_mysql_const(ER_GET_ERRNO); + rb_define_mysql_const(ER_ILLEGAL_HA); + rb_define_mysql_const(ER_KEY_NOT_FOUND); + rb_define_mysql_const(ER_NOT_FORM_FILE); + rb_define_mysql_const(ER_NOT_KEYFILE); + rb_define_mysql_const(ER_OLD_KEYFILE); + rb_define_mysql_const(ER_OPEN_AS_READONLY); + rb_define_mysql_const(ER_OUTOFMEMORY); + rb_define_mysql_const(ER_OUT_OF_SORTMEMORY); + rb_define_mysql_const(ER_UNEXPECTED_EOF); + rb_define_mysql_const(ER_CON_COUNT_ERROR); + rb_define_mysql_const(ER_OUT_OF_RESOURCES); + rb_define_mysql_const(ER_BAD_HOST_ERROR); + rb_define_mysql_const(ER_HANDSHAKE_ERROR); + rb_define_mysql_const(ER_DBACCESS_DENIED_ERROR); + rb_define_mysql_const(ER_ACCESS_DENIED_ERROR); + rb_define_mysql_const(ER_NO_DB_ERROR); + rb_define_mysql_const(ER_UNKNOWN_COM_ERROR); + rb_define_mysql_const(ER_BAD_NULL_ERROR); + rb_define_mysql_const(ER_BAD_DB_ERROR); + rb_define_mysql_const(ER_TABLE_EXISTS_ERROR); + rb_define_mysql_const(ER_BAD_TABLE_ERROR); + rb_define_mysql_const(ER_NON_UNIQ_ERROR); + rb_define_mysql_const(ER_SERVER_SHUTDOWN); + rb_define_mysql_const(ER_BAD_FIELD_ERROR); + rb_define_mysql_const(ER_WRONG_FIELD_WITH_GROUP); + rb_define_mysql_const(ER_WRONG_GROUP_FIELD); + rb_define_mysql_const(ER_WRONG_SUM_SELECT); + rb_define_mysql_const(ER_WRONG_VALUE_COUNT); + rb_define_mysql_const(ER_TOO_LONG_IDENT); + rb_define_mysql_const(ER_DUP_FIELDNAME); + rb_define_mysql_const(ER_DUP_KEYNAME); + rb_define_mysql_const(ER_DUP_ENTRY); + rb_define_mysql_const(ER_WRONG_FIELD_SPEC); + rb_define_mysql_const(ER_PARSE_ERROR); + rb_define_mysql_const(ER_EMPTY_QUERY); + rb_define_mysql_const(ER_NONUNIQ_TABLE); + rb_define_mysql_const(ER_INVALID_DEFAULT); + rb_define_mysql_const(ER_MULTIPLE_PRI_KEY); + rb_define_mysql_const(ER_TOO_MANY_KEYS); + rb_define_mysql_const(ER_TOO_MANY_KEY_PARTS); + rb_define_mysql_const(ER_TOO_LONG_KEY); + rb_define_mysql_const(ER_KEY_COLUMN_DOES_NOT_EXITS); + rb_define_mysql_const(ER_BLOB_USED_AS_KEY); + rb_define_mysql_const(ER_TOO_BIG_FIELDLENGTH); + rb_define_mysql_const(ER_WRONG_AUTO_KEY); + rb_define_mysql_const(ER_READY); + rb_define_mysql_const(ER_NORMAL_SHUTDOWN); + rb_define_mysql_const(ER_GOT_SIGNAL); + rb_define_mysql_const(ER_SHUTDOWN_COMPLETE); + rb_define_mysql_const(ER_FORCING_CLOSE); + rb_define_mysql_const(ER_IPSOCK_ERROR); + rb_define_mysql_const(ER_NO_SUCH_INDEX); + rb_define_mysql_const(ER_WRONG_FIELD_TERMINATORS); + rb_define_mysql_const(ER_BLOBS_AND_NO_TERMINATED); + rb_define_mysql_const(ER_TEXTFILE_NOT_READABLE); + rb_define_mysql_const(ER_FILE_EXISTS_ERROR); + rb_define_mysql_const(ER_LOAD_INFO); + rb_define_mysql_const(ER_ALTER_INFO); + rb_define_mysql_const(ER_WRONG_SUB_KEY); + rb_define_mysql_const(ER_CANT_REMOVE_ALL_FIELDS); + rb_define_mysql_const(ER_CANT_DROP_FIELD_OR_KEY); + rb_define_mysql_const(ER_INSERT_INFO); + rb_define_mysql_const(ER_UPDATE_TABLE_USED); + rb_define_mysql_const(ER_NO_SUCH_THREAD); + rb_define_mysql_const(ER_KILL_DENIED_ERROR); + rb_define_mysql_const(ER_NO_TABLES_USED); + rb_define_mysql_const(ER_TOO_BIG_SET); + rb_define_mysql_const(ER_NO_UNIQUE_LOGFILE); + rb_define_mysql_const(ER_TABLE_NOT_LOCKED_FOR_WRITE); + rb_define_mysql_const(ER_TABLE_NOT_LOCKED); + rb_define_mysql_const(ER_BLOB_CANT_HAVE_DEFAULT); + rb_define_mysql_const(ER_WRONG_DB_NAME); + rb_define_mysql_const(ER_WRONG_TABLE_NAME); + rb_define_mysql_const(ER_TOO_BIG_SELECT); + rb_define_mysql_const(ER_UNKNOWN_ERROR); + rb_define_mysql_const(ER_UNKNOWN_PROCEDURE); + rb_define_mysql_const(ER_WRONG_PARAMCOUNT_TO_PROCEDURE); + rb_define_mysql_const(ER_WRONG_PARAMETERS_TO_PROCEDURE); + rb_define_mysql_const(ER_UNKNOWN_TABLE); + rb_define_mysql_const(ER_FIELD_SPECIFIED_TWICE); + rb_define_mysql_const(ER_INVALID_GROUP_FUNC_USE); + rb_define_mysql_const(ER_UNSUPPORTED_EXTENSION); + rb_define_mysql_const(ER_TABLE_MUST_HAVE_COLUMNS); + rb_define_mysql_const(ER_RECORD_FILE_FULL); + rb_define_mysql_const(ER_UNKNOWN_CHARACTER_SET); + rb_define_mysql_const(ER_TOO_MANY_TABLES); + rb_define_mysql_const(ER_TOO_MANY_FIELDS); + rb_define_mysql_const(ER_TOO_BIG_ROWSIZE); + rb_define_mysql_const(ER_STACK_OVERRUN); + rb_define_mysql_const(ER_WRONG_OUTER_JOIN); + rb_define_mysql_const(ER_NULL_COLUMN_IN_INDEX); + rb_define_mysql_const(ER_CANT_FIND_UDF); + rb_define_mysql_const(ER_CANT_INITIALIZE_UDF); + rb_define_mysql_const(ER_UDF_NO_PATHS); + rb_define_mysql_const(ER_UDF_EXISTS); + rb_define_mysql_const(ER_CANT_OPEN_LIBRARY); + rb_define_mysql_const(ER_CANT_FIND_DL_ENTRY); + rb_define_mysql_const(ER_FUNCTION_NOT_DEFINED); + rb_define_mysql_const(ER_HOST_IS_BLOCKED); + rb_define_mysql_const(ER_HOST_NOT_PRIVILEGED); + rb_define_mysql_const(ER_PASSWORD_ANONYMOUS_USER); + rb_define_mysql_const(ER_PASSWORD_NOT_ALLOWED); + rb_define_mysql_const(ER_PASSWORD_NO_MATCH); + rb_define_mysql_const(ER_UPDATE_INFO); + rb_define_mysql_const(ER_CANT_CREATE_THREAD); + rb_define_mysql_const(ER_WRONG_VALUE_COUNT_ON_ROW); + rb_define_mysql_const(ER_CANT_REOPEN_TABLE); + rb_define_mysql_const(ER_INVALID_USE_OF_NULL); + rb_define_mysql_const(ER_REGEXP_ERROR); + rb_define_mysql_const(ER_MIX_OF_GROUP_FUNC_AND_FIELDS); + rb_define_mysql_const(ER_NONEXISTING_GRANT); + rb_define_mysql_const(ER_TABLEACCESS_DENIED_ERROR); + rb_define_mysql_const(ER_COLUMNACCESS_DENIED_ERROR); + rb_define_mysql_const(ER_ILLEGAL_GRANT_FOR_TABLE); + rb_define_mysql_const(ER_GRANT_WRONG_HOST_OR_USER); + rb_define_mysql_const(ER_NO_SUCH_TABLE); + rb_define_mysql_const(ER_NONEXISTING_TABLE_GRANT); + rb_define_mysql_const(ER_NOT_ALLOWED_COMMAND); + rb_define_mysql_const(ER_SYNTAX_ERROR); + rb_define_mysql_const(ER_DELAYED_CANT_CHANGE_LOCK); + rb_define_mysql_const(ER_TOO_MANY_DELAYED_THREADS); + rb_define_mysql_const(ER_ABORTING_CONNECTION); + rb_define_mysql_const(ER_NET_PACKET_TOO_LARGE); + rb_define_mysql_const(ER_NET_READ_ERROR_FROM_PIPE); + rb_define_mysql_const(ER_NET_FCNTL_ERROR); + rb_define_mysql_const(ER_NET_PACKETS_OUT_OF_ORDER); + rb_define_mysql_const(ER_NET_UNCOMPRESS_ERROR); + rb_define_mysql_const(ER_NET_READ_ERROR); + rb_define_mysql_const(ER_NET_READ_INTERRUPTED); + rb_define_mysql_const(ER_NET_ERROR_ON_WRITE); + rb_define_mysql_const(ER_NET_WRITE_INTERRUPTED); + rb_define_mysql_const(ER_TOO_LONG_STRING); + rb_define_mysql_const(ER_TABLE_CANT_HANDLE_BLOB); + rb_define_mysql_const(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT); + rb_define_mysql_const(ER_DELAYED_INSERT_TABLE_LOCKED); + rb_define_mysql_const(ER_WRONG_COLUMN_NAME); + rb_define_mysql_const(ER_WRONG_KEY_COLUMN); + rb_define_mysql_const(ER_WRONG_MRG_TABLE); + rb_define_mysql_const(ER_DUP_UNIQUE); + rb_define_mysql_const(ER_BLOB_KEY_WITHOUT_LENGTH); + rb_define_mysql_const(ER_PRIMARY_CANT_HAVE_NULL); + rb_define_mysql_const(ER_TOO_MANY_ROWS); + rb_define_mysql_const(ER_REQUIRES_PRIMARY_KEY); + rb_define_mysql_const(ER_NO_RAID_COMPILED); + rb_define_mysql_const(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); + rb_define_mysql_const(ER_KEY_DOES_NOT_EXITS); + rb_define_mysql_const(ER_CHECK_NO_SUCH_TABLE); + rb_define_mysql_const(ER_CHECK_NOT_IMPLEMENTED); + rb_define_mysql_const(ER_CANT_DO_THIS_DURING_AN_TRANSACTION); + rb_define_mysql_const(ER_ERROR_DURING_COMMIT); + rb_define_mysql_const(ER_ERROR_DURING_ROLLBACK); + rb_define_mysql_const(ER_ERROR_DURING_FLUSH_LOGS); + rb_define_mysql_const(ER_ERROR_DURING_CHECKPOINT); + rb_define_mysql_const(ER_NEW_ABORTING_CONNECTION); + rb_define_mysql_const(ER_DUMP_NOT_IMPLEMENTED); + rb_define_mysql_const(ER_FLUSH_MASTER_BINLOG_CLOSED); + rb_define_mysql_const(ER_INDEX_REBUILD); + rb_define_mysql_const(ER_MASTER); + rb_define_mysql_const(ER_MASTER_NET_READ); + rb_define_mysql_const(ER_MASTER_NET_WRITE); + rb_define_mysql_const(ER_FT_MATCHING_KEY_NOT_FOUND); + rb_define_mysql_const(ER_LOCK_OR_ACTIVE_TRANSACTION); + rb_define_mysql_const(ER_UNKNOWN_SYSTEM_VARIABLE); + rb_define_mysql_const(ER_CRASHED_ON_USAGE); + rb_define_mysql_const(ER_CRASHED_ON_REPAIR); + rb_define_mysql_const(ER_WARNING_NOT_COMPLETE_ROLLBACK); + rb_define_mysql_const(ER_TRANS_CACHE_FULL); + rb_define_mysql_const(ER_SLAVE_MUST_STOP); + rb_define_mysql_const(ER_SLAVE_NOT_RUNNING); + rb_define_mysql_const(ER_BAD_SLAVE); + rb_define_mysql_const(ER_MASTER_INFO); + rb_define_mysql_const(ER_SLAVE_THREAD); + rb_define_mysql_const(ER_TOO_MANY_USER_CONNECTIONS); + rb_define_mysql_const(ER_SET_CONSTANTS_ONLY); + rb_define_mysql_const(ER_LOCK_WAIT_TIMEOUT); + rb_define_mysql_const(ER_LOCK_TABLE_FULL); + rb_define_mysql_const(ER_READ_ONLY_TRANSACTION); + rb_define_mysql_const(ER_DROP_DB_WITH_READ_LOCK); + rb_define_mysql_const(ER_CREATE_DB_WITH_READ_LOCK); + rb_define_mysql_const(ER_WRONG_ARGUMENTS); + rb_define_mysql_const(ER_NO_PERMISSION_TO_CREATE_USER); + rb_define_mysql_const(ER_UNION_TABLES_IN_DIFFERENT_DIR); + rb_define_mysql_const(ER_LOCK_DEADLOCK); + rb_define_mysql_const(ER_TABLE_CANT_HANDLE_FT); + rb_define_mysql_const(ER_CANNOT_ADD_FOREIGN); + rb_define_mysql_const(ER_NO_REFERENCED_ROW); + rb_define_mysql_const(ER_ROW_IS_REFERENCED); + rb_define_mysql_const(ER_CONNECT_TO_MASTER); + rb_define_mysql_const(ER_QUERY_ON_MASTER); + rb_define_mysql_const(ER_ERROR_WHEN_EXECUTING_COMMAND); + rb_define_mysql_const(ER_WRONG_USAGE); + rb_define_mysql_const(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT); + rb_define_mysql_const(ER_CANT_UPDATE_WITH_READLOCK); + rb_define_mysql_const(ER_MIXING_NOT_ALLOWED); + rb_define_mysql_const(ER_DUP_ARGUMENT); + rb_define_mysql_const(ER_USER_LIMIT_REACHED); + rb_define_mysql_const(ER_SPECIFIC_ACCESS_DENIED_ERROR); + rb_define_mysql_const(ER_LOCAL_VARIABLE); + rb_define_mysql_const(ER_GLOBAL_VARIABLE); + rb_define_mysql_const(ER_NO_DEFAULT); + rb_define_mysql_const(ER_WRONG_VALUE_FOR_VAR); + rb_define_mysql_const(ER_WRONG_TYPE_FOR_VAR); + rb_define_mysql_const(ER_VAR_CANT_BE_READ); + rb_define_mysql_const(ER_CANT_USE_OPTION_HERE); + rb_define_mysql_const(ER_NOT_SUPPORTED_YET); + rb_define_mysql_const(ER_MASTER_FATAL_ERROR_READING_BINLOG); + rb_define_mysql_const(ER_SLAVE_IGNORED_TABLE); + rb_define_mysql_const(ER_INCORRECT_GLOBAL_LOCAL_VAR); + rb_define_mysql_const(ER_WRONG_FK_DEF); + rb_define_mysql_const(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF); + rb_define_mysql_const(ER_OPERAND_COLUMNS); + rb_define_mysql_const(ER_SUBQUERY_NO_1_ROW); + rb_define_mysql_const(ER_UNKNOWN_STMT_HANDLER); + rb_define_mysql_const(ER_CORRUPT_HELP_DB); + rb_define_mysql_const(ER_CYCLIC_REFERENCE); + rb_define_mysql_const(ER_AUTO_CONVERT); + rb_define_mysql_const(ER_ILLEGAL_REFERENCE); + rb_define_mysql_const(ER_DERIVED_MUST_HAVE_ALIAS); + rb_define_mysql_const(ER_SELECT_REDUCED); + rb_define_mysql_const(ER_TABLENAME_NOT_ALLOWED_HERE); + rb_define_mysql_const(ER_NOT_SUPPORTED_AUTH_MODE); + rb_define_mysql_const(ER_SPATIAL_CANT_HAVE_NULL); + rb_define_mysql_const(ER_COLLATION_CHARSET_MISMATCH); + rb_define_mysql_const(ER_SLAVE_WAS_RUNNING); + rb_define_mysql_const(ER_SLAVE_WAS_NOT_RUNNING); + rb_define_mysql_const(ER_TOO_BIG_FOR_UNCOMPRESS); + rb_define_mysql_const(ER_ZLIB_Z_MEM_ERROR); + rb_define_mysql_const(ER_ZLIB_Z_BUF_ERROR); + rb_define_mysql_const(ER_ZLIB_Z_DATA_ERROR); + rb_define_mysql_const(ER_CUT_VALUE_GROUP_CONCAT); + rb_define_mysql_const(ER_WARN_TOO_FEW_RECORDS); + rb_define_mysql_const(ER_WARN_TOO_MANY_RECORDS); + rb_define_mysql_const(ER_WARN_NULL_TO_NOTNULL); + rb_define_mysql_const(ER_WARN_DATA_OUT_OF_RANGE); + rb_define_mysql_const(ER_WARN_USING_OTHER_HANDLER); + rb_define_mysql_const(ER_CANT_AGGREGATE_2COLLATIONS); + rb_define_mysql_const(ER_DROP_USER); + rb_define_mysql_const(ER_REVOKE_GRANTS); + rb_define_mysql_const(ER_CANT_AGGREGATE_3COLLATIONS); + rb_define_mysql_const(ER_CANT_AGGREGATE_NCOLLATIONS); + rb_define_mysql_const(ER_VARIABLE_IS_NOT_STRUCT); + rb_define_mysql_const(ER_UNKNOWN_COLLATION); + rb_define_mysql_const(ER_SLAVE_IGNORED_SSL_PARAMS); + rb_define_mysql_const(ER_SERVER_IS_IN_SECURE_AUTH_MODE); + rb_define_mysql_const(ER_WARN_FIELD_RESOLVED); + rb_define_mysql_const(ER_BAD_SLAVE_UNTIL_COND); + rb_define_mysql_const(ER_MISSING_SKIP_SLAVE); + rb_define_mysql_const(ER_UNTIL_COND_IGNORED); + rb_define_mysql_const(ER_WRONG_NAME_FOR_INDEX); + rb_define_mysql_const(ER_WRONG_NAME_FOR_CATALOG); + rb_define_mysql_const(ER_WARN_QC_RESIZE); + rb_define_mysql_const(ER_BAD_FT_COLUMN); + rb_define_mysql_const(ER_UNKNOWN_KEY_CACHE); + rb_define_mysql_const(ER_WARN_HOSTNAME_WONT_WORK); + rb_define_mysql_const(ER_UNKNOWN_STORAGE_ENGINE); + rb_define_mysql_const(ER_WARN_DEPRECATED_SYNTAX); + rb_define_mysql_const(ER_NON_UPDATABLE_TABLE); + rb_define_mysql_const(ER_FEATURE_DISABLED); + rb_define_mysql_const(ER_OPTION_PREVENTS_STATEMENT); + rb_define_mysql_const(ER_DUPLICATED_VALUE_IN_TYPE); + rb_define_mysql_const(ER_TRUNCATED_WRONG_VALUE); + rb_define_mysql_const(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS); + rb_define_mysql_const(ER_INVALID_ON_UPDATE); + rb_define_mysql_const(ER_UNSUPPORTED_PS); + rb_define_mysql_const(ER_GET_ERRMSG); + rb_define_mysql_const(ER_GET_TEMPORARY_ERRMSG); + rb_define_mysql_const(ER_UNKNOWN_TIME_ZONE); + rb_define_mysql_const(ER_WARN_INVALID_TIMESTAMP); + rb_define_mysql_const(ER_INVALID_CHARACTER_STRING); + rb_define_mysql_const(ER_WARN_ALLOWED_PACKET_OVERFLOWED); + rb_define_mysql_const(ER_CONFLICTING_DECLARATIONS); + rb_define_mysql_const(ER_SP_NO_RECURSIVE_CREATE); + rb_define_mysql_const(ER_SP_ALREADY_EXISTS); + rb_define_mysql_const(ER_SP_DOES_NOT_EXIST); + rb_define_mysql_const(ER_SP_DROP_FAILED); + rb_define_mysql_const(ER_SP_STORE_FAILED); + rb_define_mysql_const(ER_SP_LILABEL_MISMATCH); + rb_define_mysql_const(ER_SP_LABEL_REDEFINE); + rb_define_mysql_const(ER_SP_LABEL_MISMATCH); + rb_define_mysql_const(ER_SP_UNINIT_VAR); + rb_define_mysql_const(ER_SP_BADSELECT); + rb_define_mysql_const(ER_SP_BADRETURN); + rb_define_mysql_const(ER_SP_BADSTATEMENT); + rb_define_mysql_const(ER_UPDATE_LOG_DEPRECATED_IGNORED); + rb_define_mysql_const(ER_UPDATE_LOG_DEPRECATED_TRANSLATED); + rb_define_mysql_const(ER_QUERY_INTERRUPTED); + rb_define_mysql_const(ER_SP_WRONG_NO_OF_ARGS); + rb_define_mysql_const(ER_SP_COND_MISMATCH); + rb_define_mysql_const(ER_SP_NORETURN); + rb_define_mysql_const(ER_SP_NORETURNEND); + rb_define_mysql_const(ER_SP_BAD_CURSOR_QUERY); + rb_define_mysql_const(ER_SP_BAD_CURSOR_SELECT); + rb_define_mysql_const(ER_SP_CURSOR_MISMATCH); + rb_define_mysql_const(ER_SP_CURSOR_ALREADY_OPEN); + rb_define_mysql_const(ER_SP_CURSOR_NOT_OPEN); + rb_define_mysql_const(ER_SP_UNDECLARED_VAR); + rb_define_mysql_const(ER_SP_WRONG_NO_OF_FETCH_ARGS); + rb_define_mysql_const(ER_SP_FETCH_NO_DATA); + rb_define_mysql_const(ER_SP_DUP_PARAM); + rb_define_mysql_const(ER_SP_DUP_VAR); + rb_define_mysql_const(ER_SP_DUP_COND); + rb_define_mysql_const(ER_SP_DUP_CURS); + rb_define_mysql_const(ER_SP_CANT_ALTER); + rb_define_mysql_const(ER_SP_SUBSELECT_NYI); + rb_define_mysql_const(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG); + rb_define_mysql_const(ER_SP_VARCOND_AFTER_CURSHNDLR); + rb_define_mysql_const(ER_SP_CURSOR_AFTER_HANDLER); + rb_define_mysql_const(ER_SP_CASE_NOT_FOUND); + rb_define_mysql_const(ER_FPARSER_TOO_BIG_FILE); + rb_define_mysql_const(ER_FPARSER_BAD_HEADER); + rb_define_mysql_const(ER_FPARSER_EOF_IN_COMMENT); + rb_define_mysql_const(ER_FPARSER_ERROR_IN_PARAMETER); + rb_define_mysql_const(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER); + rb_define_mysql_const(ER_VIEW_NO_EXPLAIN); + rb_define_mysql_const(ER_FRM_UNKNOWN_TYPE); + rb_define_mysql_const(ER_WRONG_OBJECT); + rb_define_mysql_const(ER_NONUPDATEABLE_COLUMN); + rb_define_mysql_const(ER_VIEW_SELECT_DERIVED); + rb_define_mysql_const(ER_VIEW_SELECT_CLAUSE); + rb_define_mysql_const(ER_VIEW_SELECT_VARIABLE); + rb_define_mysql_const(ER_VIEW_SELECT_TMPTABLE); + rb_define_mysql_const(ER_VIEW_WRONG_LIST); + rb_define_mysql_const(ER_WARN_VIEW_MERGE); + rb_define_mysql_const(ER_WARN_VIEW_WITHOUT_KEY); + rb_define_mysql_const(ER_VIEW_INVALID); + rb_define_mysql_const(ER_SP_NO_DROP_SP); + rb_define_mysql_const(ER_SP_GOTO_IN_HNDLR); + rb_define_mysql_const(ER_TRG_ALREADY_EXISTS); + rb_define_mysql_const(ER_TRG_DOES_NOT_EXIST); + rb_define_mysql_const(ER_TRG_ON_VIEW_OR_TEMP_TABLE); + rb_define_mysql_const(ER_TRG_CANT_CHANGE_ROW); + rb_define_mysql_const(ER_TRG_NO_SUCH_ROW_IN_TRG); + rb_define_mysql_const(ER_NO_DEFAULT_FOR_FIELD); + rb_define_mysql_const(ER_DIVISION_BY_ZERO); + rb_define_mysql_const(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD); + rb_define_mysql_const(ER_ILLEGAL_VALUE_FOR_TYPE); + rb_define_mysql_const(ER_VIEW_NONUPD_CHECK); + rb_define_mysql_const(ER_VIEW_CHECK_FAILED); + rb_define_mysql_const(ER_PROCACCESS_DENIED_ERROR); + rb_define_mysql_const(ER_RELAY_LOG_FAIL); + rb_define_mysql_const(ER_PASSWD_LENGTH); + rb_define_mysql_const(ER_UNKNOWN_TARGET_BINLOG); + rb_define_mysql_const(ER_IO_ERR_LOG_INDEX_READ); + rb_define_mysql_const(ER_BINLOG_PURGE_PROHIBITED); + rb_define_mysql_const(ER_FSEEK_FAIL); + rb_define_mysql_const(ER_BINLOG_PURGE_FATAL_ERR); + rb_define_mysql_const(ER_LOG_IN_USE); + rb_define_mysql_const(ER_LOG_PURGE_UNKNOWN_ERR); + rb_define_mysql_const(ER_RELAY_LOG_INIT); + rb_define_mysql_const(ER_NO_BINARY_LOGGING); + rb_define_mysql_const(ER_RESERVED_SYNTAX); + rb_define_mysql_const(ER_WSAS_FAILED); + rb_define_mysql_const(ER_DIFF_GROUPS_PROC); + rb_define_mysql_const(ER_NO_GROUP_FOR_PROC); + rb_define_mysql_const(ER_ORDER_WITH_PROC); + rb_define_mysql_const(ER_LOGGING_PROHIBIT_CHANGING_OF); + rb_define_mysql_const(ER_NO_FILE_MAPPING); + rb_define_mysql_const(ER_WRONG_MAGIC); + rb_define_mysql_const(ER_PS_MANY_PARAM); + rb_define_mysql_const(ER_KEY_PART_0); + rb_define_mysql_const(ER_VIEW_CHECKSUM); + rb_define_mysql_const(ER_VIEW_MULTIUPDATE); + rb_define_mysql_const(ER_VIEW_NO_INSERT_FIELD_LIST); + rb_define_mysql_const(ER_VIEW_DELETE_MERGE_VIEW); + rb_define_mysql_const(ER_CANNOT_USER); + rb_define_mysql_const(ER_XAER_NOTA); + rb_define_mysql_const(ER_XAER_INVAL); + rb_define_mysql_const(ER_XAER_RMFAIL); + rb_define_mysql_const(ER_XAER_OUTSIDE); + rb_define_mysql_const(ER_XAER_RMERR); + rb_define_mysql_const(ER_XA_RBROLLBACK); + rb_define_mysql_const(ER_NONEXISTING_PROC_GRANT); + rb_define_mysql_const(ER_PROC_AUTO_GRANT_FAIL); + rb_define_mysql_const(ER_PROC_AUTO_REVOKE_FAIL); + rb_define_mysql_const(ER_DATA_TOO_LONG); + rb_define_mysql_const(ER_SP_BAD_SQLSTATE); + rb_define_mysql_const(ER_STARTUP); + rb_define_mysql_const(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR); + rb_define_mysql_const(ER_CANT_CREATE_USER_WITH_GRANT); + rb_define_mysql_const(ER_WRONG_VALUE_FOR_TYPE); + rb_define_mysql_const(ER_TABLE_DEF_CHANGED); + rb_define_mysql_const(ER_SP_DUP_HANDLER); + rb_define_mysql_const(ER_SP_NOT_VAR_ARG); + rb_define_mysql_const(ER_SP_NO_RETSET); + rb_define_mysql_const(ER_CANT_CREATE_GEOMETRY_OBJECT); + rb_define_mysql_const(ER_FAILED_ROUTINE_BREAK_BINLOG); + rb_define_mysql_const(ER_BINLOG_UNSAFE_ROUTINE); + rb_define_mysql_const(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER); + rb_define_mysql_const(ER_EXEC_STMT_WITH_OPEN_CURSOR); + rb_define_mysql_const(ER_STMT_HAS_NO_OPEN_CURSOR); + rb_define_mysql_const(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG); + rb_define_mysql_const(ER_NO_DEFAULT_FOR_VIEW_FIELD); + rb_define_mysql_const(ER_SP_NO_RECURSION); + rb_define_mysql_const(ER_TOO_BIG_SCALE); + rb_define_mysql_const(ER_TOO_BIG_PRECISION); + rb_define_mysql_const(ER_M_BIGGER_THAN_D); + rb_define_mysql_const(ER_WRONG_LOCK_OF_SYSTEM_TABLE); + rb_define_mysql_const(ER_CONNECT_TO_FOREIGN_DATA_SOURCE); + rb_define_mysql_const(ER_QUERY_ON_FOREIGN_DATA_SOURCE); + rb_define_mysql_const(ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST); + rb_define_mysql_const(ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE); + rb_define_mysql_const(ER_FOREIGN_DATA_STRING_INVALID); + rb_define_mysql_const(ER_CANT_CREATE_FEDERATED_TABLE); + rb_define_mysql_const(ER_TRG_IN_WRONG_SCHEMA); + rb_define_mysql_const(ER_STACK_OVERRUN_NEED_MORE); + rb_define_mysql_const(ER_TOO_LONG_BODY); + rb_define_mysql_const(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE); + rb_define_mysql_const(ER_TOO_BIG_DISPLAYWIDTH); + rb_define_mysql_const(ER_XAER_DUPID); + rb_define_mysql_const(ER_DATETIME_FUNCTION_OVERFLOW); + rb_define_mysql_const(ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG); + rb_define_mysql_const(ER_VIEW_PREVENT_UPDATE); + rb_define_mysql_const(ER_PS_NO_RECURSION); + rb_define_mysql_const(ER_SP_CANT_SET_AUTOCOMMIT); + rb_define_mysql_const(ER_MALFORMED_DEFINER); + rb_define_mysql_const(ER_VIEW_FRM_NO_USER); + rb_define_mysql_const(ER_VIEW_OTHER_USER); + rb_define_mysql_const(ER_NO_SUCH_USER); + rb_define_mysql_const(ER_FORBID_SCHEMA_CHANGE); + rb_define_mysql_const(ER_ROW_IS_REFERENCED_2); + rb_define_mysql_const(ER_NO_REFERENCED_ROW_2); + rb_define_mysql_const(ER_SP_BAD_VAR_SHADOW); + rb_define_mysql_const(ER_TRG_NO_DEFINER); + rb_define_mysql_const(ER_OLD_FILE_FORMAT); + rb_define_mysql_const(ER_SP_RECURSION_LIMIT); + rb_define_mysql_const(ER_SP_PROC_TABLE_CORRUPT); + rb_define_mysql_const(ER_SP_WRONG_NAME); + rb_define_mysql_const(ER_TABLE_NEEDS_UPGRADE); + rb_define_mysql_const(ER_SP_NO_AGGREGATE); + rb_define_mysql_const(ER_MAX_PREPARED_STMT_COUNT_REACHED); + rb_define_mysql_const(ER_VIEW_RECURSIVE); + rb_define_mysql_const(ER_NON_GROUPING_FIELD_USED); + rb_define_mysql_const(ER_TABLE_CANT_HANDLE_SPKEYS); + rb_define_mysql_const(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA); + rb_define_mysql_const(ER_REMOVED_SPACES); + rb_define_mysql_const(ER_AUTOINC_READ_FAILED); + rb_define_mysql_const(ER_USERNAME); + rb_define_mysql_const(ER_HOSTNAME); + rb_define_mysql_const(ER_WRONG_STRING_LENGTH); + rb_define_mysql_const(ER_NON_INSERTABLE_TABLE); + rb_define_mysql_const(ER_ADMIN_WRONG_MRG_TABLE); + rb_define_mysql_const(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT); + rb_define_mysql_const(ER_NAME_BECOMES_EMPTY); + rb_define_mysql_const(ER_ERROR_LAST); diff --git a/ext/extconf.rb b/ext/extconf.rb new file mode 100644 index 0000000..bc00612 --- /dev/null +++ b/ext/extconf.rb @@ -0,0 +1,70 @@ +require 'mkmf' + +if /mswin32/ =~ RUBY_PLATFORM + inc, lib = dir_config('mysql') + exit 1 unless have_library("libmysql") +elsif mc = with_config('mysql-config') then + mc = 'mysql_config' if mc == true + cflags = `#{mc} --cflags`.chomp + exit 1 if $? != 0 + libs = `#{mc} --libs`.chomp + exit 1 if $? != 0 + $CPPFLAGS += ' ' + cflags + $libs = libs + " " + $libs +else + inc, lib = dir_config('mysql', '/usr/local') + libs = ['m', 'z', 'socket', 'nsl', 'mygcc'] + while not find_library('mysqlclient', 'mysql_query', lib, "#{lib}/mysql") do + exit 1 if libs.empty? + have_library(libs.shift) + end +end + +have_func('mysql_ssl_set') +have_func('rb_str_set_len') + +if have_header('mysql.h') then + src = "#include \n#include \n" +elsif have_header('mysql/mysql.h') then + src = "#include \n#include \n" +else + exit 1 +end + +# make mysql constant +File.open("conftest.c", "w") do |f| + f.puts src +end +if defined? cpp_command then + cpp = Config.expand(cpp_command('')) +else + cpp = Config.expand sprintf(CPP, $CPPFLAGS, $CFLAGS, '') +end +if /mswin32/ =~ RUBY_PLATFORM && !/-E/.match(cpp) + cpp << " -E" +end +unless system "#{cpp} > confout" then + exit 1 +end +File.unlink "conftest.c" + +error_syms = [] +IO.foreach('confout') do |l| + next unless l =~ /errmsg\.h|mysqld_error\.h/ + fn = l.split(/\"/)[1] + IO.foreach(fn) do |m| + if m =~ /^#define\s+([CE]R_[0-9A-Z_]+)/ then + error_syms << $1 + end + end +end +File.unlink 'confout' +error_syms.uniq! + +File.open('error_const.h', 'w') do |f| + error_syms.each do |s| + f.puts " rb_define_mysql_const(#{s});" + end +end + +create_makefile("mysql") diff --git a/ext/mysql.c b/ext/mysql.c new file mode 100644 index 0000000..713f33d --- /dev/null +++ b/ext/mysql.c @@ -0,0 +1,2322 @@ +/* ruby mysql module + * $Id: mysql.c 229 2008-06-20 07:44:04Z tommy $ + * modified 2008-08-26 Muhammad A. Ali + * added an async interface + */ + +#include +#ifndef RSTRING_PTR +#define RSTRING_PTR(str) RSTRING(str)->ptr +#endif +#ifndef RSTRING_LEN +#define RSTRING_LEN(str) RSTRING(str)->len +#endif +#ifndef HAVE_RB_STR_SET_LEN +#define rb_str_set_len(str, length) (RSTRING_LEN(str) = (length)) +#endif + +#ifdef HAVE_MYSQL_H +#include +#include +//#include +#include +#include +#else +#include +#include +//#include +#include +#include +#endif + +#define MYSQL_RUBY_VERSION 20800 + +#define GC_STORE_RESULT_LIMIT 20 + +#if MYSQL_VERSION_ID < 32224 +#define mysql_field_count mysql_num_fields +#endif + +#define NILorSTRING(obj) (NIL_P(obj)? NULL: StringValuePtr(obj)) +#define NILorINT(obj) (NIL_P(obj)? 0: NUM2INT(obj)) + +#define GetMysqlStruct(obj) (Check_Type(obj, T_DATA), (struct mysql*)DATA_PTR(obj)) +#define GetHandler(obj) (Check_Type(obj, T_DATA), &(((struct mysql*)DATA_PTR(obj))->handler)) +#define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res) +#define GetMysqlStmt(obj) (Check_Type(obj, T_DATA), ((struct mysql_stmt*)DATA_PTR(obj))->stmt) + +VALUE cMysql; +VALUE cMysqlRes; +VALUE cMysqlField; +VALUE cMysqlStmt; +VALUE cMysqlRowOffset; +VALUE cMysqlTime; +VALUE eMysql; + +static int store_result_count = 0; + +struct mysql { + MYSQL handler; + char connection; + char query_with_result; +}; + +struct mysql_res { + MYSQL_RES* res; + char freed; +}; + +#if MYSQL_VERSION_ID >= 40101 +struct mysql_stmt { + MYSQL_STMT *stmt; + char closed; + struct { + int n; + MYSQL_BIND *bind; + unsigned long *length; + MYSQL_TIME *buffer; + } param; + struct { + int n; + MYSQL_BIND *bind; + my_bool *is_null; + unsigned long *length; + } result; + MYSQL_RES *res; +}; +#endif + +/* free Mysql class object */ +static void free_mysql(struct mysql* my) +{ + if (my->connection == Qtrue) + mysql_close(&my->handler); + xfree(my); +} + +static void free_mysqlres(struct mysql_res* resp) +{ + if (resp->freed == Qfalse) { + mysql_free_result(resp->res); + store_result_count--; + } + xfree(resp); +} + +#if MYSQL_VERSION_ID >= 40101 +static void free_mysqlstmt_memory(struct mysql_stmt *s) +{ + if (s->param.bind) { + xfree(s->param.bind); + s->param.bind = NULL; + } + if (s->param.length) { + xfree(s->param.length); + s->param.length = NULL; + } + if (s->param.buffer) { + xfree(s->param.buffer); + s->param.buffer = NULL; + } + s->param.n = 0; + if (s->res) { + mysql_free_result(s->res); + s->res = NULL; + } + if (s->result.bind) { + int i; + for (i = 0; i < s->result.n; i++) { + if (s->result.bind[i].buffer) + xfree(s->result.bind[i].buffer); + s->result.bind[i].buffer = NULL; + } + xfree(s->result.bind); + s->result.bind = NULL; + } + if (s->result.is_null) { + xfree(s->result.is_null); + s->result.is_null = NULL; + } + if (s->result.length) { + xfree(s->result.length); + s->result.length = NULL; + } + s->result.n = 0; +} + +static void free_execute_memory(struct mysql_stmt *s) +{ + if (s->res && s->result.bind) { + int i; + for (i = 0; i < s->result.n; i++) { + if (s->result.bind[i].buffer) + xfree(s->result.bind[i].buffer); + s->result.bind[i].buffer = NULL; + } + } + mysql_stmt_free_result(s->stmt); +} + +static void free_mysqlstmt(struct mysql_stmt* s) +{ + free_mysqlstmt_memory(s); + if (s->closed == Qfalse) + mysql_stmt_close(s->stmt); + if (s->res) + mysql_free_result(s->res); + xfree(s); +} +#endif + +static void mysql_raise(MYSQL* m) +{ + VALUE e = rb_exc_new2(eMysql, mysql_error(m)); + rb_iv_set(e, "errno", INT2FIX(mysql_errno(m))); +#if MYSQL_VERSION_ID >= 40101 + rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_sqlstate(m))); +#endif + rb_exc_raise(e); +} + +static VALUE mysqlres2obj(MYSQL_RES* res) +{ + VALUE obj; + struct mysql_res* resp; + obj = Data_Make_Struct(cMysqlRes, struct mysql_res, 0, free_mysqlres, resp); + rb_iv_set(obj, "colname", Qnil); + rb_iv_set(obj, "tblcolname", Qnil); + resp->res = res; + resp->freed = Qfalse; + rb_obj_call_init(obj, 0, NULL); + if (++store_result_count > GC_STORE_RESULT_LIMIT) + rb_gc(); + return obj; +} + +/* make Mysql::Field object */ +static VALUE make_field_obj(MYSQL_FIELD* f) +{ + VALUE obj; + if (f == NULL) + return Qnil; + obj = rb_obj_alloc(cMysqlField); + rb_iv_set(obj, "name", f->name? rb_str_freeze(rb_tainted_str_new2(f->name)): Qnil); + rb_iv_set(obj, "table", f->table? rb_str_freeze(rb_tainted_str_new2(f->table)): Qnil); + rb_iv_set(obj, "def", f->def? rb_str_freeze(rb_tainted_str_new2(f->def)): Qnil); + rb_iv_set(obj, "type", INT2NUM(f->type)); + rb_iv_set(obj, "length", INT2NUM(f->length)); + rb_iv_set(obj, "max_length", INT2NUM(f->max_length)); + rb_iv_set(obj, "flags", INT2NUM(f->flags)); + rb_iv_set(obj, "decimals", INT2NUM(f->decimals)); + return obj; +} + +/*------------------------------- + * Mysql class method + */ + +/* init() */ +static VALUE init(VALUE klass) +{ + struct mysql* myp; + VALUE obj; + + obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp); + mysql_init(&myp->handler); + myp->connection = Qfalse; + myp->query_with_result = Qtrue; + rb_obj_call_init(obj, 0, NULL); + return obj; +} + +/* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */ +static VALUE real_connect(int argc, VALUE* argv, VALUE klass) +{ + VALUE host, user, passwd, db, port, sock, flag; + char *h, *u, *p, *d, *s; + unsigned int pp, f; + struct mysql* myp; + VALUE obj; + +#if MYSQL_VERSION_ID >= 32200 + rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag); + d = NILorSTRING(db); + f = NILorINT(flag); +#elif MYSQL_VERSION_ID >= 32115 + rb_scan_args(argc, argv, "06", &host, &user, &passwd, &port, &sock, &flag); + f = NILorINT(flag); +#else + rb_scan_args(argc, argv, "05", &host, &user, &passwd, &port, &sock); +#endif + h = NILorSTRING(host); + u = NILorSTRING(user); + p = NILorSTRING(passwd); + pp = NILorINT(port); + s = NILorSTRING(sock); + + obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp); +#if MYSQL_VERSION_ID >= 32200 + mysql_init(&myp->handler); + if (mysql_real_connect(&myp->handler, h, u, p, d, pp, s, f) == NULL) +#elif MYSQL_VERSION_ID >= 32115 + if (mysql_real_connect(&myp->handler, h, u, p, pp, s, f) == NULL) +#else + if (mysql_real_connect(&myp->handler, h, u, p, pp, s) == NULL) +#endif + mysql_raise(&myp->handler); + + myp->handler.reconnect = 0; + myp->connection = Qtrue; + myp->query_with_result = Qtrue; + rb_obj_call_init(obj, argc, argv); + + return obj; +} + +/* escape_string(string) */ +static VALUE escape_string(VALUE klass, VALUE str) +{ + VALUE ret; + Check_Type(str, T_STRING); + ret = rb_str_new(0, (RSTRING_LEN(str))*2+1); + rb_str_set_len(ret, mysql_escape_string(RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str))); + return ret; +} + +/* client_info() */ +static VALUE client_info(VALUE klass) +{ + return rb_tainted_str_new2(mysql_get_client_info()); +} + +#if MYSQL_VERSION_ID >= 32332 +/* my_debug(string) */ +static VALUE my_debug(VALUE obj, VALUE str) +{ + mysql_debug(StringValuePtr(str)); + return obj; +} +#endif + +#if MYSQL_VERSION_ID >= 40000 +/* client_version() */ +static VALUE client_version(VALUE obj) +{ + return INT2NUM(mysql_get_client_version()); +} +#endif + +/*------------------------------- + * Mysql object method + */ + +#if MYSQL_VERSION_ID >= 32200 +/* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */ +static VALUE real_connect2(int argc, VALUE* argv, VALUE obj) +{ + VALUE host, user, passwd, db, port, sock, flag; + char *h, *u, *p, *d, *s; + unsigned int pp, f; + MYSQL* m = GetHandler(obj); + rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag); + d = NILorSTRING(db); + f = NILorINT(flag); + h = NILorSTRING(host); + u = NILorSTRING(user); + p = NILorSTRING(passwd); + pp = NILorINT(port); + s = NILorSTRING(sock); + + if (mysql_real_connect(m, h, u, p, d, pp, s, f) == NULL) + mysql_raise(m); + m->reconnect = 0; + GetMysqlStruct(obj)->connection = Qtrue; + + return obj; +} + +/* options(opt, value=nil) */ +static VALUE options(int argc, VALUE* argv, VALUE obj) +{ + VALUE opt, val; + int n; + my_bool b; + char* v; + MYSQL* m = GetHandler(obj); + + rb_scan_args(argc, argv, "11", &opt, &val); + switch(NUM2INT(opt)) { + case MYSQL_OPT_CONNECT_TIMEOUT: +#if MYSQL_VERSION_ID >= 40100 + case MYSQL_OPT_PROTOCOL: +#endif +#if MYSQL_VERSION_ID >= 40101 + case MYSQL_OPT_READ_TIMEOUT: + case MYSQL_OPT_WRITE_TIMEOUT: +#endif + if (val == Qnil) + rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)"); + n = NUM2INT(val); + v = (char*)&n; + break; + case MYSQL_INIT_COMMAND: + case MYSQL_READ_DEFAULT_FILE: + case MYSQL_READ_DEFAULT_GROUP: +#if MYSQL_VERSION_ID >= 32349 + case MYSQL_SET_CHARSET_DIR: + case MYSQL_SET_CHARSET_NAME: +#endif +#if MYSQL_VERSION_ID >= 40100 + case MYSQL_SHARED_MEMORY_BASE_NAME: +#endif +#if MYSQL_VERSION_ID >= 40101 + case MYSQL_SET_CLIENT_IP: +#endif + if (val == Qnil) + rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)"); + v = StringValuePtr(val); + break; +#if MYSQL_VERSION_ID >= 40101 + case MYSQL_SECURE_AUTH: + if (val == Qnil || val == Qfalse) + b = 1; + else + b = 0; + v = (char*)&b; + break; +#endif +#if MYSQL_VERSION_ID >= 32349 + case MYSQL_OPT_LOCAL_INFILE: + if (val == Qnil || val == Qfalse) + v = NULL; + else { + n = 1; + v = (char*)&n; + } + break; +#endif + default: + v = NULL; + } + + if (mysql_options(m, NUM2INT(opt), v) != 0) + rb_raise(eMysql, "unknown option: %d", NUM2INT(opt)); + return obj; +} +#endif + +#if MYSQL_VERSION_ID >= 32332 +/* real_escape_string(string) */ +static VALUE real_escape_string(VALUE obj, VALUE str) +{ + MYSQL* m = GetHandler(obj); + VALUE ret; + Check_Type(str, T_STRING); + ret = rb_str_new(0, (RSTRING_LEN(str))*2+1); + rb_str_set_len(ret, mysql_real_escape_string(m, RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str))); + return ret; +} +#endif + +/* initialize() */ +static VALUE initialize(int argc, VALUE* argv, VALUE obj) +{ + return obj; +} + +/* affected_rows() */ +static VALUE affected_rows(VALUE obj) +{ + return INT2NUM(mysql_affected_rows(GetHandler(obj))); +} + +#if MYSQL_VERSION_ID >= 32303 +/* change_user(user=nil, passwd=nil, db=nil) */ +static VALUE change_user(int argc, VALUE* argv, VALUE obj) +{ + VALUE user, passwd, db; + char *u, *p, *d; + MYSQL* m = GetHandler(obj); + rb_scan_args(argc, argv, "03", &user, &passwd, &db); + u = NILorSTRING(user); + p = NILorSTRING(passwd); + d = NILorSTRING(db); + if (mysql_change_user(m, u, p, d) != 0) + mysql_raise(m); + return obj; +} +#endif + +#if MYSQL_VERSION_ID >= 32321 +/* character_set_name() */ +static VALUE character_set_name(VALUE obj) +{ + return rb_tainted_str_new2(mysql_character_set_name(GetHandler(obj))); +} +#endif + +/* close() */ +static VALUE my_close(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + mysql_close(m); + GetMysqlStruct(obj)->connection = Qfalse; + return obj; +} + +#if MYSQL_VERSION_ID < 40000 +/* create_db(db) */ +static VALUE create_db(VALUE obj, VALUE db) +{ + MYSQL* m = GetHandler(obj); + if (mysql_create_db(m, StringValuePtr(db)) != 0) + mysql_raise(m); + return obj; +} + +/* drop_db(db) */ +static VALUE drop_db(VALUE obj, VALUE db) +{ + MYSQL* m = GetHandler(obj); + if (mysql_drop_db(m, StringValuePtr(db)) != 0) + mysql_raise(m); + return obj; +} +#endif + +#if MYSQL_VERSION_ID >= 32332 +/* dump_debug_info() */ +static VALUE dump_debug_info(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + if (mysql_dump_debug_info(m) != 0) + mysql_raise(m); + return obj; +} +#endif + +/* errno() */ +static VALUE my_errno(VALUE obj) +{ + return INT2NUM(mysql_errno(GetHandler(obj))); +} + +/* error() */ +static VALUE my_error(VALUE obj) +{ + return rb_str_new2(mysql_error(GetHandler(obj))); +} + +/* field_count() */ +static VALUE field_count(VALUE obj) +{ + return INT2NUM(mysql_field_count(GetHandler(obj))); +} + +/* host_info() */ +static VALUE host_info(VALUE obj) +{ + return rb_tainted_str_new2(mysql_get_host_info(GetHandler(obj))); +} + +/* proto_info() */ +static VALUE proto_info(VALUE obj) +{ + return INT2NUM(mysql_get_proto_info(GetHandler(obj))); +} + +/* server_info() */ +static VALUE server_info(VALUE obj) +{ + return rb_tainted_str_new2(mysql_get_server_info(GetHandler(obj))); +} + +/* info() */ +static VALUE info(VALUE obj) +{ + const char* p = mysql_info(GetHandler(obj)); + return p? rb_tainted_str_new2(p): Qnil; +} + +/* insert_id() */ +static VALUE insert_id(VALUE obj) +{ + return INT2NUM(mysql_insert_id(GetHandler(obj))); +} + +/* kill(pid) */ +static VALUE my_kill(VALUE obj, VALUE pid) +{ + int p = NUM2INT(pid); + MYSQL* m = GetHandler(obj); + if (mysql_kill(m, p) != 0) + mysql_raise(m); + return obj; +} + +/* list_dbs(db=nil) */ +static VALUE list_dbs(int argc, VALUE* argv, VALUE obj) +{ + unsigned int i, n; + VALUE db, ret; + MYSQL* m = GetHandler(obj); + MYSQL_RES* res; + + rb_scan_args(argc, argv, "01", &db); + res = mysql_list_dbs(m, NILorSTRING(db)); + if (res == NULL) + mysql_raise(m); + + n = mysql_num_rows(res); + ret = rb_ary_new2(n); + for (i=0; i= 40103 + if (mysql_shutdown(m, NIL_P(level) ? SHUTDOWN_DEFAULT : NUM2INT(level)) != 0) +#else + if (mysql_shutdown(m) != 0) +#endif + mysql_raise(m); + return obj; +} + +/* stat() */ +static VALUE my_stat(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + const char* s = mysql_stat(m); + if (s == NULL) + mysql_raise(m); + return rb_tainted_str_new2(s); +} + +/* store_result() */ +static VALUE store_result(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + MYSQL_RES* res = mysql_store_result(m); + if (res == NULL) + mysql_raise(m); + return mysqlres2obj(res); +} + +/* thread_id() */ +static VALUE thread_id(VALUE obj) +{ + return INT2NUM(mysql_thread_id(GetHandler(obj))); +} + +/* use_result() */ +static VALUE use_result(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + MYSQL_RES* res = mysql_use_result(m); + if (res == NULL) + mysql_raise(m); + return mysqlres2obj(res); +} + +static VALUE res_free(VALUE); +/* query(sql) */ +static VALUE query(VALUE obj, VALUE sql) +{ + int loop = 0; + MYSQL* m = GetHandler(obj); + Check_Type(sql, T_STRING); + if (GetMysqlStruct(obj)->connection == Qfalse) { + rb_raise(eMysql, "query: not connected"); + } + if (rb_block_given_p()) { + if (mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0) + mysql_raise(m); + do { + MYSQL_RES* res = mysql_store_result(m); + if (res == NULL) { + if (mysql_field_count(m) != 0) + mysql_raise(m); + } else { + VALUE robj = mysqlres2obj(res); + rb_ensure(rb_yield, robj, res_free, robj); + } +#if MYSQL_VERSION_ID >= 40101 + if ((loop = mysql_next_result(m)) > 0) + mysql_raise(m); + } while (loop == 0); +#else + } while (0); +#endif + return obj; + } + if (mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0) + mysql_raise(m); + if (GetMysqlStruct(obj)->query_with_result == Qfalse) + return obj; + if (mysql_field_count(m) == 0) + return Qnil; + return store_result(obj); +} + +/* socket */ +static VALUE socket(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + return INT2NUM(vio_fd(m->net.vio)); +} + +/* setnonblocking */ +/* +static VALUE setnonblocking(VALUE obj, VALUE new_state) +{ + MYSQL* m = GetHandler(obj); + my_bool current; + return m->net.vio->vioblocking(m->net.vio, new_state, *current); +} +*/ +/* isblocking */ +/* +static VALUE isblocking(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + return m->net.vio->is_blocking(m->net.vio); +} +*/ + +/* send_query */ +static VALUE send_query(VALUE obj, VALUE sql) +{ + MYSQL* m = GetHandler(obj); + Check_Type(sql, T_STRING); + if (GetMysqlStruct(obj)->connection == Qfalse) { + rb_raise(eMysql, "query: not connected"); + } + if (mysql_send_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0) + mysql_raise(m); + return Qnil; +} + +/* get_result */ +static VALUE get_result(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + if (GetMysqlStruct(obj)->connection == Qfalse) { + rb_raise(eMysql, "query: not connected"); + } + if (mysql_read_query_result(m) != 0) + mysql_raise(m); + if (GetMysqlStruct(obj)->query_with_result == Qfalse) + return obj; + if (mysql_field_count(m) == 0) + return Qnil; + return store_result(obj); +} + +/* async_query */ +static VALUE async_query(VALUE obj, VALUE sql) +{ + send_query(obj,sql); + MYSQL* m = GetHandler(obj); + int sd = (int)vio_fd(m->net.vio); + rb_io_wait_readable(sd); + return get_result(obj); +} + + +#if MYSQL_VERSION_ID >= 40100 +/* server_version() */ +static VALUE server_version(VALUE obj) +{ + return INT2NUM(mysql_get_server_version(GetHandler(obj))); +} + +/* warning_count() */ +static VALUE warning_count(VALUE obj) +{ + return INT2NUM(mysql_warning_count(GetHandler(obj))); +} + +/* commit() */ +static VALUE commit(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + if (mysql_commit(m) != 0) + mysql_raise(m); + return obj; +} + +/* rollback() */ +static VALUE rollback(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + if (mysql_rollback(m) != 0) + mysql_raise(m); + return obj; +} + +/* autocommit() */ +static VALUE autocommit(VALUE obj, VALUE mode) +{ + MYSQL* m = GetHandler(obj); + int f; + f = (mode == Qnil || mode == Qfalse || (rb_type(mode) == T_FIXNUM && NUM2INT(mode) == 0)) ? 0 : 1; + if (mysql_autocommit(m, f) != 0) + mysql_raise(m); + return obj; +} +#endif + +#ifdef HAVE_MYSQL_SSL_SET +/* ssl_set(key=nil, cert=nil, ca=nil, capath=nil, cipher=nil) */ +static VALUE ssl_set(int argc, VALUE* argv, VALUE obj) +{ + VALUE key, cert, ca, capath, cipher; + char *s_key, *s_cert, *s_ca, *s_capath, *s_cipher; + MYSQL* m = GetHandler(obj); + rb_scan_args(argc, argv, "05", &key, &cert, &ca, &capath, &cipher); + s_key = NILorSTRING(key); + s_cert = NILorSTRING(cert); + s_ca = NILorSTRING(ca); + s_capath = NILorSTRING(capath); + s_cipher = NILorSTRING(cipher); + mysql_ssl_set(m, s_key, s_cert, s_ca, s_capath, s_cipher); + return obj; +} +#endif + +#if MYSQL_VERSION_ID >= 40100 +/* more_results() */ +static VALUE more_results(VALUE obj) +{ + if (mysql_more_results(GetHandler(obj)) == 0) + return Qfalse; + else + return Qtrue; +} + +static VALUE next_result(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + int ret; + ret = mysql_next_result(m); + if (ret > 0) + mysql_raise(m); + if (ret == 0) + return Qtrue; + return Qfalse; +} +#endif + +#if MYSQL_VERSION_ID >= 40101 +/* set_server_option(option) */ +static VALUE set_server_option(VALUE obj, VALUE option) +{ + MYSQL *m = GetHandler(obj); + if (mysql_set_server_option(m, NUM2INT(option)) != 0) + mysql_raise(m); + return obj; +} + +/* sqlstate() */ +static VALUE sqlstate(VALUE obj) +{ + MYSQL *m = GetHandler(obj); + return rb_tainted_str_new2(mysql_sqlstate(m)); +} +#endif + +#if MYSQL_VERSION_ID >= 40102 +/* stmt_init() */ +static VALUE stmt_init(VALUE obj) +{ + MYSQL *m = GetHandler(obj); + MYSQL_STMT *s; + struct mysql_stmt* stmt; + my_bool true = 1; + VALUE st_obj; + + if ((s = mysql_stmt_init(m)) == NULL) + mysql_raise(m); + if (mysql_stmt_attr_set(s, STMT_ATTR_UPDATE_MAX_LENGTH, &true)) + rb_raise(rb_eArgError, "mysql_stmt_attr_set() failed"); + st_obj = Data_Make_Struct(cMysqlStmt, struct mysql_stmt, 0, free_mysqlstmt, stmt); + memset(stmt, 0, sizeof(*stmt)); + stmt->stmt = s; + stmt->closed = Qfalse; + return st_obj; +} + +static VALUE stmt_prepare(VALUE obj, VALUE query); +/* prepare(query) */ +static VALUE prepare(VALUE obj, VALUE query) +{ + VALUE st; + st = stmt_init(obj); + return stmt_prepare(st, query); +} +#endif + +/* query_with_result() */ +static VALUE query_with_result(VALUE obj) +{ + return GetMysqlStruct(obj)->query_with_result? Qtrue: Qfalse; +} + +/* query_with_result=(flag) */ +static VALUE query_with_result_set(VALUE obj, VALUE flag) +{ + if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE) + rb_raise(rb_eTypeError, "invalid type, required true or false."); + GetMysqlStruct(obj)->query_with_result = flag; + return flag; +} + +/* reconnect() */ +static VALUE reconnect(VALUE obj) +{ + return GetHandler(obj)->reconnect ? Qtrue : Qfalse; +} + +/* reconnect=(flag) */ +static VALUE reconnect_set(VALUE obj, VALUE flag) +{ + GetHandler(obj)->reconnect = (flag == Qnil || flag == Qfalse) ? 0 : 1; + return flag; +} + +/*------------------------------- + * Mysql::Result object method + */ + +/* check if already freed */ +static void check_free(VALUE obj) +{ + struct mysql_res* resp = DATA_PTR(obj); + if (resp->freed == Qtrue) + rb_raise(eMysql, "Mysql::Result object is already freed"); +} + +/* data_seek(offset) */ +static VALUE data_seek(VALUE obj, VALUE offset) +{ + check_free(obj); + mysql_data_seek(GetMysqlRes(obj), NUM2INT(offset)); + return obj; +} + +/* fetch_field() */ +static VALUE fetch_field(VALUE obj) +{ + check_free(obj); + return make_field_obj(mysql_fetch_field(GetMysqlRes(obj))); +} + +/* fetch_fields() */ +static VALUE fetch_fields(VALUE obj) +{ + MYSQL_RES* res; + MYSQL_FIELD* f; + unsigned int n; + VALUE ret; + unsigned int i; + check_free(obj); + res = GetMysqlRes(obj); + f = mysql_fetch_fields(res); + n = mysql_num_fields(res); + ret = rb_ary_new2(n); + for (i=0; i= max) + rb_raise(eMysql, "%d: out of range (max: %d)", n, max-1); +#if MYSQL_VERSION_ID >= 32226 + return make_field_obj(mysql_fetch_field_direct(res, n)); +#else + return make_field_obj(&mysql_fetch_field_direct(res, n)); +#endif +} + +/* fetch_lengths() */ +static VALUE fetch_lengths(VALUE obj) +{ + MYSQL_RES* res; + unsigned int n; + unsigned long* lengths; + VALUE ary; + unsigned int i; + check_free(obj); + res = GetMysqlRes(obj); + n = mysql_num_fields(res); + lengths = mysql_fetch_lengths(res); + if (lengths == NULL) + return Qnil; + ary = rb_ary_new2(n); + for (i=0; ires); + resp->freed = Qtrue; + store_result_count--; + return Qnil; +} + +/* num_fields() */ +static VALUE num_fields(VALUE obj) +{ + check_free(obj); + return INT2NUM(mysql_num_fields(GetMysqlRes(obj))); +} + +/* num_rows() */ +static VALUE num_rows(VALUE obj) +{ + check_free(obj); + return INT2NUM(mysql_num_rows(GetMysqlRes(obj))); +} + +/* row_seek(offset) */ +static VALUE row_seek(VALUE obj, VALUE offset) +{ + MYSQL_ROW_OFFSET prev_offset; + if (CLASS_OF(offset) != cMysqlRowOffset) + rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset)); + check_free(obj); + prev_offset = mysql_row_seek(GetMysqlRes(obj), DATA_PTR(offset)); + return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset); +} + +/* row_tell() */ +static VALUE row_tell(VALUE obj) +{ + MYSQL_ROW_OFFSET offset; + check_free(obj); + offset = mysql_row_tell(GetMysqlRes(obj)); + return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset); +} + +/* each {...} */ +static VALUE each(VALUE obj) +{ + VALUE row; + check_free(obj); + while ((row = fetch_row(obj)) != Qnil) + rb_yield(row); + return obj; +} + +/* each_hash(with_table=false) {...} */ +static VALUE each_hash(int argc, VALUE* argv, VALUE obj) +{ + VALUE with_table; + VALUE hash; + check_free(obj); + rb_scan_args(argc, argv, "01", &with_table); + if (with_table == Qnil) + with_table = Qfalse; + while ((hash = fetch_hash2(obj, with_table)) != Qnil) + rb_yield(hash); + return obj; +} + +/*------------------------------- + * Mysql::Field object method + */ + +/* hash */ +static VALUE field_hash(VALUE obj) +{ + VALUE h = rb_hash_new(); + rb_hash_aset(h, rb_str_new2("name"), rb_iv_get(obj, "name")); + rb_hash_aset(h, rb_str_new2("table"), rb_iv_get(obj, "table")); + rb_hash_aset(h, rb_str_new2("def"), rb_iv_get(obj, "def")); + rb_hash_aset(h, rb_str_new2("type"), rb_iv_get(obj, "type")); + rb_hash_aset(h, rb_str_new2("length"), rb_iv_get(obj, "length")); + rb_hash_aset(h, rb_str_new2("max_length"), rb_iv_get(obj, "max_length")); + rb_hash_aset(h, rb_str_new2("flags"), rb_iv_get(obj, "flags")); + rb_hash_aset(h, rb_str_new2("decimals"), rb_iv_get(obj, "decimals")); + return h; +} + +/* inspect */ +static VALUE field_inspect(VALUE obj) +{ + VALUE n = rb_iv_get(obj, "name"); + VALUE s = rb_str_new(0, RSTRING_LEN(n) + 16); + sprintf(RSTRING_PTR(s), "#", RSTRING_PTR(n)); + return s; +} + +#define DefineMysqlFieldMemberMethod(m)\ +static VALUE field_##m(VALUE obj)\ +{return rb_iv_get(obj, #m);} + +DefineMysqlFieldMemberMethod(name) +DefineMysqlFieldMemberMethod(table) +DefineMysqlFieldMemberMethod(def) +DefineMysqlFieldMemberMethod(type) +DefineMysqlFieldMemberMethod(length) +DefineMysqlFieldMemberMethod(max_length) +DefineMysqlFieldMemberMethod(flags) +DefineMysqlFieldMemberMethod(decimals) + +#ifdef IS_NUM +/* is_num? */ +static VALUE field_is_num(VALUE obj) +{ + return IS_NUM(NUM2INT(rb_iv_get(obj, "type"))) ? Qtrue : Qfalse; +} +#endif + +#ifdef IS_NOT_NULL +/* is_not_null? */ +static VALUE field_is_not_null(VALUE obj) +{ + return IS_NOT_NULL(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse; +} +#endif + +#ifdef IS_PRI_KEY +/* is_pri_key? */ +static VALUE field_is_pri_key(VALUE obj) +{ + return IS_PRI_KEY(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse; +} +#endif + +#if MYSQL_VERSION_ID >= 40102 +/*------------------------------- + * Mysql::Stmt object method + */ + +/* check if stmt is already closed */ +static void check_stmt_closed(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + if (s->closed == Qtrue) + rb_raise(eMysql, "Mysql::Stmt object is already closed"); +} + +static void mysql_stmt_raise(MYSQL_STMT* s) +{ + VALUE e = rb_exc_new2(eMysql, mysql_stmt_error(s)); + rb_iv_set(e, "errno", INT2FIX(mysql_stmt_errno(s))); + rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_stmt_sqlstate(s))); + rb_exc_raise(e); +} + +/* affected_rows() */ +static VALUE stmt_affected_rows(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + my_ulonglong n; + check_stmt_closed(obj); + n = mysql_stmt_affected_rows(s->stmt); + return INT2NUM(n); +} + +#if 0 +/* attr_get(option) */ +static VALUE stmt_attr_get(VALUE obj, VALUE opt) +{ + struct mysql_stmt* s = DATA_PTR(obj); + check_stmt_closed(obj); + if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) { + my_bool arg; + mysql_stmt_attr_get(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg); + return arg == 1 ? Qtrue : Qfalse; + } + rb_raise(eMysql, "unknown option: %d", NUM2INT(opt)); +} + +/* attr_set(option, arg) */ +static VALUE stmt_attr_set(VALUE obj, VALUE opt, VALUE val) +{ + struct mysql_stmt* s = DATA_PTR(obj); + check_stmt_closed(obj); + if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) { + my_bool arg; + arg = (val == Qnil || val == Qfalse) ? 0 : 1; + mysql_stmt_attr_set(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg); + return obj; + } + rb_raise(eMysql, "unknown option: %d", NUM2INT(opt)); +} +#endif + +/* bind_result(bind,...) */ +static VALUE stmt_bind_result(int argc, VALUE *argv, VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + int i; + MYSQL_FIELD *field; + + check_stmt_closed(obj); + if (argc != s->result.n) + rb_raise(eMysql, "bind_result: result value count(%d) != number of argument(%d)", s->result.n, argc); + for (i = 0; i < argc; i++) { + if (argv[i] == Qnil || argv[i] == rb_cNilClass) { + field = mysql_fetch_fields(s->res); + s->result.bind[i].buffer_type = field[i].type; + } + else if (argv[i] == rb_cString) + s->result.bind[i].buffer_type = MYSQL_TYPE_STRING; + else if (argv[i] == rb_cNumeric || argv[i] == rb_cInteger || argv[i] == rb_cFixnum) + s->result.bind[i].buffer_type = MYSQL_TYPE_LONGLONG; + else if (argv[i] == rb_cFloat) + s->result.bind[i].buffer_type = MYSQL_TYPE_DOUBLE; + else if (argv[i] == cMysqlTime) + s->result.bind[i].buffer_type = MYSQL_TYPE_DATETIME; + else + rb_raise(rb_eTypeError, "unrecognized class: %s", RSTRING_PTR(rb_inspect(argv[i]))); + if (mysql_stmt_bind_result(s->stmt, s->result.bind)) + mysql_stmt_raise(s->stmt); + } + return obj; +} + +/* close() */ +static VALUE stmt_close(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + check_stmt_closed(obj); + mysql_stmt_close(s->stmt); + s->closed = Qtrue; + return Qnil; +} + +/* data_seek(offset) */ +static VALUE stmt_data_seek(VALUE obj, VALUE offset) +{ + struct mysql_stmt* s = DATA_PTR(obj); + check_stmt_closed(obj); + mysql_stmt_data_seek(s->stmt, NUM2INT(offset)); + return obj; +} + +/* execute(arg,...) */ +static VALUE stmt_execute(int argc, VALUE *argv, VALUE obj) +{ + struct mysql_stmt *s = DATA_PTR(obj); + MYSQL_STMT *stmt = s->stmt; + int i; + + check_stmt_closed(obj); + free_execute_memory(s); + if (s->param.n != argc) + rb_raise(eMysql, "execute: param_count(%d) != number of argument(%d)", s->param.n, argc); + if (argc > 0) { + memset(s->param.bind, 0, sizeof(*(s->param.bind))*argc); + for (i = 0; i < argc; i++) { + switch (TYPE(argv[i])) { + case T_NIL: + s->param.bind[i].buffer_type = MYSQL_TYPE_NULL; + break; + case T_FIXNUM: +#if SIZEOF_INT < SIZEOF_LONG + s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG; + s->param.bind[i].buffer = &(s->param.buffer[i]); + *(LONG_LONG*)(s->param.bind[i].buffer) = FIX2LONG(argv[i]); +#else + s->param.bind[i].buffer_type = MYSQL_TYPE_LONG; + s->param.bind[i].buffer = &(s->param.buffer[i]); + *(int*)(s->param.bind[i].buffer) = FIX2INT(argv[i]); +#endif + break; + case T_BIGNUM: + s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG; + s->param.bind[i].buffer = &(s->param.buffer[i]); + *(LONG_LONG*)(s->param.bind[i].buffer) = rb_big2ll(argv[i]); + break; + case T_FLOAT: + s->param.bind[i].buffer_type = MYSQL_TYPE_DOUBLE; + s->param.bind[i].buffer = &(s->param.buffer[i]); + *(double*)(s->param.bind[i].buffer) = NUM2DBL(argv[i]); + break; + case T_STRING: + s->param.bind[i].buffer_type = MYSQL_TYPE_STRING; + s->param.bind[i].buffer = RSTRING_PTR(argv[i]); + s->param.bind[i].buffer_length = RSTRING_LEN(argv[i]); + s->param.length[i] = RSTRING_LEN(argv[i]); + s->param.bind[i].length = &(s->param.length[i]); + break; + default: + if (CLASS_OF(argv[i]) == rb_cTime) { + MYSQL_TIME t; + VALUE a = rb_funcall(argv[i], rb_intern("to_a"), 0); + s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME; + s->param.bind[i].buffer = &(s->param.buffer[i]); + t.second_part = 0; + t.neg = 0; + t.second = FIX2INT(RARRAY(a)->ptr[0]); + t.minute = FIX2INT(RARRAY(a)->ptr[1]); + t.hour = FIX2INT(RARRAY(a)->ptr[2]); + t.day = FIX2INT(RARRAY(a)->ptr[3]); + t.month = FIX2INT(RARRAY(a)->ptr[4]); + t.year = FIX2INT(RARRAY(a)->ptr[5]); + *(MYSQL_TIME*)&(s->param.buffer[i]) = t; + } else if (CLASS_OF(argv[i]) == cMysqlTime) { + MYSQL_TIME t; + s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME; + s->param.bind[i].buffer = &(s->param.buffer[i]); + t.second_part = 0; + t.neg = 0; + t.second = NUM2INT(rb_iv_get(argv[i], "second")); + t.minute = NUM2INT(rb_iv_get(argv[i], "minute")); + t.hour = NUM2INT(rb_iv_get(argv[i], "hour")); + t.day = NUM2INT(rb_iv_get(argv[i], "day")); + t.month = NUM2INT(rb_iv_get(argv[i], "month")); + t.year = NUM2INT(rb_iv_get(argv[i], "year")); + *(MYSQL_TIME*)&(s->param.buffer[i]) = t; + } else + rb_raise(rb_eTypeError, "unsupported type: %d", TYPE(argv[i])); + } + } + if (mysql_stmt_bind_param(stmt, s->param.bind)) + mysql_stmt_raise(stmt); + } + + if (mysql_stmt_execute(stmt)) + mysql_stmt_raise(stmt); + if (s->res) { + MYSQL_FIELD *field; + if (mysql_stmt_store_result(stmt)) + mysql_stmt_raise(stmt); + field = mysql_fetch_fields(s->res); + for (i = 0; i < s->result.n; i++) { + switch(s->result.bind[i].buffer_type) { + case MYSQL_TYPE_NULL: + break; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + s->result.bind[i].buffer = xmalloc(8); + s->result.bind[i].buffer_length = 8; + memset(s->result.bind[i].buffer, 0, 8); + break; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: +#if MYSQL_VERSION_ID >= 50003 + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_BIT: +#endif + s->result.bind[i].buffer = xmalloc(field[i].max_length); + memset(s->result.bind[i].buffer, 0, field[i].max_length); + s->result.bind[i].buffer_length = field[i].max_length; + break; + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + s->result.bind[i].buffer = xmalloc(sizeof(MYSQL_TIME)); + s->result.bind[i].buffer_length = sizeof(MYSQL_TIME); + memset(s->result.bind[i].buffer, 0, sizeof(MYSQL_TIME)); + break; + default: + rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type); + } + } + if (mysql_stmt_bind_result(s->stmt, s->result.bind)) + mysql_stmt_raise(s->stmt); + } + return obj; +} + +/* fetch() */ +static VALUE stmt_fetch(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + VALUE ret; + int i; + int r; + + check_stmt_closed(obj); + r = mysql_stmt_fetch(s->stmt); + if (r == MYSQL_NO_DATA) + return Qnil; +#ifdef MYSQL_DATA_TRUNCATED + if (r == MYSQL_DATA_TRUNCATED) + rb_raise(rb_eRuntimeError, "unexpectedly data truncated"); +#endif + if (r == 1) + mysql_stmt_raise(s->stmt); + + ret = rb_ary_new2(s->result.n); + for (i = 0; i < s->result.n; i++) { + if (s->result.is_null[i]) + rb_ary_push(ret, Qnil); + else { + VALUE v; + MYSQL_TIME *t; + switch (s->result.bind[i].buffer_type) { + case MYSQL_TYPE_TINY: + if (s->result.bind[i].is_unsigned) + v = UINT2NUM(*(unsigned char *)s->result.bind[i].buffer); + else + v = INT2NUM(*(signed char *)s->result.bind[i].buffer); + break; + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_YEAR: + if (s->result.bind[i].is_unsigned) + v = UINT2NUM(*(unsigned short *)s->result.bind[i].buffer); + else + v = INT2NUM(*(short *)s->result.bind[i].buffer); + break; + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + if (s->result.bind[i].is_unsigned) + v = UINT2NUM(*(unsigned int *)s->result.bind[i].buffer); + else + v = INT2NUM(*(int *)s->result.bind[i].buffer); + break; + case MYSQL_TYPE_LONGLONG: + if (s->result.bind[i].is_unsigned) + v = ULL2NUM(*(unsigned long long *)s->result.bind[i].buffer); + else + v = LL2NUM(*(long long *)s->result.bind[i].buffer); + break; + case MYSQL_TYPE_FLOAT: + v = rb_float_new((double)(*(float *)s->result.bind[i].buffer)); + break; + case MYSQL_TYPE_DOUBLE: + v = rb_float_new(*(double *)s->result.bind[i].buffer); + break; + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + t = (MYSQL_TIME *)s->result.bind[i].buffer; + v = rb_obj_alloc(cMysqlTime); + rb_funcall(v, rb_intern("initialize"), 8, + INT2FIX(t->year), INT2FIX(t->month), + INT2FIX(t->day), INT2FIX(t->hour), + INT2FIX(t->minute), INT2FIX(t->second), + (t->neg ? Qtrue : Qfalse), + INT2FIX(t->second_part)); + break; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: +#if MYSQL_VERSION_ID >= 50003 + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_BIT: +#endif + v = rb_tainted_str_new(s->result.bind[i].buffer, s->result.length[i]); + break; + default: + rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type); + } + rb_ary_push(ret, v); + } + } + return ret; +} + +/* each {...} */ +static VALUE stmt_each(VALUE obj) +{ + VALUE row; + check_stmt_closed(obj); + while ((row = stmt_fetch(obj)) != Qnil) + rb_yield(row); + return obj; +} + +/* field_count() */ +static VALUE stmt_field_count(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + unsigned int n; + check_stmt_closed(obj); + n = mysql_stmt_field_count(s->stmt); + return INT2NUM(n); +} + +/* free_result() */ +static VALUE stmt_free_result(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + check_stmt_closed(obj); + if (mysql_stmt_free_result(s->stmt)) + mysql_stmt_raise(s->stmt); + return obj; +} + +/* insert_id() */ +static VALUE stmt_insert_id(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + my_ulonglong n; + check_stmt_closed(obj); + n = mysql_stmt_insert_id(s->stmt); + return INT2NUM(n); +} + +/* num_rows() */ +static VALUE stmt_num_rows(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + my_ulonglong n; + check_stmt_closed(obj); + n = mysql_stmt_num_rows(s->stmt); + return INT2NUM(n); +} + +/* param_count() */ +static VALUE stmt_param_count(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + unsigned long n; + check_stmt_closed(obj); + n = mysql_stmt_param_count(s->stmt); + return INT2NUM(n); +} + +/* prepare(query) */ +static VALUE stmt_prepare(VALUE obj, VALUE query) +{ + struct mysql_stmt* s = DATA_PTR(obj); + int n; + int i; + MYSQL_FIELD *field; + + free_mysqlstmt_memory(s); + check_stmt_closed(obj); + Check_Type(query, T_STRING); + if (mysql_stmt_prepare(s->stmt, RSTRING_PTR(query), RSTRING_LEN(query))) + mysql_stmt_raise(s->stmt); + + n = mysql_stmt_param_count(s->stmt); + s->param.n = n; + s->param.bind = xmalloc(sizeof(s->param.bind[0]) * n); + s->param.length = xmalloc(sizeof(s->param.length[0]) * n); + s->param.buffer = xmalloc(sizeof(s->param.buffer[0]) * n); + + s->res = mysql_stmt_result_metadata(s->stmt); + if (s->res) { + n = s->result.n = mysql_num_fields(s->res); + s->result.bind = xmalloc(sizeof(s->result.bind[0]) * n); + s->result.is_null = xmalloc(sizeof(s->result.is_null[0]) * n); + s->result.length = xmalloc(sizeof(s->result.length[0]) * n); + field = mysql_fetch_fields(s->res); + memset(s->result.bind, 0, sizeof(s->result.bind[0]) * n); + for (i = 0; i < n; i++) { + s->result.bind[i].buffer_type = field[i].type; +#if MYSQL_VERSION_ID < 50003 + if (field[i].type == MYSQL_TYPE_DECIMAL) + s->result.bind[i].buffer_type = MYSQL_TYPE_STRING; +#endif + s->result.bind[i].is_null = &(s->result.is_null[i]); + s->result.bind[i].length = &(s->result.length[i]); + s->result.bind[i].is_unsigned = ((field[i].flags & UNSIGNED_FLAG) != 0); + } + } else { + if (mysql_stmt_errno(s->stmt)) + mysql_stmt_raise(s->stmt); + } + + return obj; +} + +#if 0 +/* reset() */ +static VALUE stmt_reset(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + check_stmt_closed(obj); + if (mysql_stmt_reset(s->stmt)) + mysql_stmt_raise(s->stmt); + return obj; +} +#endif + +/* result_metadata() */ +static VALUE stmt_result_metadata(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + MYSQL_RES *res; + check_stmt_closed(obj); + res = mysql_stmt_result_metadata(s->stmt); + if (res == NULL) { + if (mysql_stmt_errno(s->stmt) != 0) + mysql_stmt_raise(s->stmt); + return Qnil; + } + return mysqlres2obj(res); +} + +/* row_seek(offset) */ +static VALUE stmt_row_seek(VALUE obj, VALUE offset) +{ + struct mysql_stmt* s = DATA_PTR(obj); + MYSQL_ROW_OFFSET prev_offset; + if (CLASS_OF(offset) != cMysqlRowOffset) + rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset)); + check_stmt_closed(obj); + prev_offset = mysql_stmt_row_seek(s->stmt, DATA_PTR(offset)); + return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset); +} + +/* row_tell() */ +static VALUE stmt_row_tell(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + MYSQL_ROW_OFFSET offset; + check_stmt_closed(obj); + offset = mysql_stmt_row_tell(s->stmt); + return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset); +} + +#if 0 +/* send_long_data(col, data) */ +static VALUE stmt_send_long_data(VALUE obj, VALUE col, VALUE data) +{ + struct mysql_stmt* s = DATA_PTR(obj); + int c; + check_stmt_closed(obj); + c = NUM2INT(col); + if (0 <= c && c < s->param.n) { + s->param.bind[c].buffer_type = MYSQL_TYPE_STRING; + if (mysql_stmt_bind_param(s->stmt, s->param.bind)) + mysql_stmt_raise(s->stmt); + } + if (mysql_stmt_send_long_data(s->stmt, c, RSTRING_PTR(data), RSTRING_LEN(data))) + mysql_stmt_raise(s->stmt); + return obj; +} +#endif + +/* sqlstate() */ +static VALUE stmt_sqlstate(VALUE obj) +{ + struct mysql_stmt* s = DATA_PTR(obj); + return rb_tainted_str_new2(mysql_stmt_sqlstate(s->stmt)); +} + +/*------------------------------- + * Mysql::Time object method + */ + +static VALUE time_initialize(int argc, VALUE* argv, VALUE obj) +{ + VALUE year, month, day, hour, minute, second, neg, second_part; + rb_scan_args(argc, argv, "08", &year, &month, &day, &hour, &minute, &second, &neg, &second_part); +#define NILorFIXvalue(o) (NIL_P(o) ? INT2FIX(0) : (Check_Type(o, T_FIXNUM), o)) + rb_iv_set(obj, "year", NILorFIXvalue(year)); + rb_iv_set(obj, "month", NILorFIXvalue(month)); + rb_iv_set(obj, "day", NILorFIXvalue(day)); + rb_iv_set(obj, "hour", NILorFIXvalue(hour)); + rb_iv_set(obj, "minute", NILorFIXvalue(minute)); + rb_iv_set(obj, "second", NILorFIXvalue(second)); + rb_iv_set(obj, "neg", (neg == Qnil || neg == Qfalse) ? Qfalse : Qtrue); + rb_iv_set(obj, "second_part", NILorFIXvalue(second_part)); + return obj; +} + +static VALUE time_inspect(VALUE obj) +{ + char buf[36]; + sprintf(buf, "#", + NUM2INT(rb_iv_get(obj, "year")), + NUM2INT(rb_iv_get(obj, "month")), + NUM2INT(rb_iv_get(obj, "day")), + NUM2INT(rb_iv_get(obj, "hour")), + NUM2INT(rb_iv_get(obj, "minute")), + NUM2INT(rb_iv_get(obj, "second"))); + return rb_str_new2(buf); +} + +static VALUE time_to_s(VALUE obj) +{ + char buf[20]; + sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", + NUM2INT(rb_iv_get(obj, "year")), + NUM2INT(rb_iv_get(obj, "month")), + NUM2INT(rb_iv_get(obj, "day")), + NUM2INT(rb_iv_get(obj, "hour")), + NUM2INT(rb_iv_get(obj, "minute")), + NUM2INT(rb_iv_get(obj, "second"))); + return rb_str_new2(buf); +} + +#define DefineMysqlTimeGetMethod(m)\ +static VALUE time_get_##m(VALUE obj)\ +{return rb_iv_get(obj, #m);} + +DefineMysqlTimeGetMethod(year) +DefineMysqlTimeGetMethod(month) +DefineMysqlTimeGetMethod(day) +DefineMysqlTimeGetMethod(hour) +DefineMysqlTimeGetMethod(minute) +DefineMysqlTimeGetMethod(second) +DefineMysqlTimeGetMethod(neg) +DefineMysqlTimeGetMethod(second_part) + +#define DefineMysqlTimeSetMethod(m)\ +static VALUE time_set_##m(VALUE obj, VALUE v)\ +{rb_iv_set(obj, #m, NILorFIXvalue(v)); return v;} + +DefineMysqlTimeSetMethod(year) +DefineMysqlTimeSetMethod(month) +DefineMysqlTimeSetMethod(day) +DefineMysqlTimeSetMethod(hour) +DefineMysqlTimeSetMethod(minute) +DefineMysqlTimeSetMethod(second) +DefineMysqlTimeSetMethod(second_part) + +static VALUE time_set_neg(VALUE obj, VALUE v) +{ + rb_iv_set(obj, "neg", (v == Qnil || v == Qfalse) ? Qfalse : Qtrue); + return v; +} + +static VALUE time_equal(VALUE obj, VALUE v) +{ + if (CLASS_OF(v) == cMysqlTime && + NUM2INT(rb_iv_get(obj, "year")) == NUM2INT(rb_iv_get(v, "year")) && + NUM2INT(rb_iv_get(obj, "month")) == NUM2INT(rb_iv_get(v, "month")) && + NUM2INT(rb_iv_get(obj, "day")) == NUM2INT(rb_iv_get(v, "day")) && + NUM2INT(rb_iv_get(obj, "hour")) == NUM2INT(rb_iv_get(v, "hour")) && + NUM2INT(rb_iv_get(obj, "minute")) == NUM2INT(rb_iv_get(v, "minute")) && + NUM2INT(rb_iv_get(obj, "second")) == NUM2INT(rb_iv_get(v, "second")) && + rb_iv_get(obj, "neg") == rb_iv_get(v, "neg") && + NUM2INT(rb_iv_get(obj, "second_part")) == NUM2INT(rb_iv_get(v, "second_part"))) + return Qtrue; + return Qfalse; +} + +#endif + +/*------------------------------- + * Mysql::Error object method + */ + +static VALUE error_error(VALUE obj) +{ + return rb_iv_get(obj, "mesg"); +} + +static VALUE error_errno(VALUE obj) +{ + return rb_iv_get(obj, "errno"); +} + +static VALUE error_sqlstate(VALUE obj) +{ + return rb_iv_get(obj, "sqlstate"); +} + +/*------------------------------- + * Initialize + */ + +void Init_mysql(void) +{ + cMysql = rb_define_class("Mysql", rb_cObject); + cMysqlRes = rb_define_class_under(cMysql, "Result", rb_cObject); + cMysqlField = rb_define_class_under(cMysql, "Field", rb_cObject); +#if MYSQL_VERSION_ID >= 40102 + cMysqlStmt = rb_define_class_under(cMysql, "Stmt", rb_cObject); + cMysqlRowOffset = rb_define_class_under(cMysql, "RowOffset", rb_cObject); + cMysqlTime = rb_define_class_under(cMysql, "Time", rb_cObject); +#endif + eMysql = rb_define_class_under(cMysql, "Error", rb_eStandardError); + + rb_define_global_const("MysqlRes", cMysqlRes); + rb_define_global_const("MysqlField", cMysqlField); + rb_define_global_const("MysqlError", eMysql); + + /* Mysql class method */ + rb_define_singleton_method(cMysql, "init", init, 0); + rb_define_singleton_method(cMysql, "real_connect", real_connect, -1); + rb_define_singleton_method(cMysql, "connect", real_connect, -1); + rb_define_singleton_method(cMysql, "new", real_connect, -1); + rb_define_singleton_method(cMysql, "escape_string", escape_string, 1); + rb_define_singleton_method(cMysql, "quote", escape_string, 1); + rb_define_singleton_method(cMysql, "client_info", client_info, 0); + rb_define_singleton_method(cMysql, "get_client_info", client_info, 0); +#if MYSQL_VERSION_ID >= 32332 + rb_define_singleton_method(cMysql, "debug", my_debug, 1); +#endif +#if MYSQL_VERSION_ID >= 40000 + rb_define_singleton_method(cMysql, "get_client_version", client_version, 0); + rb_define_singleton_method(cMysql, "client_version", client_version, 0); +#endif + + /* Mysql object method */ +#if MYSQL_VERSION_ID >= 32200 + rb_define_method(cMysql, "real_connect", real_connect2, -1); + rb_define_method(cMysql, "connect", real_connect2, -1); + rb_define_method(cMysql, "options", options, -1); +#endif + rb_define_method(cMysql, "initialize", initialize, -1); +#if MYSQL_VERSION_ID >= 32332 + rb_define_method(cMysql, "escape_string", real_escape_string, 1); + rb_define_method(cMysql, "quote", real_escape_string, 1); +#else + rb_define_method(cMysql, "escape_string", escape_string, 1); + rb_define_method(cMysql, "quote", escape_string, 1); +#endif + rb_define_method(cMysql, "client_info", client_info, 0); + rb_define_method(cMysql, "get_client_info", client_info, 0); + rb_define_method(cMysql, "affected_rows", affected_rows, 0); +#if MYSQL_VERSION_ID >= 32303 + rb_define_method(cMysql, "change_user", change_user, -1); +#endif +#if MYSQL_VERSION_ID >= 32321 + rb_define_method(cMysql, "character_set_name", character_set_name, 0); +#endif + rb_define_method(cMysql, "close", my_close, 0); +#if MYSQL_VERSION_ID < 40000 + rb_define_method(cMysql, "create_db", create_db, 1); + rb_define_method(cMysql, "drop_db", drop_db, 1); +#endif +#if MYSQL_VERSION_ID >= 32332 + rb_define_method(cMysql, "dump_debug_info", dump_debug_info, 0); +#endif + rb_define_method(cMysql, "errno", my_errno, 0); + rb_define_method(cMysql, "error", my_error, 0); + rb_define_method(cMysql, "field_count", field_count, 0); +#if MYSQL_VERSION_ID >= 40000 + rb_define_method(cMysql, "get_client_version", client_version, 0); + rb_define_method(cMysql, "client_version", client_version, 0); +#endif + rb_define_method(cMysql, "get_host_info", host_info, 0); + rb_define_method(cMysql, "host_info", host_info, 0); + rb_define_method(cMysql, "get_proto_info", proto_info, 0); + rb_define_method(cMysql, "proto_info", proto_info, 0); + rb_define_method(cMysql, "get_server_info", server_info, 0); + rb_define_method(cMysql, "server_info", server_info, 0); + rb_define_method(cMysql, "info", info, 0); + rb_define_method(cMysql, "insert_id", insert_id, 0); + rb_define_method(cMysql, "kill", my_kill, 1); + rb_define_method(cMysql, "list_dbs", list_dbs, -1); + rb_define_method(cMysql, "list_fields", list_fields, -1); + rb_define_method(cMysql, "list_processes", list_processes, 0); + rb_define_method(cMysql, "list_tables", list_tables, -1); +#if MYSQL_VERSION_ID >= 32200 + rb_define_method(cMysql, "ping", ping, 0); +#endif + rb_define_method(cMysql, "query", query, 1); + rb_define_method(cMysql, "real_query", query, 1); + rb_define_method(cMysql, "async_query", async_query, 1); + rb_define_method(cMysql, "send_query", send_query, 1); + rb_define_method(cMysql, "get_result", get_result, 0); + rb_define_method(cMysql, "socket", socket, 0); + rb_define_method(cMysql, "refresh", refresh, 1); + rb_define_method(cMysql, "reload", reload, 0); + rb_define_method(cMysql, "select_db", select_db, 1); + rb_define_method(cMysql, "shutdown", my_shutdown, -1); + rb_define_method(cMysql, "stat", my_stat, 0); + rb_define_method(cMysql, "store_result", store_result, 0); + rb_define_method(cMysql, "thread_id", thread_id, 0); + rb_define_method(cMysql, "use_result", use_result, 0); +#if MYSQL_VERSION_ID >= 40100 + rb_define_method(cMysql, "get_server_version", server_version, 0); + rb_define_method(cMysql, "server_version", server_version, 0); + rb_define_method(cMysql, "warning_count", warning_count, 0); + rb_define_method(cMysql, "commit", commit, 0); + rb_define_method(cMysql, "rollback", rollback, 0); + rb_define_method(cMysql, "autocommit", autocommit, 1); +#endif +#ifdef HAVE_MYSQL_SSL_SET + rb_define_method(cMysql, "ssl_set", ssl_set, -1); +#endif +#if MYSQL_VERSION_ID >= 40102 + rb_define_method(cMysql, "stmt_init", stmt_init, 0); + rb_define_method(cMysql, "prepare", prepare, 1); +#endif +#if MYSQL_VERSION_ID >= 40100 + rb_define_method(cMysql, "more_results", more_results, 0); + rb_define_method(cMysql, "more_results?", more_results, 0); + rb_define_method(cMysql, "next_result", next_result, 0); +#endif +#if MYSQL_VERSION_ID >= 40101 + rb_define_method(cMysql, "set_server_option", set_server_option, 1); + rb_define_method(cMysql, "sqlstate", sqlstate, 0); +#endif + rb_define_method(cMysql, "query_with_result", query_with_result, 0); + rb_define_method(cMysql, "query_with_result=", query_with_result_set, 1); + + rb_define_method(cMysql, "reconnect", reconnect, 0); + rb_define_method(cMysql, "reconnect=", reconnect_set, 1); + + /* Mysql constant */ + rb_define_const(cMysql, "VERSION", INT2FIX(MYSQL_RUBY_VERSION)); +#if MYSQL_VERSION_ID >= 32200 + rb_define_const(cMysql, "OPT_CONNECT_TIMEOUT", INT2NUM(MYSQL_OPT_CONNECT_TIMEOUT)); + rb_define_const(cMysql, "OPT_COMPRESS", INT2NUM(MYSQL_OPT_COMPRESS)); + rb_define_const(cMysql, "OPT_NAMED_PIPE", INT2NUM(MYSQL_OPT_NAMED_PIPE)); + rb_define_const(cMysql, "INIT_COMMAND", INT2NUM(MYSQL_INIT_COMMAND)); + rb_define_const(cMysql, "READ_DEFAULT_FILE", INT2NUM(MYSQL_READ_DEFAULT_FILE)); + rb_define_const(cMysql, "READ_DEFAULT_GROUP", INT2NUM(MYSQL_READ_DEFAULT_GROUP)); +#endif +#if MYSQL_VERSION_ID >= 32349 + rb_define_const(cMysql, "SET_CHARSET_DIR", INT2NUM(MYSQL_SET_CHARSET_DIR)); + rb_define_const(cMysql, "SET_CHARSET_NAME", INT2NUM(MYSQL_SET_CHARSET_NAME)); + rb_define_const(cMysql, "OPT_LOCAL_INFILE", INT2NUM(MYSQL_OPT_LOCAL_INFILE)); +#endif +#if MYSQL_VERSION_ID >= 40100 + rb_define_const(cMysql, "OPT_PROTOCOL", INT2NUM(MYSQL_OPT_PROTOCOL)); + rb_define_const(cMysql, "SHARED_MEMORY_BASE_NAME", INT2NUM(MYSQL_SHARED_MEMORY_BASE_NAME)); +#endif +#if MYSQL_VERSION_ID >= 40101 + rb_define_const(cMysql, "OPT_READ_TIMEOUT", INT2NUM(MYSQL_OPT_READ_TIMEOUT)); + rb_define_const(cMysql, "OPT_WRITE_TIMEOUT", INT2NUM(MYSQL_OPT_WRITE_TIMEOUT)); + rb_define_const(cMysql, "SECURE_AUTH", INT2NUM(MYSQL_SECURE_AUTH)); + rb_define_const(cMysql, "OPT_GUESS_CONNECTION", INT2NUM(MYSQL_OPT_GUESS_CONNECTION)); + rb_define_const(cMysql, "OPT_USE_EMBEDDED_CONNECTION", INT2NUM(MYSQL_OPT_USE_EMBEDDED_CONNECTION)); + rb_define_const(cMysql, "OPT_USE_REMOTE_CONNECTION", INT2NUM(MYSQL_OPT_USE_REMOTE_CONNECTION)); + rb_define_const(cMysql, "SET_CLIENT_IP", INT2NUM(MYSQL_SET_CLIENT_IP)); +#endif + rb_define_const(cMysql, "REFRESH_GRANT", INT2NUM(REFRESH_GRANT)); + rb_define_const(cMysql, "REFRESH_LOG", INT2NUM(REFRESH_LOG)); + rb_define_const(cMysql, "REFRESH_TABLES", INT2NUM(REFRESH_TABLES)); +#ifdef REFRESH_HOSTS + rb_define_const(cMysql, "REFRESH_HOSTS", INT2NUM(REFRESH_HOSTS)); +#endif +#ifdef REFRESH_STATUS + rb_define_const(cMysql, "REFRESH_STATUS", INT2NUM(REFRESH_STATUS)); +#endif +#ifdef REFRESH_THREADS + rb_define_const(cMysql, "REFRESH_THREADS", INT2NUM(REFRESH_THREADS)); +#endif +#ifdef REFRESH_SLAVE + rb_define_const(cMysql, "REFRESH_SLAVE", INT2NUM(REFRESH_SLAVE)); +#endif +#ifdef REFRESH_MASTER + rb_define_const(cMysql, "REFRESH_MASTER", INT2NUM(REFRESH_MASTER)); +#endif +#ifdef CLIENT_LONG_PASSWORD +#endif +#ifdef CLIENT_FOUND_ROWS + rb_define_const(cMysql, "CLIENT_FOUND_ROWS", INT2NUM(CLIENT_FOUND_ROWS)); +#endif +#ifdef CLIENT_LONG_FLAG +#endif +#ifdef CLIENT_CONNECT_WITH_DB +#endif +#ifdef CLIENT_NO_SCHEMA + rb_define_const(cMysql, "CLIENT_NO_SCHEMA", INT2NUM(CLIENT_NO_SCHEMA)); +#endif +#ifdef CLIENT_COMPRESS + rb_define_const(cMysql, "CLIENT_COMPRESS", INT2NUM(CLIENT_COMPRESS)); +#endif +#ifdef CLIENT_ODBC + rb_define_const(cMysql, "CLIENT_ODBC", INT2NUM(CLIENT_ODBC)); +#endif +#ifdef CLIENT_LOCAL_FILES + rb_define_const(cMysql, "CLIENT_LOCAL_FILES", INT2NUM(CLIENT_LOCAL_FILES)); +#endif +#ifdef CLIENT_IGNORE_SPACE + rb_define_const(cMysql, "CLIENT_IGNORE_SPACE", INT2NUM(CLIENT_IGNORE_SPACE)); +#endif +#ifdef CLIENT_CHANGE_USER + rb_define_const(cMysql, "CLIENT_CHANGE_USER", INT2NUM(CLIENT_CHANGE_USER)); +#endif +#ifdef CLIENT_INTERACTIVE + rb_define_const(cMysql, "CLIENT_INTERACTIVE", INT2NUM(CLIENT_INTERACTIVE)); +#endif +#ifdef CLIENT_SSL + rb_define_const(cMysql, "CLIENT_SSL", INT2NUM(CLIENT_SSL)); +#endif +#ifdef CLIENT_IGNORE_SIGPIPE + rb_define_const(cMysql, "CLIENT_IGNORE_SIGPIPE", INT2NUM(CLIENT_IGNORE_SIGPIPE)); +#endif +#ifdef CLIENT_TRANSACTIONS + rb_define_const(cMysql, "CLIENT_TRANSACTIONS", INT2NUM(CLIENT_TRANSACTIONS)); +#endif +#ifdef CLIENT_MULTI_STATEMENTS + rb_define_const(cMysql, "CLIENT_MULTI_STATEMENTS", INT2NUM(CLIENT_MULTI_STATEMENTS)); +#endif +#ifdef CLIENT_MULTI_RESULTS + rb_define_const(cMysql, "CLIENT_MULTI_RESULTS", INT2NUM(CLIENT_MULTI_RESULTS)); +#endif +#if MYSQL_VERSION_ID >= 40101 + rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_ON", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON)); + rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_OFF", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF)); +#endif + + /* Mysql::Result object method */ + rb_define_method(cMysqlRes, "data_seek", data_seek, 1); + rb_define_method(cMysqlRes, "fetch_field", fetch_field, 0); + rb_define_method(cMysqlRes, "fetch_fields", fetch_fields, 0); + rb_define_method(cMysqlRes, "fetch_field_direct", fetch_field_direct, 1); + rb_define_method(cMysqlRes, "fetch_lengths", fetch_lengths, 0); + rb_define_method(cMysqlRes, "fetch_row", fetch_row, 0); + rb_define_method(cMysqlRes, "fetch_hash", fetch_hash, -1); + rb_define_method(cMysqlRes, "field_seek", field_seek, 1); + rb_define_method(cMysqlRes, "field_tell", field_tell, 0); + rb_define_method(cMysqlRes, "free", res_free, 0); + rb_define_method(cMysqlRes, "num_fields", num_fields, 0); + rb_define_method(cMysqlRes, "num_rows", num_rows, 0); + rb_define_method(cMysqlRes, "row_seek", row_seek, 1); + rb_define_method(cMysqlRes, "row_tell", row_tell, 0); + rb_define_method(cMysqlRes, "each", each, 0); + rb_define_method(cMysqlRes, "each_hash", each_hash, -1); + + /* MysqlField object method */ + rb_define_method(cMysqlField, "name", field_name, 0); + rb_define_method(cMysqlField, "table", field_table, 0); + rb_define_method(cMysqlField, "def", field_def, 0); + rb_define_method(cMysqlField, "type", field_type, 0); + rb_define_method(cMysqlField, "length", field_length, 0); + rb_define_method(cMysqlField, "max_length", field_max_length, 0); + rb_define_method(cMysqlField, "flags", field_flags, 0); + rb_define_method(cMysqlField, "decimals", field_decimals, 0); + rb_define_method(cMysqlField, "hash", field_hash, 0); + rb_define_method(cMysqlField, "inspect", field_inspect, 0); +#ifdef IS_NUM + rb_define_method(cMysqlField, "is_num?", field_is_num, 0); +#endif +#ifdef IS_NOT_NULL + rb_define_method(cMysqlField, "is_not_null?", field_is_not_null, 0); +#endif +#ifdef IS_PRI_KEY + rb_define_method(cMysqlField, "is_pri_key?", field_is_pri_key, 0); +#endif + + /* Mysql::Field constant: TYPE */ + rb_define_const(cMysqlField, "TYPE_TINY", INT2NUM(FIELD_TYPE_TINY)); +#if MYSQL_VERSION_ID >= 32115 + rb_define_const(cMysqlField, "TYPE_ENUM", INT2NUM(FIELD_TYPE_ENUM)); +#endif + rb_define_const(cMysqlField, "TYPE_DECIMAL", INT2NUM(FIELD_TYPE_DECIMAL)); + rb_define_const(cMysqlField, "TYPE_SHORT", INT2NUM(FIELD_TYPE_SHORT)); + rb_define_const(cMysqlField, "TYPE_LONG", INT2NUM(FIELD_TYPE_LONG)); + rb_define_const(cMysqlField, "TYPE_FLOAT", INT2NUM(FIELD_TYPE_FLOAT)); + rb_define_const(cMysqlField, "TYPE_DOUBLE", INT2NUM(FIELD_TYPE_DOUBLE)); + rb_define_const(cMysqlField, "TYPE_NULL", INT2NUM(FIELD_TYPE_NULL)); + rb_define_const(cMysqlField, "TYPE_TIMESTAMP", INT2NUM(FIELD_TYPE_TIMESTAMP)); + rb_define_const(cMysqlField, "TYPE_LONGLONG", INT2NUM(FIELD_TYPE_LONGLONG)); + rb_define_const(cMysqlField, "TYPE_INT24", INT2NUM(FIELD_TYPE_INT24)); + rb_define_const(cMysqlField, "TYPE_DATE", INT2NUM(FIELD_TYPE_DATE)); + rb_define_const(cMysqlField, "TYPE_TIME", INT2NUM(FIELD_TYPE_TIME)); + rb_define_const(cMysqlField, "TYPE_DATETIME", INT2NUM(FIELD_TYPE_DATETIME)); +#if MYSQL_VERSION_ID >= 32130 + rb_define_const(cMysqlField, "TYPE_YEAR", INT2NUM(FIELD_TYPE_YEAR)); +#endif +#if MYSQL_VERSION_ID >= 50003 + rb_define_const(cMysqlField, "TYPE_BIT", INT2NUM(FIELD_TYPE_BIT)); + rb_define_const(cMysqlField, "TYPE_NEWDECIMAL", INT2NUM(FIELD_TYPE_NEWDECIMAL)); +#endif + rb_define_const(cMysqlField, "TYPE_SET", INT2NUM(FIELD_TYPE_SET)); + rb_define_const(cMysqlField, "TYPE_BLOB", INT2NUM(FIELD_TYPE_BLOB)); + rb_define_const(cMysqlField, "TYPE_STRING", INT2NUM(FIELD_TYPE_STRING)); +#if MYSQL_VERSION_ID >= 40000 + rb_define_const(cMysqlField, "TYPE_VAR_STRING", INT2NUM(FIELD_TYPE_VAR_STRING)); +#endif + rb_define_const(cMysqlField, "TYPE_CHAR", INT2NUM(FIELD_TYPE_CHAR)); + + /* Mysql::Field constant: FLAG */ + rb_define_const(cMysqlField, "NOT_NULL_FLAG", INT2NUM(NOT_NULL_FLAG)); + rb_define_const(cMysqlField, "PRI_KEY_FLAG", INT2NUM(PRI_KEY_FLAG)); + rb_define_const(cMysqlField, "UNIQUE_KEY_FLAG", INT2NUM(UNIQUE_KEY_FLAG)); + rb_define_const(cMysqlField, "MULTIPLE_KEY_FLAG", INT2NUM(MULTIPLE_KEY_FLAG)); + rb_define_const(cMysqlField, "BLOB_FLAG", INT2NUM(BLOB_FLAG)); + rb_define_const(cMysqlField, "UNSIGNED_FLAG", INT2NUM(UNSIGNED_FLAG)); + rb_define_const(cMysqlField, "ZEROFILL_FLAG", INT2NUM(ZEROFILL_FLAG)); + rb_define_const(cMysqlField, "BINARY_FLAG", INT2NUM(BINARY_FLAG)); +#ifdef ENUM_FLAG + rb_define_const(cMysqlField, "ENUM_FLAG", INT2NUM(ENUM_FLAG)); +#endif +#ifdef AUTO_INCREMENT_FLAG + rb_define_const(cMysqlField, "AUTO_INCREMENT_FLAG", INT2NUM(AUTO_INCREMENT_FLAG)); +#endif +#ifdef TIMESTAMP_FLAG + rb_define_const(cMysqlField, "TIMESTAMP_FLAG", INT2NUM(TIMESTAMP_FLAG)); +#endif +#ifdef SET_FLAG + rb_define_const(cMysqlField, "SET_FLAG", INT2NUM(SET_FLAG)); +#endif +#ifdef NUM_FLAG + rb_define_const(cMysqlField, "NUM_FLAG", INT2NUM(NUM_FLAG)); +#endif +#ifdef PART_KEY_FLAG + rb_define_const(cMysqlField, "PART_KEY_FLAG", INT2NUM(PART_KEY_FLAG)); +#endif + +#if MYSQL_VERSION_ID >= 40102 + /* Mysql::Stmt object method */ + rb_define_method(cMysqlStmt, "affected_rows", stmt_affected_rows, 0); +#if 0 + rb_define_method(cMysqlStmt, "attr_get", stmt_attr_get, 1); + rb_define_method(cMysqlStmt, "attr_set", stmt_attr_set, 2); +#endif + rb_define_method(cMysqlStmt, "bind_result", stmt_bind_result, -1); + rb_define_method(cMysqlStmt, "close", stmt_close, 0); + rb_define_method(cMysqlStmt, "data_seek", stmt_data_seek, 1); + rb_define_method(cMysqlStmt, "each", stmt_each, 0); + rb_define_method(cMysqlStmt, "execute", stmt_execute, -1); + rb_define_method(cMysqlStmt, "fetch", stmt_fetch, 0); + rb_define_method(cMysqlStmt, "field_count", stmt_field_count, 0); + rb_define_method(cMysqlStmt, "free_result", stmt_free_result, 0); + rb_define_method(cMysqlStmt, "insert_id", stmt_insert_id, 0); + rb_define_method(cMysqlStmt, "num_rows", stmt_num_rows, 0); + rb_define_method(cMysqlStmt, "param_count", stmt_param_count, 0); + rb_define_method(cMysqlStmt, "prepare", stmt_prepare, 1); +#if 0 + rb_define_method(cMysqlStmt, "reset", stmt_reset, 0); +#endif + rb_define_method(cMysqlStmt, "result_metadata", stmt_result_metadata, 0); + rb_define_method(cMysqlStmt, "row_seek", stmt_row_seek, 1); + rb_define_method(cMysqlStmt, "row_tell", stmt_row_tell, 0); +#if 0 + rb_define_method(cMysqlStmt, "send_long_data", stmt_send_long_data, 2); +#endif + rb_define_method(cMysqlStmt, "sqlstate", stmt_sqlstate, 0); + +#if 0 + rb_define_const(cMysqlStmt, "ATTR_UPDATE_MAX_LENGTH", INT2NUM(STMT_ATTR_UPDATE_MAX_LENGTH)); +#endif + + /* Mysql::Time object method */ + rb_define_method(cMysqlTime, "initialize", time_initialize, -1); + rb_define_method(cMysqlTime, "inspect", time_inspect, 0); + rb_define_method(cMysqlTime, "to_s", time_to_s, 0); + rb_define_method(cMysqlTime, "year", time_get_year, 0); + rb_define_method(cMysqlTime, "month", time_get_month, 0); + rb_define_method(cMysqlTime, "day", time_get_day, 0); + rb_define_method(cMysqlTime, "hour", time_get_hour, 0); + rb_define_method(cMysqlTime, "minute", time_get_minute, 0); + rb_define_method(cMysqlTime, "second", time_get_second, 0); + rb_define_method(cMysqlTime, "neg", time_get_neg, 0); + rb_define_method(cMysqlTime, "second_part", time_get_second_part, 0); + rb_define_method(cMysqlTime, "year=", time_set_year, 1); + rb_define_method(cMysqlTime, "month=", time_set_month, 1); + rb_define_method(cMysqlTime, "day=", time_set_day, 1); + rb_define_method(cMysqlTime, "hour=", time_set_hour, 1); + rb_define_method(cMysqlTime, "minute=", time_set_minute, 1); + rb_define_method(cMysqlTime, "second=", time_set_second, 1); + rb_define_method(cMysqlTime, "neg=", time_set_neg, 1); + rb_define_method(cMysqlTime, "second_part=", time_set_second_part, 1); + rb_define_method(cMysqlTime, "==", time_equal, 1); + +#endif + + /* Mysql::Error object method */ + rb_define_method(eMysql, "error", error_error, 0); + rb_define_method(eMysql, "errno", error_errno, 0); + rb_define_method(eMysql, "sqlstate", error_sqlstate, 0); + + /* Mysql::Error constant */ +#define rb_define_mysql_const(s) rb_define_const(eMysql, #s, INT2NUM(s)) +#include "error_const.h" +} diff --git a/mysqlplus.gemspec b/mysqlplus.gemspec new file mode 100755 index 0000000..b42d9ef --- /dev/null +++ b/mysqlplus.gemspec @@ -0,0 +1,25 @@ +Gem::Specification.new do |s| + s.name = "mysqlplus" + s.version = "0.1.0" + s.date = "2008-08-13" + s.summary = "Enhanced Ruby MySQL driver" + s.email = "oldmoe@gmail.com" + s.homepage = "http://github.com/oldmoe/mysqlplus" + s.description = "Enhanced Ruby MySQL driver" + s.has_rdoc = true + s.authors = ["Muhammad A. Ali"] + s.platform = Gem::Platform::RUBY + s.files = [ + "mysqlplus.gemspec", + "README", + "test/test_threaded.rb", + "test/test_evented.rb", + "ext/extconf.rb", + "ext/mysql.c", + "ext/Makefile" + ] + s.rdoc_options = ["--main", "README"] + s.extra_rdoc_files = ["README"] + s.extensions << "ext/extconf.rb" +end + diff --git a/test/test_evented.rb b/test/test_evented.rb new file mode 100644 index 0000000..767e872 --- /dev/null +++ b/test/test_evented.rb @@ -0,0 +1,49 @@ +require 'mysql' + +class Mysql + attr_accessor :fiber + alias :old_query :query + def query(sql) + if Fiber.current[:neverblock] + send_query(sql) + @fiber = Fiber.current + Fiber.yield + else + old_query(sql) + end + end + + def process_command + @fiber.resume get_result + end +end + +@count = 10 +@connections = {} + +@count.times do + c = Mysql.real_connect('localhost','root',nil) + @connections[IO.new(c.socket)] = c +end + +@sockets = @connections.keys + +@done = 0 +@t = Time.now +@connections.each_value do |c| + c.send_query('select sleep(1)') +end + +loop do + res = select(@sockets,nil,nil,nil) + if res + res.first.each do |c| + @connections[c].get_result.each{|r| p r} + @done = @done + 1 + if @done == @count + puts Time.now - @t + exit + end + end + end +end diff --git a/test/test_threaded.rb b/test/test_threaded.rb new file mode 100644 index 0000000..b5d2c4e --- /dev/null +++ b/test/test_threaded.rb @@ -0,0 +1,22 @@ +require 'mysql' + +$t = Time.now +$connections = [] +$count = 10 + +$count.times do + $connections << Mysql.real_connect('localhost','root') +end +$done = 0 +$t = Time.now +$count.times do |i| + Thread.new do + $connections[i].async_query('select sleep(0.1)').each{|r|puts "#{i}:#{r}"} + $done = $done + 1 + puts Time.now - $t if $done == $count + end +end + +loop do + break if $done == $count +end