├── extra ├── README_ja.html ├── tommy.css └── README.html ├── .gitignore ├── lib ├── mysql │ └── version.rb └── mysql.rb ├── Manifest.txt ├── Rakefile ├── tasks ├── gem.rake ├── vendor_mysql.rake └── native.rake ├── History.txt ├── README.md ├── COPYING.ja ├── COPYING ├── ext └── mysql_api │ ├── extconf.rb │ └── mysql.c └── test └── test_mysql.rb /extra/README_ja.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luislavena/mysql-gem/HEAD/extra/README_ja.html -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bundle 2 | *.log 3 | *.o 4 | *.so 5 | ext/Makefile 6 | ext/mysql.c 7 | pkg 8 | tmp 9 | vendor 10 | -------------------------------------------------------------------------------- /lib/mysql/version.rb: -------------------------------------------------------------------------------- 1 | # define version string to be used internally for the Gem by Hoe. 2 | class Mysql 3 | module GemVersion 4 | VERSION = '2.9.1' 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/mysql.rb: -------------------------------------------------------------------------------- 1 | # support multiple ruby version (fat binaries under windows) 2 | begin 3 | RUBY_VERSION =~ /(\d+.\d+)/ 4 | require "mysql/#{$1}/mysql_api" 5 | rescue LoadError 6 | require 'mysql/mysql_api' 7 | end 8 | 9 | require 'mysql/version' 10 | -------------------------------------------------------------------------------- /Manifest.txt: -------------------------------------------------------------------------------- 1 | COPYING 2 | COPYING.ja 3 | History.txt 4 | Manifest.txt 5 | README.md 6 | Rakefile 7 | ext/mysql_api/extconf.rb 8 | ext/mysql_api/mysql.c 9 | extra/README.html 10 | extra/README_ja.html 11 | extra/tommy.css 12 | lib/mysql.rb 13 | lib/mysql/version.rb 14 | tasks/gem.rake 15 | tasks/native.rake 16 | tasks/vendor_mysql.rake 17 | test/test_mysql.rb 18 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #-- 2 | # Copyright (c) 2008 Luis Lavena 3 | # 4 | # This source code is released under the MIT License. 5 | # See LICENSE file for details 6 | #++ 7 | 8 | # 9 | # NOTE: Keep this file clean. 10 | # Add your customizations inside tasks directory. 11 | # Thank You. 12 | # 13 | 14 | begin 15 | require 'rake' 16 | rescue LoadError 17 | require 'rubygems' 18 | require 'rake' 19 | end 20 | 21 | # load rakefile extensions (tasks) 22 | Dir['tasks/*.rake'].sort.each { |f| load f } 23 | -------------------------------------------------------------------------------- /tasks/gem.rake: -------------------------------------------------------------------------------- 1 | require 'rubygems/package_task' 2 | require 'hoe' 3 | 4 | HOE = Hoe.spec 'mysql' do 5 | self.rubyforge_name = 'mysql-win' 6 | self.author = ['TOMITA Masahiro'] 7 | self.email = %w[tommy@tmtm.org] 8 | self.need_tar = false 9 | self.need_zip = false 10 | 11 | spec_extras[:required_ruby_version] = Gem::Requirement.new('>= 1.8.7') 12 | 13 | spec_extras[:extensions] = ["ext/mysql_api/extconf.rb"] 14 | 15 | extra_dev_deps << ['rake-compiler', "~> 0.8.1"] 16 | end 17 | 18 | file "#{HOE.spec.name}.gemspec" => ['Rakefile', 'tasks/gem.rake'] do |t| 19 | puts "Generating #{t.name}" 20 | File.open(t.name, 'w') { |f| f.puts HOE.spec.to_yaml } 21 | end 22 | 23 | desc "Generate or update the standalone gemspec file for the project" 24 | task :gemspec => ["#{HOE.spec.name}.gemspec"] 25 | -------------------------------------------------------------------------------- /History.txt: -------------------------------------------------------------------------------- 1 | === 2.9.1 / 2013-02-16 / Vacation time! 2 | 3 | * Bugfixes: 4 | * Use C89 comment style in source code. #13 [knu] 5 | * Use ULL2NUM to return `affected_rows`. #11, #12 [cbandy] 6 | 7 | === 2.9.0 / 2012-11-17 8 | 9 | DEPRECATION: Ruby 1.8.6 is no longer supported. Do not update your production 10 | application blindly without testing first any dependency change! 11 | 12 | * Incompatibility: 13 | * Requires Ruby 1.8.7 or newer. 14 | 15 | * Enhancements: 16 | * Detect MySQL version at load time and fail on mismatch [ghazel] 17 | * Use MySQL Connector/C for Windows binary bindings instead 18 | 19 | * Bug fixes: 20 | * Use RbConfig since Config is deprecated in Ruby 2.0 [tenderlove] 21 | 22 | === 2.8.2 / 2012-11-06 / *yanked* 23 | 24 | * Yanked: 25 | * Changes in requirements render this gem incompatible for some users. 26 | 27 | === 2.8.1 / 2009-08-21 28 | 29 | * New features: 30 | * Early support for Ruby 1.9 31 | 32 | * Enhancements: 33 | * Improved gem release process using Hoe as development dependency 34 | * Implemented support for cross compilation 35 | * Binary version built against MySQL 5.0.83 36 | 37 | * Bug fixes: 38 | * Improved detection of mysql and it's configuration (mysql_config) 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MySQL/Ruby Interface 2 | 3 | * http://github.com/luislavena/mysql-gem 4 | 5 | ## Maintainer needed 6 | 7 | As January 1st, 2015, this project has become unmaintained: 8 | 9 | https://groups.google.com/d/topic/rubyinstaller/nzpIDZqXO-Q/discussion 10 | 11 | If you want to take over maintenance of this project, please 12 | [open an issue](issues) stating your intention and we can coordinate the 13 | entire process there. 14 | 15 | Thank you. 16 | 17 | ## DESCRIPTION 18 | 19 | This is the MySQL API module for Ruby. It provides the same functions for Ruby 20 | programs that the MySQL C API provides for C programs. 21 | 22 | This package is offered as gem for easy installation using RubyGems. It wraps 23 | unmodified tmtm's mysql-ruby extension into a proper gem. 24 | 25 | Please note that tmtm (Tomita Mashahiro) has deprecated development of this 26 | extension and only update it for bug fixes. 27 | 28 | ### Warning about incompatible MySQL versions under Windows 29 | 30 | Mixing MySQL versions will generate segmentation faults. 31 | 32 | Running the binary version of this gem against a different version of MySQL 33 | shared library libMySQL.dll will generate segmentation faults and 34 | terminate your application. 35 | 36 | Please use the exact same MAJOR.MINOR version of MySQL, see History.txt for 37 | specific version of MySQL used to build the binaries. 38 | -------------------------------------------------------------------------------- /tasks/vendor_mysql.rake: -------------------------------------------------------------------------------- 1 | require 'rake/clean' 2 | require 'rake/extensioncompiler' 3 | 4 | # download mysql library and headers 5 | directory "vendor" 6 | 7 | CONNECTOR_DIR = "mysql-connector-c-noinstall-#{CONNECTOR_VERSION}-win32" 8 | CONNECTOR_ZIP = "#{CONNECTOR_DIR}.zip" 9 | 10 | file "vendor/#{CONNECTOR_ZIP}" => ['vendor'] do |t| 11 | url = "http://dev.mysql.com/get/Downloads/Connector-C/#{File.basename(t.name)}/from/#{CONNECTOR_MIRROR}/" 12 | when_writing "downloading #{t.name}" do 13 | sh "curl -L #{url} -o #{t.name}" 14 | end 15 | end 16 | 17 | file "vendor/#{CONNECTOR_DIR}/include/mysql.h" => ["vendor/#{CONNECTOR_ZIP}"] do |t| 18 | full_file = File.expand_path(t.prerequisites.last) 19 | when_writing "creating #{t.name}" do 20 | cd "vendor" do 21 | sh "unzip #{full_file} #{CONNECTOR_DIR}/bin/** #{CONNECTOR_DIR}/include/** #{CONNECTOR_DIR}/lib/**" 22 | end 23 | # update file timestamp to avoid Rake perform this extraction again. 24 | touch t.name 25 | end 26 | end 27 | 28 | # clobber expanded packages 29 | CLOBBER.include("vendor/#{CONNECTOR_ZIP}") 30 | CLOBBER.include("vendor/#{CONNECTOR_DIR}") 31 | 32 | # vendor:mysql 33 | task 'vendor:mysql' => ["vendor/#{CONNECTOR_DIR}/include/mysql.h"] 34 | 35 | # hook into cross compilation vendored mysql dependency 36 | if RUBY_PLATFORM =~ /mingw|mswin/ then 37 | Rake::Task['compile'].prerequisites.unshift 'vendor:mysql' 38 | else 39 | if Rake::Task.tasks.map {|t| t.name }.include? 'cross' 40 | Rake::Task['cross'].prerequisites.unshift 'vendor:mysql' 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /extra/tommy.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: black; 3 | background: white; 4 | margin-left: 10%; 5 | margin-right: 10%; 6 | } 7 | 8 | h1 { 9 | color: white; 10 | background: #08d; 11 | width: 100%; 12 | } 13 | 14 | h1 a { 15 | color: white; 16 | } 17 | 18 | h1 a:link { 19 | } 20 | 21 | h1 a:visited { 22 | color: white; 23 | } 24 | 25 | h1 a:hover { 26 | } 27 | 28 | h2 { 29 | width: 100%; 30 | border: thin #0cc; 31 | border-style: solid none; 32 | background: #cff; 33 | } 34 | 35 | h3 { 36 | width: 100%; 37 | border: thin #0cc; 38 | border-style: none none solid; 39 | background: #eff; 40 | } 41 | 42 | h4 { 43 | border: thin #0cc; 44 | border-style: none none solid; 45 | } 46 | 47 | dt { 48 | font-weight: bold; 49 | } 50 | 51 | dd { 52 | margin-bottom: 3ex; 53 | } 54 | 55 | table { 56 | border-collapse: collapse; 57 | border: thin solid; 58 | } 59 | 60 | tr,th,td { 61 | border: thin solid; 62 | padding: 3px; 63 | } 64 | 65 | th { 66 | background-color: #00ffff; 67 | } 68 | 69 | td { 70 | background-color: #eeeeee; 71 | } 72 | 73 | div.intro { 74 | margin-right: 10%; 75 | margin-left: 10%; 76 | font-size: 90%; 77 | } 78 | 79 | div.code { 80 | margin-left: 10%; 81 | color: white; 82 | background: black; 83 | border: thin inset; 84 | padding: 4px; 85 | } 86 | 87 | div.code2 { 88 | margin-left: 10%; 89 | color: white; 90 | background: darkgreen; 91 | border: thin inset; 92 | padding: 4px; 93 | } 94 | 95 | pre { 96 | margin: 20px; 97 | padding: 4px; 98 | border: #363 inset; 99 | color: #fff; 100 | background: #232; 101 | width: 80%; 102 | } 103 | 104 | 105 | /* 106 | a { 107 | background: #eee; 108 | } 109 | */ 110 | 111 | a:link { 112 | color: #008; 113 | } 114 | 115 | a:visited { 116 | color: black; 117 | } 118 | 119 | a:hover { 120 | background: #fcc; 121 | } 122 | 123 | .red { 124 | color: red; 125 | } 126 | 127 | .notice { 128 | font-weight: bold; 129 | background: #f88; 130 | } 131 | 132 | .input { 133 | font-weight:bold; 134 | } -------------------------------------------------------------------------------- /tasks/native.rake: -------------------------------------------------------------------------------- 1 | # use rake-compiler for building the extension 2 | require 'rake/extensiontask' 3 | 4 | CONNECTOR_VERSION = "6.0.2" 5 | CONNECTOR_MIRROR = ENV['CONNECTOR_MIRROR'] || "http://mysql.localhost.net.ar" 6 | 7 | Rake::ExtensionTask.new('mysql_api', HOE.spec) do |ext| 8 | # reference where the vendored MySQL got extracted 9 | mysql_lib = File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', "mysql-connector-c-noinstall-#{CONNECTOR_VERSION}-win32")) 10 | 11 | # where native extension will be copied (matches makefile) 12 | ext.lib_dir = "lib/mysql" 13 | 14 | # define target for extension (supporting fat binaries) 15 | if RUBY_PLATFORM =~ /mswin|mingw/ then 16 | ruby_ver = RUBY_VERSION.match(/(\d+\.\d+)/)[1] 17 | ext.lib_dir = "lib/mysql/#{ruby_ver}" 18 | end 19 | 20 | # automatically add build options to avoid need of manual input 21 | if RUBY_PLATFORM =~ /mswin|mingw/ then 22 | ext.config_options << "--with-mysql-dir=#{mysql_lib}" 23 | else 24 | ext.cross_compile = true 25 | ext.cross_platform = ['i386-mingw32', 'i386-mswin32-60'] 26 | ext.cross_config_options << "--with-mysql-dir=#{mysql_lib}" 27 | ext.cross_compiling do |gemspec| 28 | gemspec.post_install_message = <<-POST_INSTALL_MESSAGE 29 | 30 | ====================================================================================================== 31 | 32 | You've installed the binary version of #{gemspec.name}. 33 | It was built using MySQL Connector/C version #{CONNECTOR_VERSION}. 34 | It's recommended to use the exact same version to avoid potential issues. 35 | 36 | At the time of building this gem, the necessary DLL files where available 37 | in the following URL: 38 | 39 | http://dev.mysql.com/get/Downloads/Connector-C/mysql-connector-c-noinstall-#{CONNECTOR_VERSION}-win32.zip/from/pick 40 | 41 | You can put the lib\\libmysql.dll available in this package to your Ruby bin directory. 42 | E.g. C:\\Ruby\\bin 43 | 44 | ====================================================================================================== 45 | 46 | POST_INSTALL_MESSAGE 47 | end 48 | end 49 | end 50 | 51 | # ensure things are compiled prior testing 52 | task :test => [:compile] 53 | -------------------------------------------------------------------------------- /COPYING.ja: -------------------------------------------------------------------------------- 1 | $BK\%W%m%0%i%`$O%U%j!<%=%U%H%&%'%"$G$9!%(BGPL(the GNU General 2 | Public License)$B$^$?$O0J2<$K<($9>r7o$GK\%W%m%0%i%`$r:FG[I[$G(B 3 | $B$-$^$9!%(BGPL$B$K$D$$$F$O(BGPL$B%U%!%$%k$r;2>H$7$F2<$5$$!%(B 4 | 5 | 1. $BJ#@=$O@)8B$J$/<+M3$G$9!%(B 6 | 7 | 2. $B0J2<$N>r7o$N$$$:$l$+$rK~$?$9;~$KK\%W%m%0%i%`$N%=!<%9$r(B 8 | $B<+M3$KJQ99$G$-$^$9!%(B 9 | 10 | (a) $B%M%C%H%K%e!<%:$K%]%9%H$7$?$j!$:nA0$rJQ99$9$k!%(B 17 | $B$=$N%=%U%H%&%'%"$rG[I[$9$k;~$K$OJQ99A0$NK\%W%m%0%i(B 18 | $B%`$bF1;~$KG[I[$9$k!%$^$?$OJQ99A0$NK\%W%m%0%i%`$N%=!<(B 19 | $B%9$NF~$NJQ99>r7o$r:nr7o$N$$$:$l$+$rK~$?$9;~$KK\%W%m%0%i%`$r%3%s%Q%$(B 24 | $B%k$7$?%*%V%8%'%/%H%3!<%I$dA0$rJQ99$7$?$&$(!$%*%j%8%J(B 32 | $B%k$N%=!<%9%3!<%I$NF~$NG[I[>r7o$r:n$N%W%m%0%i%`$X$N0zMQ$O$$$+$J$kL\E*$G$"$l<+M3$G$9!%$?(B 37 | $B$@$7!$K\%W%m%0%i%`$K4^$^$l$kB>$N:n$l$N:nl9g$,$"$j$^$9!%(B 39 | 40 | $B$=$l$i%U%!%$%k$N0lMw$H$=$l$>$l$NG[I[>r7o$J$I$KIU$$$F$O(B 41 | LEGAL$B%U%!%$%k$r;2>H$7$F$/$@$5$$!%(B 42 | 43 | 5. $BK\%W%m%0%i%`$X$NF~NO$H$J$k%9%/%j%W%H$*$h$S!$K\%W%m%0%i(B 44 | $B%`$+$i$N=PNO$N8"Mx$OK\%W%m%0%i%`$N:n(B 45 | $B$l$NF~=PNO$r@8@.$7$??M$KB0$7$^$9!%$^$?!$K\%W%m%0%i%`$K(B 46 | $BAH$_9~$^$l$k$?$a$N3HD%%i%$%V%i%j$K$D$$$F$bF1MM$G$9!%(B 47 | 48 | 6. $BK\%W%m%0%i%`$OL5J]>Z$G$9!%:n. 2 | You can redistribute it and/or modify it under either the terms of the GPL 3 | (see the file GPL), or the conditions below: 4 | 5 | 1. You may make and give away verbatim copies of the source form of the 6 | software without restriction, provided that you duplicate all of the 7 | original copyright notices and associated disclaimers. 8 | 9 | 2. You may modify your copy of the software in any way, provided that 10 | you do at least ONE of the following: 11 | 12 | a) place your modifications in the Public Domain or otherwise 13 | make them Freely Available, such as by posting said 14 | modifications to Usenet or an equivalent medium, or by allowing 15 | the author to include your modifications in the software. 16 | 17 | b) use the modified software only within your corporation or 18 | organization. 19 | 20 | c) give non-standard binaries non-standard names, with 21 | instructions on where to get the original software distribution. 22 | 23 | d) make other distribution arrangements with the author. 24 | 25 | 3. You may distribute the software in object code or binary form, 26 | provided that you do at least ONE of the following: 27 | 28 | a) distribute the binaries and library files of the software, 29 | together with instructions (in the manual page or equivalent) 30 | on where to get the original distribution. 31 | 32 | b) accompany the distribution with the machine-readable source of 33 | the software. 34 | 35 | c) give non-standard binaries non-standard names, with 36 | instructions on where to get the original software distribution. 37 | 38 | d) make other distribution arrangements with the author. 39 | 40 | 4. You may modify and include the part of the software into any other 41 | software (possibly commercial). But some files in the distribution 42 | are not written by the author, so that they are not under these terms. 43 | 44 | For the list of those files and their copying conditions, see the 45 | file LEGAL. 46 | 47 | 5. The scripts and library files supplied as input to or produced as 48 | output from the software do not automatically fall under the 49 | copyright of the software, but belong to whomever generated them, 50 | and may be sold commercially, and may be aggregated with this 51 | software. 52 | 53 | 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR 54 | IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 55 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 | PURPOSE. 57 | -------------------------------------------------------------------------------- /ext/mysql_api/extconf.rb: -------------------------------------------------------------------------------- 1 | # Darwin (OSX) special cases for universal binaries 2 | # This is to avoid the lack of UB binaries for MySQL 3 | ENV["RC_ARCHS"] = "" if RUBY_PLATFORM =~ /darwin/ 4 | 5 | require 'mkmf' 6 | 7 | # Improved detection of mysql_config 8 | # Code from DataObjects do_mysql adapter 9 | 10 | # All instances of mysql_config on PATH ... 11 | def mysql_config_paths 12 | ENV['PATH'].split(File::PATH_SEPARATOR).collect do |path| 13 | [ "#{path}/mysql_config", "#{path}/mysql_config5" ]. 14 | detect { |bin| File.exist?(bin) } 15 | end 16 | end 17 | 18 | # The first mysql_config binary on PATH ... 19 | def default_mysql_config_path 20 | mysql_config_paths.compact.first 21 | end 22 | 23 | # Allow overriding path to mysql_config on command line using: 24 | # ruby extconf.rb --with-mysql-config=/path/to/mysql_config 25 | if RUBY_PLATFORM =~ /mswin|mingw/ 26 | inc, lib = dir_config('mysql') 27 | exit 1 unless have_library("libmysql") 28 | elsif mc = with_config('mysql-config', default_mysql_config_path) then 29 | mc = 'mysql_config' if mc == true 30 | cflags = `#{mc} --cflags`.chomp 31 | exit 1 if $? != 0 32 | libs = `#{mc} --libs`.chomp 33 | exit 1 if $? != 0 34 | $CPPFLAGS += ' ' + cflags 35 | $libs = libs + " " + $libs 36 | else 37 | inc, lib = dir_config('mysql', '/usr/local') 38 | libs = ['m', 'z', 'socket', 'nsl', 'mygcc'] 39 | while not find_library('mysqlclient', 'mysql_query', lib, "#{lib}/mysql") do 40 | exit 1 if libs.empty? 41 | have_library(libs.shift) 42 | end 43 | end 44 | 45 | have_func('mysql_ssl_set') 46 | have_func('rb_str_set_len') 47 | have_func('rb_thread_start_timer') 48 | 49 | if have_header('mysql.h') then 50 | src = "#include \n#include \n" 51 | elsif have_header('mysql/mysql.h') then 52 | src = "#include \n#include \n" 53 | else 54 | exit 1 55 | end 56 | 57 | # make mysql constant 58 | File.open("conftest.c", "w") do |f| 59 | f.puts src 60 | end 61 | if defined? cpp_command then 62 | cpp = RbConfig.expand(cpp_command('')) 63 | else 64 | cpp = RbConfig.expand sprintf(CPP, $CPPFLAGS, $CFLAGS, '') 65 | end 66 | if RUBY_PLATFORM =~ /mswin/ && !/-E/.match(cpp) 67 | cpp << " -E" 68 | end 69 | unless system "#{cpp} > confout" then 70 | exit 1 71 | end 72 | File.unlink "conftest.c" 73 | 74 | error_syms = [] 75 | IO.foreach('confout') do |l| 76 | next unless l =~ /errmsg\.h|mysqld_error\.h/ 77 | fn = l.split(/\"/)[1] 78 | IO.foreach(fn) do |m| 79 | if m =~ /^#define\s+([CE]R_[0-9A-Z_]+)/ then 80 | error_syms << $1 81 | end 82 | end 83 | end 84 | File.unlink 'confout' 85 | error_syms.uniq! 86 | 87 | File.open('error_const.h', 'w') do |f| 88 | error_syms.each do |s| 89 | f.puts " rb_define_mysql_const(#{s});" 90 | end 91 | end 92 | 93 | create_makefile("mysql/mysql_api") 94 | -------------------------------------------------------------------------------- /extra/README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MySQL/Ruby 9 | 10 | 11 | 12 |

MySQL/Ruby

13 |

[Japanese]

14 |
15 |

16 | This is the MySQL API module for Ruby. 17 | It provides the same functions for Ruby programs that the MySQL C API provides for C programs. 18 |

19 | 20 |

Download

21 | 25 | 26 |

Requirement

27 |
    28 |
  • MySQL 5.0.67 29 |
  • Ruby 1.8.7, 1.9.1 30 |
31 |

32 | The module may work for other versions, but that has not been verified. 33 |

34 | 35 |

License

36 |

37 | This program is under Ruby's license. 38 |

39 | 40 |

Install

41 |

42 | 1st: 43 |

44 |
  45 | % ruby extconf.rb
  46 | 
47 |

48 | or 49 |

50 |
  51 | % ruby extconf.rb --with-mysql-dir=/usr/local/mysql
  52 | 
53 |

54 | or 55 |

56 |
  57 | % ruby extconf.rb --with-mysql-config
  58 | 
59 |

60 | then 61 |

62 |
  63 | % make
  64 | 
65 |

66 | extconf.rb has following options: 67 |

68 |
69 |
--with-mysql-include=dir 70 |
71 | MySQL header file directory. Default is /usr/local/include. 72 | 73 |
--with-mysql-lib=dir 74 |
75 | MySQL library directory. Default is /usr/local/lib. 76 | 77 |
--with-mysql-dir=dir 78 |
79 | Same as --with-mysql-include=dir/include, 80 | --with-mysql-lib=dir/lib. 81 | 82 |
--with-mysql-config[=/path/to/mysql_config] 83 |
84 | Get compile-parameter from mysql_config command. 85 |
86 |

87 | 2nd: 88 |

89 |
  90 | % ruby ./test.rb -- [hostname [user [passwd [dbname [port [socket [flag]]]]]]]
  91 | 
92 | 93 |

94 | 3rd: 95 |

96 |
  97 | # make install
  98 | 
99 | 100 |

Note

101 |

102 | If you get error like 'libmysqlclient not found' when testing, 103 | you need to specify the directory in which the library is 104 | located so that make can find it. 105 |

106 |
 107 | % env LD_RUN_PATH=libmysqlclient.so directory make
 108 | 
109 |

110 | test.rb is tested on Linux only. 111 |

112 | 113 |

Usage

114 |

115 | The names of methods provided by this module basically are the 116 | same as the names of the functions in the C API, except that the 117 | Ruby method names do not begin with a 'mysql_' prefix. For 118 | example, the Ruby query() method corresponds to the C API 119 | mysql_query() function. For details on the use of each Ruby 120 | method, see the descriptions of the corresponding C functions in 121 | the MySQL Reference Manual. 122 |

123 |

124 | Some Ruby methods may be invoked under other names that serve as 125 | equivalent aliases, as noted below. 126 |

127 |

128 | If an error occurs when a method executes, it raises a 129 | Mysql::Error exception. 130 |

131 | 132 |

Mysql class

133 |

CLASS METHODS

134 |
135 |
init() 136 |
137 |

138 | It return Mysql object. It not connect to mysqld. 139 |

140 | 141 |
real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) 142 |
connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) 143 |
new(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) 144 |
145 |

146 | connect to mysqld and return Mysql object. 147 |

148 | 149 |
escape_string(str) 150 |
quote(str) 151 |
152 |

153 | quote string for insert/update. 154 |

155 | 156 |
get_client_info() 157 |
client_info() 158 |
159 |

160 | return client version information. 161 |

162 | 163 |
get_client_version() 164 |
client_version() 165 |
166 |

167 | return client version as number. 168 |

169 | 170 |
debug(str) 171 |
172 |

173 | same as C API mysql_debug(). 174 |

175 |
176 | 177 |

OBJECT METHODS

178 |
179 |
options(opt, val=nil) 180 |
181 |

182 | same as C API mysql_options(). 183 |

184 | 185 |
real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) 186 |
connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) 187 |
188 |

189 | same as Mysql.real_connect(). 190 |

191 | 192 |
affected_rows() 193 |
194 |

195 | return affected rows. 196 |

197 | 198 |
autocommit(mode) 199 |
200 |

201 | set autocommit mode. 202 |

203 | 204 |
change_user(user=nil, passwd=nil, db=nil) 205 |
206 |

207 | change user. 208 |

209 | 210 |
character_set_name() 211 |
212 |

213 | return character set. 214 |

215 | 216 |
close() 217 |
218 |

219 | close connection. 220 |

221 | 222 |
commit() 223 |
224 |

225 | commit transaction. 226 |

227 | 228 |
create_db(db) 229 |
230 |

231 | create database. 232 |

233 | 234 |
drop_db(db) 235 |
236 |

237 | drop database. 238 |

239 | 240 |
dump_debug_info() 241 |
242 |

243 | same as C API mysql_dump_debug_info(). 244 |

245 | 246 |
errno() 247 |
248 |

249 | return error number. 250 |

251 | 252 |
error() 253 |
254 |

255 | return error message. 256 |

257 | 258 |
escape_string(str) 259 |
quote(str) 260 |
261 |

262 | quote strings for insert/update. 263 | same as C API mysql_real_escape_string(). 264 |

265 | 266 |
field_count() 267 |
268 |

269 | return number of columns of last query. 270 |

271 | 272 |
get_client_info() 273 |
client_info() 274 |
275 |

276 | return client version information. 277 |

278 | 279 |
get_client_version() 280 |
client_version() 281 |
282 |

283 | return client version number. 284 |

285 | 286 |
get_host_info() 287 |
host_info() 288 |
289 |

290 | return connection information. 291 |

292 | 293 |
get_proto_info() 294 |
proto_info() 295 |
296 |

297 | return connection protocol version. 298 |

299 | 300 |
get_server_info() 301 |
server_info() 302 |
303 |

304 | return server version information. 305 |

306 | 307 |
get_server_version() 308 |
server_version() 309 |
310 |

311 | return server version number. 312 |

313 | 314 |
info() 315 |
316 |

317 | return information of last query. 318 |

319 | 320 |
insert_id() 321 |
322 |

323 | return last AUTO_INCREMENT value. 324 |

325 | 326 |
kill(id) 327 |
328 |

329 | kill thread. 330 |

331 | 332 |
list_dbs(db=nil) 333 |
334 |

335 | return database list. 336 |

337 | 338 |
list_fields(table, field=nil) 339 |
340 |

341 | return Mysql::Result object. 342 |

343 | 344 |
list_processes() 345 |
346 |

347 | return Mysql::Result object. 348 |

349 | 350 |
list_tables(table=nil) 351 |
352 |

353 | return table list Array. 354 |

355 | 356 |
more_results?() 357 |
358 |

359 | returns true if more results exist from the currently executed query. 360 |

361 | 362 |
next_result() 363 |
364 |

365 | returns true if more results exist from the currently executed query. 366 | after this, you do store_result() to get result table of query. 367 |

368 | 369 |
ping() 370 |
371 |

372 | check server. 373 |

374 | 375 |
prepare(q) 376 |
377 |

378 |

379 | 380 |
query(q) 381 |
real_query(q) 382 |
383 |

384 | do query and store_result(). return Mysql::Result object. 385 | If query_with_result is false, it does not store_result(). 386 |

387 | 388 |
query(q) {|res| ...} 389 |
real_query(q) {|res| ...} 390 |
391 |

392 | do query and execute block with Mysql::Result object. 393 | Mysql::Result object is freed when exiting block. 394 | If multiple statement mode, it does repeat block each query. 395 |

396 |

397 | Since MySQL/Ruby 2.8, it no longer turn on multiple statement mode automatically. 398 | If you want to turn on multiple statement mode, set Mysql::CLIENT_MULTI_STATEMENTS for Mysql.connect or execute Mysql#set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON). 399 |

400 | 401 |
refresh(r) 402 |
403 |

404 | flush server log or cache. 405 |

406 | 407 |
reload() 408 |
409 |

410 | reload access privilege table. 411 |

412 | 413 |
rollback() 414 |
415 |

416 | rollback transaction. 417 |

418 | 419 |
select_db(db) 420 |
421 |

422 | select database. 423 |

424 | 425 |
set_server_option(opt) 426 |
427 |

428 | set option to server. 429 | options is one of Mysql::OPTION_MULTI_STATEMENTS_ON, Mysql::OPTION_MULTI_STATEMENTS_OFF. 430 |

431 | 432 |
shutdown() 433 |
434 |

435 | shutdown server. 436 |

437 | 438 |
ssl_set(key=nil, cert=nil, ca=nil, capath=nil, cipher=nil) 439 |
440 |

441 | use SSL. 442 |

443 | 444 |
stat() 445 |
446 |

447 | return server status. 448 |

449 | 450 |
stmt_init() 451 |
452 |

453 | return Mysql::Stmt class object. 454 |

455 | 456 |
store_result() 457 |
458 |

459 | return Mysql::Result object. 460 |

461 | 462 |
thread_id() 463 |
464 |

465 | retrun thread id. 466 |

467 | 468 |
use_result() 469 |
470 |

471 | return Mysql::Result object. 472 |

473 | 474 |
warning_count() 475 |
476 |

477 | return warning count last query. 478 |

479 |
480 | 481 |

OBJECT VARIABLES

482 | 483 |
484 |
query_with_result 485 |
486 |

487 | If true, query() also invokes store_result() and returns a 488 | Mysql::Result object. Default is true. 489 |

490 | 491 |
reconnect 492 |
493 |

494 | If true, reconnect to server automatically when disconect to server. 495 | Default is false. 496 |

497 | 498 |
499 | 500 |

Mysql::Result class

501 | 502 |

OBJECT METHODS

503 |
504 |
free() 505 |
506 |

507 | free memory of result table. 508 |

509 | 510 |
data_seek(offset) 511 |
512 |

513 | seek row. 514 |

515 | 516 |
fetch_field() 517 |
518 |

519 | return next Mysql::Field object. 520 |

521 | 522 |
fetch_fields() 523 |
524 |

525 | return Array of Mysql::Field object. 526 |

527 | 528 |
fetch_field_direct(fieldnr) 529 |
530 |

531 | return Mysql::Field object. 532 |

533 | 534 |
fetch_lengths() 535 |
536 |

537 | return Array of field length. 538 |

539 | 540 |
fetch_row() 541 |
542 |

543 | return row as Array. 544 |

545 | 546 |
fetch_hash(with_table=false) 547 |
548 |

549 | return row as Hash. 550 | If with_table is true, hash key format is "tablename.fieldname". 551 |

552 | 553 |
field_seek(offset) 554 |
555 |

556 | seek field. 557 |

558 | 559 |
field_tell() 560 |
561 |

562 | return field position. 563 |

564 | 565 |
num_fields() 566 |
567 |

568 | return number of fields. 569 |

570 | 571 |
num_rows() 572 |
573 |

574 | return number of rows. 575 |

576 | 577 |
row_seek(offset) 578 |
579 |

580 | seek row. 581 |

582 | 583 |
row_tell() 584 |
585 |

586 | return row position. 587 |

588 |
589 | 590 |

ITERATOR

591 |
592 |
each() {|x| ...} 593 |
594 |

595 | 'x' is array of column values. 596 |

597 | 598 |
each_hash(with_table=false) {|x| ...} 599 |
600 |

601 | 'x' is hash of column values, and the keys are the column names. 602 |

603 |
604 | 605 |

Mysql::Field class

606 | 607 |

OBJECT VARIABLES(read only)

608 |
609 |
name
field name 610 |
table
table name 611 |
def
default value 612 |
type
field type 613 |
length
field length 614 |
max_length
max field length 615 |
flags
field flag 616 |
decimals
number of decimals 617 |
618 | 619 |

OBJECT METHODS

620 |
621 |
hash() 622 |
623 |

624 | return field as Hash. 625 |

626 |

627 | ex.) obj.name == obj.hash['name'] 628 |

629 | 630 |
is_not_null?() 631 |
632 |

633 | True if this field is defined as NOT NULL. 634 |

635 | 636 |
is_num?() 637 |
638 |

639 | True if this field type is numeric. 640 |

641 | 642 |
is_pri_key?() 643 |
644 |

645 | True if this field is a primary key. 646 |

647 | 648 |
inspect() 649 |
650 |

651 | return "#<Mysql::Field:fieldname>" 652 |

653 |
654 | 655 |

Mysql::Stmt class

656 |

657 | Example: 658 |

659 |
 660 | my = Mysql.new(hostname, username, password, databasename)
 661 | st = my.prepare("insert into tblname (col1,col2,col3) values (?,?,?)")
 662 | st.execute("abc",123,Time.now)
 663 | st.prepare("select col1,col2,col3 from tblname")
 664 | st.execute
 665 | st.fetch  # => ["abc", 123, #<Mysql::Time:2005-07-24 23:52:55>]
 666 | st.close
 667 | 
668 | 669 |

OBJECT METHODS

670 |
671 |
affected_rows() 672 |
673 |

674 |

675 | 676 |
bind_result(class, ...) 677 |
678 |

679 |

680 | 681 |
close() 682 |
683 |

684 |

685 | 686 |
data_seek(offset) 687 |
688 |

689 |

690 | 691 |
execute(arg, ...) 692 |
693 |

694 |

695 | 696 |
fetch() 697 |
698 |

699 |

700 |

701 | Type mapping: 702 |

703 | 704 |
MySQL typeRuby class 705 |
TINYINT, SMALLINT, MEDIUMINT, YEARFixnum 706 |
INT, BIGINTFixnum or Bignum 707 |
FLOAT, DOUBLEFloat 708 |
DECIMALString 709 |
DATE, DATETIME, TIMESTAMP, TIMEMysql::Time 710 |
CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, TINYTEXT, TINYBLOB, TINYTEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB, LONGTEXT, ENUM, SET, BITString 711 |
NULLNilClass 712 |
713 | 714 |
field_count() 715 |
716 |

717 |

718 | 719 |
free_result() 720 |
721 |

722 |

723 | 724 |
insert_id() 725 |
726 |

727 |

728 | 729 |
num_rows() 730 |
731 |

732 |

733 | 734 |
param_count() 735 |
736 |

737 |

738 | 739 |
prepare(q) 740 |
741 |

742 |

743 | 744 |
result_metadata() 745 |
746 |

747 |

748 | 749 |
row_seek(offset) 750 |
751 |

752 |

753 | 754 |
row_tell() 755 |
756 |

757 |

758 | 759 |
sqlstate() 760 |
761 |

762 |

763 |
764 | 765 |

ITERATOR

766 |
767 |
each() {|x| ...} 768 |
769 |

770 |

771 |
772 | 773 |

Mysql::Time class

774 |

775 |

776 | 777 |

CLASS METHODS

778 |
779 |
new(year=0,month=0,day=0,hour=0,minute=0,second=0,neg=false,second_part=0) 780 |
781 |

782 |

783 |
784 | 785 |

OBJECT VARIABLES

786 |
787 |
year 788 |
789 | 790 |
month 791 |
792 | 793 |
day 794 |
795 | 796 |
hour 797 |
798 | 799 |
minute 800 |
801 | 802 |
second 803 |
804 | 805 |
neg 806 |
807 | 808 |
second_part 809 |
810 |
811 | 812 |

Mysql::Error class

813 | 814 |

OBJECT VARIABLES(read only)

815 |
816 |
error 817 |
eror message 818 |
errno 819 |
error number 820 |
821 | 822 |

History

823 |
824 |
2010-02-11
825 |
826 | version 2.8.2
827 |
    828 |
  • Fix: Mysql#insert_id returns invalid value when larger than 2**32. 829 |
830 | 831 |
2009-02-01 832 |
833 | version 2.8.1
834 |
    835 |
  • correspond to Ruby 1.9.1 836 |
837 | 838 |
2008-09-29 839 |
840 | version 2.8
841 | version 2.7.7 842 |
    843 |
  • When connecting to MySQL, EINTR is occurred sometimes ([ruby-dev:31842]) 844 |
  • MySQL/Ruby 2.7.* can not be compiled on Ruby 1.8.5. 845 |
846 | 847 |
2008-06-20 848 |
849 | version 2.8pre4
850 |
    851 |
  • [ruby-dev:35152] 852 |
853 | 854 |
2008-06-17 855 |
856 | version 2.8pre3
857 | version 2.7.6 858 |
    859 |
  • On 64bit machine, Mysql::Stmt#execute raise error on large numeric value(>= 2**30). 860 |
861 | 862 |
2008-03-08 863 |
864 | version 2.8pre2
865 | version 2.7.5 866 |
    867 |
  • On 64bit machine, Mysql::Stmt#fetch return invalid numeric value. 868 |
869 | 870 |
2007-12-26 871 |
872 | version 2.8pre1 873 |
    874 |
  • for Ruby 1.9.0 875 |
  • Incompat: Mysql::Result#each_hash don't create column name string each row. it's shared. 876 |
  • Incompat: Mysql#query with block no longer turn on multi-statements mode automatically. 877 |
878 | 879 |
2007-08-22 880 |
881 | version 2.7.4 882 |
    883 |
  • BUG: Mysql::Stmt#execute memory leak. 884 |
885 | 886 |
2006-12-20 887 |
888 | version 2.7.3 889 |
    890 |
  • BUG: Mysql#query with block is stopped when last query failed. 891 |
892 | 893 |
2006-10-28 894 |
895 | version 2.7.2 896 |
    897 |
  • BUG: Mysql::Stmt#result_metadata don't return nil. (Thanks to Hidetoshi) 898 |
  • BUG: Mysql#close check mysql_errno. 899 |
  • BUG: multistatement Mysql#query with block ignore error. 900 |
  • extconf.rb for Visual C++. (Thanks to Shugo Maeda) 901 |
  • support MySQL BIT type. 902 |
  • add Mysql::Field::TYPE_BIT, TYPE_NEWDECIMAL. 903 |
904 | 905 |
2006-06-04 906 |
907 | version 2.7.1 908 |
    909 |
  • change free() to xfree(). To avoid crash on Windows. (Thanks Tobias Grimm) 910 |
911 | 912 |
2005-08-22 913 |
914 | version 2.7 915 |
    916 |
  • add constants for Mysql#options: Mysql::OPT_GUESS_CONNECTION, Mysql::OPT_USE_EMBEDDED_CONNECTION, Mysql::OPT_USE_REMOTE_CONNECTION, Mysql::SET_CLIENT_IP 917 |
  • test.rb: for 4.0.x, 5.0.x 918 |
919 | 920 |
2005-08-16 921 |
922 | version 2.7-beta3 923 |
    924 |
  • add Mysql::Stmt#bind_result 925 |
926 | 927 |
2005-08-02 928 |
929 | version 2.7-beta2 930 |
    931 |
  • BUG: mysql.c.in: fetch_hash: nil value doesn't exist in hash. (Thanks Stefan Kaes) 932 |
  • add constant Mysql::VERSION. 933 |
  • add Mysql#prepare 934 |
935 | 936 |
2005-07-24 937 |
938 | version 2.7-beta 939 |
    940 |
  • add Mysql#stmt_init method 941 |
  • add Mysql::Stmt, Mysql::Time, Mysql::RowOffset class 942 |
  • add Mysql::Error#sqlstate method 943 |
  • change offset value to Mysql::RowOffset object that is used by Mysql::Result#row_seek,row_tell 944 |
945 | 946 |
2005-07-31 947 |
948 | version 2.6.3 949 |
    950 |
  • add constant Mysql::VERSION. 951 |
952 | 953 |
2005-07-26 954 |
955 | version 2.6.2 956 |
    957 |
  • BUG: mysql.c.in: fetch_hash: nil value doesn't exist in hash. (Thanks Stefan Kaes) 958 |
959 | 960 |
2005-06-28 961 |
962 | version 2.6.1 963 |
    964 |
  • mysql.c.in: fix to compile error on MacOSX. 965 |
966 | 967 |
2005-04-25 968 |
969 | version 2.6 970 |
    971 |
  • add constants for Mysql#option(): 972 | Mysql::OPT_PROTOCOL, Mysql::OPT_READ_TIMEOUT, 973 | Mysql::OPT_WRITE_TIMEOUT, Mysql::SET_CHARSET_DIR, 974 | Mysql::SET_CHARSET_NAME, Mysql::SHARED_MEMORY_BASE_NAME, 975 | Mysql::SECURE_AUTH 976 |
  • add methods: Mysql#more_results?(), Mysql#next_result(), 977 | Mysql#set_server_option(), Mysql#sqlstate() 978 |
  • add constants for Mysql#connect(): 979 | Mysql::CLIENT_MULTI_STATEMENTS, Mysql::CLIENT_MULTI_RESULTS 980 |
  • add constants for Mysql#set_server_option(): 981 | Mysql::OPTION_MULTI_STATEMENTS_ON, 982 | Mysql::OPTION_MULTI_STATEMENTS_OFF 983 |
  • add Mysql#query() with block 984 |
  • add Mysql#reconnect(), Mysql#reconnect=() 985 |
  • When connection was closed, it don't try to reconnect by default. 986 |
987 | 988 |
2005-02-12 989 |
990 | version 2.5.2 991 |
    992 |
  • BUG: Mysql#connect make object to not close. (Thanks Andres Salomon) 993 |
994 | 995 |
2004-09-20 996 |
997 | version 2.5.1 998 |
    999 |
  • add Mysql#set_ssl(). 1000 |
1001 | 1002 |
2004-08-31 1003 |
1004 | version 2.5 1005 |
    1006 |
  • correspond to MySQL 4.1.x. 1007 |
  • change MysqlRes, MysqlField, MysqlError to Mysql::Result, Mysql::Field, Mysql::Error. 1008 |
  • add Mysql.client_version(), Mysql.get_client_version(), 1009 | Mysql#client_version(), Mysql#get_client_version(), 1010 | Mysql#server_version(), Mysql#get_server_version(), 1011 | Mysql#warning_count(), Mysql#commit(), Mysql#rollback(), 1012 | Mysql#autocommit(). 1013 |
  • add Mysql::Field#is_not_null?(), Mysql::Field#is_pri_key?(), 1014 | Mysql::Field#is_num?(). 1015 |
  • add MysqlField::TYPE_VAR_STRING. 1016 |
1017 | 1018 |
2003-08-10 1019 |
1020 | version 2.4.5 1021 |
    1022 |
  • extconf.rb: correspond to MySQL 4.1. 1023 |
  • mysql.c.in: correspond to Ruby 1.8. 1024 |
1025 | 1026 |
2003-02-23 1027 |
1028 | version 2.4.4a 1029 |
    1030 |
  • make extconf.rb to correspond to Ruby 1.8.0 1031 |
1032 | 1033 |
2003-01-29 1034 |
1035 | version 2.4.4 1036 |
    1037 |
  • add Mysql::OPT_LOCAL_INFILE. 1038 |
  • add --with-mysql-config option to extconf.rb. 1039 |
  • extconf.rb automatically detect typical library. 1040 |
1041 | 1042 |
2003-01-05 1043 |
1044 | version 2.4.3c 1045 |
    1046 |
  • modified English README. Thanks to Paul DuBois. 1047 |
1048 | 1049 |
2002-12-24 1050 |
1051 | version 2.4.3b 1052 |
    1053 |
  • make extconf.rb to correspond to Ruby 1.6.8. 1054 |
1055 | 1056 |
2002-11-07 1057 |
1058 | version 2.4.3a 1059 |
    1060 |
  • fix bug duplicating constant. 1061 |
1062 | 1063 |
2002-09-10 1064 |
1065 | version 2.4.3 1066 |
    1067 |
  • for error number with prefix ER_ . 1068 |
  • get error constant from errmsg.h and mysqld_error.h automatically. 1069 |
1070 | 1071 |
2002-01-07 1072 |
1073 | version 2.4.2 1074 |
    1075 |
  • for MySQL 4.0. 1076 |
  • change `uint' to `unsigned int' (for mswin). 1077 |
1078 | 1079 |
2001-12-02 1080 |
1081 | version 2.4.1 1082 |
    1083 |
  • remove `extern' (for Cygiwn). 1084 |
  • change option of extconf.rb. 1085 |
1086 | 1087 |
2001-10-12 1088 |
1089 | version 2.4.0 1090 |
    1091 |
  • for Ruby 1.7. 1092 |
  • add Mysql::debug(), Mysql#change_user(), Mysql#character_set_name(), Mysql#dump_debug_info(). 1093 |
1094 |
1095 | 1096 |

Author

1097 |

1098 | e-mail: TOMITA Masahiro tommy@tmtm.org 1099 | http://tmtm.org 1100 |

1101 |
1102 |
TOMITA Masahiro
1103 | 1104 | 1105 | Last modified: Sun Feb 1 17:48:41 JST 2009 1106 | 1107 | 1108 | 1109 | -------------------------------------------------------------------------------- /test/test_mysql.rb: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ruby 2 | # $Id: test.rb 244 2009-02-01 08:43:39Z tommy $ 3 | 4 | require "test/unit" 5 | require 'ostruct' 6 | require 'mysql' 7 | 8 | CONFIG = OpenStruct.new 9 | CONFIG.host = ENV['MYSQL_HOST'] || 'localhost' 10 | CONFIG.port = ENV['MYSQL_PORT'] || '3306' 11 | CONFIG.user = ENV['MYSQL_USER'] || 'root' 12 | CONFIG.pass = ENV['MYSQL_PASS'] || '' 13 | CONFIG.sock = ENV['MYSQL_SOCK'] 14 | CONFIG.flag = ENV['MYSQL_FLAG'] 15 | CONFIG.database = ENV['MYSQL_DATABASE'] || 'test' 16 | 17 | class TC_Mysql < Test::Unit::TestCase 18 | def setup() 19 | @host = CONFIG.host 20 | @user = CONFIG.user 21 | @pass = CONFIG.pass 22 | @db = CONFIG.database 23 | 24 | @port = CONFIG.port.to_i 25 | @sock = CONFIG.sock 26 | @flag = CONFIG.flag.to_i 27 | end 28 | 29 | def teardown() 30 | end 31 | 32 | def test_version() 33 | assert_equal(20802, Mysql::VERSION) 34 | end 35 | 36 | def test_init() 37 | assert_nothing_raised{@m = Mysql.init} 38 | assert_nothing_raised{@m.close} 39 | end 40 | 41 | def test_real_connect() 42 | assert_nothing_raised{@m = Mysql.real_connect(@host, @user, @pass, @db, @port, @sock, @flag)} 43 | assert_nothing_raised{@m.close} 44 | end 45 | 46 | def test_connect() 47 | assert_nothing_raised{@m = Mysql.connect(@host, @user, @pass, @db, @port, @sock, @flag)} 48 | assert_nothing_raised{@m.close} 49 | end 50 | 51 | def test_new() 52 | assert_nothing_raised{@m = Mysql.new(@host, @user, @pass, @db, @port, @sock, @flag)} 53 | assert_nothing_raised{@m.close} 54 | end 55 | 56 | def test_escape_string() 57 | assert_equal("abc\\'def\\\"ghi\\0jkl%mno", Mysql.escape_string("abc'def\"ghi\0jkl%mno")) 58 | end 59 | 60 | def test_quote() 61 | assert_equal("abc\\'def\\\"ghi\\0jkl%mno", Mysql.quote("abc'def\"ghi\0jkl%mno")) 62 | end 63 | 64 | def test_get_client_info() 65 | assert_match(/^\d.\d+.\d+[a-z]?(-.*)?$/, Mysql.get_client_info()) 66 | end 67 | 68 | def test_client_info() 69 | assert_match(/^\d.\d+.\d+[a-z]?(-.*)?$/, Mysql.client_info()) 70 | end 71 | 72 | def test_options() 73 | @m = Mysql.init 74 | assert_equal(@m, @m.options(Mysql::INIT_COMMAND, "SET AUTOCOMMIT=0")) 75 | assert_equal(@m, @m.options(Mysql::OPT_COMPRESS)) 76 | assert_equal(@m, @m.options(Mysql::OPT_CONNECT_TIMEOUT, 10)) 77 | assert_equal(@m, @m.options(Mysql::GUESS_CONNECTION)) if defined? Mysql::GUESS_CONNECTION 78 | assert_equal(@m, @m.options(Mysql::OPT_LOCAL_INFILE, true)) 79 | # assert_equal(@m, @m.options(Mysql::OPT_NAMED_PIPE)) 80 | # assert_equal(@m, @m.options(Mysql::OPT_PROTOCOL, 1)) 81 | assert_equal(@m, @m.options(Mysql::OPT_READ_TIMEOUT, 10)) if defined? Mysql::OPT_READ_TIMEOUT 82 | assert_equal(@m, @m.options(Mysql::OPT_USE_EMBEDDED_CONNECTION)) if defined? Mysql::OPT_USE_EMBEDDED_CONNECTION 83 | assert_equal(@m, @m.options(Mysql::OPT_USE_REMOTE_CONNECTION)) if defined? Mysql::OPT_USE_REMOTE_CONNECTION 84 | assert_equal(@m, @m.options(Mysql::OPT_WRITE_TIMEOUT, 10)) if defined? Mysql::OPT_WRITE_TIMEOUT 85 | # assert_equal(@m, @m.options(Mysql::READ_DEFAULT_FILE, "/tmp/hoge")) 86 | assert_equal(@m, @m.options(Mysql::READ_DEFAULT_GROUP, "test")) 87 | assert_equal(@m, @m.options(Mysql::SECURE_AUTH, true)) if defined? Mysql::SECURE_AUTH 88 | # assert_equal(@m, @m.options(Mysql::SET_CHARSET_DIR, "??")) 89 | assert_equal(@m, @m.options(Mysql::SET_CHARSET_NAME, "latin1")) 90 | assert_equal(@m, @m.options(Mysql::SET_CLIENT_IP, "127.0.0.1")) if defined? Mysql::SET_CLIENT_IP 91 | # assert_equal(@m, @m.options(Mysql::SHARED_MEMORY_BASE_NAME, "xxx")) 92 | assert_equal(@m, @m.connect(@host, @user, @pass, @db, @port, @sock, @flag)) 93 | @m.close 94 | end 95 | 96 | def test_real_connect2() 97 | @m = Mysql.init 98 | assert_equal(@m, @m.real_connect(@host, @user, @pass, @db, @port, @sock, @flag)) 99 | @m.close 100 | end 101 | 102 | def test_connect2() 103 | @m = Mysql.init 104 | assert_equal(@m, @m.connect(@host, @user, @pass, @db, @port, @sock, @flag)) 105 | @m.close 106 | end 107 | 108 | end 109 | 110 | class TC_Mysql2 < Test::Unit::TestCase 111 | def setup() 112 | @host = CONFIG.host 113 | @user = CONFIG.user 114 | @pass = CONFIG.pass 115 | @db = CONFIG.database 116 | 117 | @port = CONFIG.port.to_i 118 | @sock = CONFIG.sock 119 | @flag = CONFIG.flag.to_i 120 | 121 | @m = Mysql.new(@host, @user, @pass, @db, @port, @sock, @flag) 122 | end 123 | 124 | def teardown() 125 | @m.close if @m 126 | end 127 | 128 | def test_affected_rows() 129 | @m.query("create temporary table t (id int)") 130 | @m.query("insert into t values (1)") 131 | assert_equal(1, @m.affected_rows) 132 | end 133 | 134 | def test_autocommit() 135 | if @m.methods.include? "autocommit" then 136 | assert_equal(@m, @m.autocommit(true)) 137 | assert_equal(@m, @m.autocommit(false)) 138 | end 139 | end 140 | 141 | # def test_ssl_set() 142 | # end 143 | 144 | def test_more_results_next_result() 145 | if @m.server_version >= 40100 then 146 | @m.query_with_result = false 147 | @m.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON) if defined? Mysql::OPTION_MULTI_STATEMENTS_ON 148 | @m.query("select 1,2,3; select 4,5,6") 149 | res = @m.store_result 150 | assert_equal(["1","2","3"], res.fetch_row) 151 | assert_equal(nil, res.fetch_row) 152 | assert_equal(true, @m.more_results) 153 | assert_equal(true, @m.more_results?) 154 | assert_equal(true, @m.next_result) 155 | res = @m.store_result 156 | assert_equal(["4","5","6"], res.fetch_row) 157 | assert_equal(nil, res.fetch_row) 158 | assert_equal(false, @m.more_results) 159 | assert_equal(false, @m.more_results?) 160 | assert_equal(false, @m.next_result) 161 | end 162 | end if Mysql.client_version >= 40100 163 | 164 | def test_query_with_block() 165 | if @m.server_version >= 40100 then 166 | @m.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON) 167 | expect = [["1","2","3"], ["4","5","6"]] 168 | @m.query("select 1,2,3; select 4,5,6") {|res| 169 | assert_equal(1, res.num_rows) 170 | assert_equal(expect.shift, res.fetch_row) 171 | } 172 | assert(expect.empty?) 173 | expect = [["1","2","3"], ["4","5","6"]] 174 | assert_raises(Mysql::Error) { 175 | @m.query("select 1,2,3; hoge; select 4,5,6") {|res| 176 | assert_equal(1, res.num_rows) 177 | assert_equal(expect.shift, res.fetch_row) 178 | } 179 | } 180 | assert_equal(1, expect.size) 181 | expect = [["1","2","3"], ["4","5","6"]] 182 | assert_raises(Mysql::Error) { 183 | @m.query("select 1,2,3; select 4,5,6; hoge") {|res| 184 | assert_equal(1, res.num_rows) 185 | assert_equal(expect.shift, res.fetch_row) 186 | } 187 | } 188 | assert(expect.empty?) 189 | end 190 | end 191 | 192 | def test_query_with_block_single() 193 | @m.query("select 1,2,3") {|res| 194 | assert_equal(1, res.num_rows) 195 | assert_equal(["1","2","3"], res.fetch_row) 196 | } 197 | end 198 | 199 | def test_set_server_option() 200 | if @m.server_version >= 40101 then 201 | assert_equal(@m, @m.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON)) 202 | assert_equal(@m, @m.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_OFF)) 203 | end 204 | end if Mysql.client_version >= 40101 205 | 206 | def test_sqlstate() 207 | if @m.server_version >= 40100 then 208 | if RUBY_PLATFORM !~ /mingw|mswin/ then 209 | assert_equal("00000", @m.sqlstate) 210 | else 211 | assert_equal("HY000", @m.sqlstate) 212 | end 213 | assert_raises(Mysql::Error){@m.query("hogehoge")} 214 | assert_equal("42000", @m.sqlstate) 215 | end 216 | end 217 | 218 | def test_query_with_result() 219 | assert_equal(true, @m.query_with_result) 220 | assert_equal(false, @m.query_with_result = false) 221 | assert_equal(false, @m.query_with_result) 222 | assert_equal(true, @m.query_with_result = true) 223 | assert_equal(true, @m.query_with_result) 224 | end 225 | 226 | def test_reconnect() 227 | assert_equal(false, @m.reconnect) 228 | assert_equal(true, @m.reconnect = true) 229 | assert_equal(true, @m.reconnect) 230 | assert_equal(false, @m.reconnect = false) 231 | assert_equal(false, @m.reconnect) 232 | end 233 | end 234 | 235 | class TC_MysqlRes < Test::Unit::TestCase 236 | def setup() 237 | @host = CONFIG.host 238 | @user = CONFIG.user 239 | @pass = CONFIG.pass 240 | @db = CONFIG.database 241 | 242 | @port = CONFIG.port.to_i 243 | @sock = CONFIG.sock 244 | @flag = CONFIG.flag.to_i 245 | 246 | @m = Mysql.new(@host, @user, @pass, @db, @port, @sock, @flag) 247 | @m.query("create temporary table t (id int, str char(10), primary key (id))") 248 | @m.query("insert into t values (1, 'abc'), (2, 'defg'), (3, 'hi'), (4, null)") 249 | @res = @m.query("select * from t") 250 | end 251 | 252 | def teardown() 253 | @res.free 254 | @m.close 255 | end 256 | 257 | def test_num_fields() 258 | assert_equal(2, @res.num_fields) 259 | end 260 | 261 | def test_num_rows() 262 | assert_equal(4, @res.num_rows) 263 | end 264 | 265 | def test_fetch_row() 266 | assert_equal(["1","abc"], @res.fetch_row) 267 | assert_equal(["2","defg"], @res.fetch_row) 268 | assert_equal(["3","hi"], @res.fetch_row) 269 | assert_equal(["4",nil], @res.fetch_row) 270 | assert_equal(nil, @res.fetch_row) 271 | end 272 | 273 | def test_fetch_hash() 274 | assert_equal({"id"=>"1", "str"=>"abc"}, @res.fetch_hash) 275 | assert_equal({"id"=>"2", "str"=>"defg"}, @res.fetch_hash) 276 | assert_equal({"id"=>"3", "str"=>"hi"}, @res.fetch_hash) 277 | assert_equal({"id"=>"4", "str"=>nil}, @res.fetch_hash) 278 | assert_equal(nil, @res.fetch_hash) 279 | end 280 | 281 | def test_fetch_hash2() 282 | assert_equal({"t.id"=>"1", "t.str"=>"abc"}, @res.fetch_hash(true)) 283 | assert_equal({"t.id"=>"2", "t.str"=>"defg"}, @res.fetch_hash(true)) 284 | assert_equal({"t.id"=>"3", "t.str"=>"hi"}, @res.fetch_hash(true)) 285 | assert_equal({"t.id"=>"4", "t.str"=>nil}, @res.fetch_hash(true)) 286 | assert_equal(nil, @res.fetch_hash) 287 | end 288 | 289 | def test_each() 290 | ary = [["1","abc"], ["2","defg"], ["3","hi"], ["4",nil]] 291 | @res.each do |a| 292 | assert_equal(ary.shift, a) 293 | end 294 | end 295 | 296 | def test_each_hash() 297 | hash = [{"id"=>"1","str"=>"abc"}, {"id"=>"2","str"=>"defg"}, {"id"=>"3","str"=>"hi"}, {"id"=>"4","str"=>nil}] 298 | @res.each_hash do |h| 299 | assert_equal(hash.shift, h) 300 | end 301 | end 302 | 303 | def test_data_seek() 304 | assert_equal(["1","abc"], @res.fetch_row) 305 | assert_equal(["2","defg"], @res.fetch_row) 306 | assert_equal(["3","hi"], @res.fetch_row) 307 | @res.data_seek(1) 308 | assert_equal(["2","defg"], @res.fetch_row) 309 | end 310 | 311 | def test_row_seek() 312 | assert_equal(["1","abc"], @res.fetch_row) 313 | pos = @res.row_tell 314 | assert_equal(["2","defg"], @res.fetch_row) 315 | assert_equal(["3","hi"], @res.fetch_row) 316 | @res.row_seek(pos) 317 | assert_equal(["2","defg"], @res.fetch_row) 318 | end 319 | 320 | def test_field_seek() 321 | assert_equal(0, @res.field_tell) 322 | @res.fetch_field 323 | assert_equal(1, @res.field_tell) 324 | @res.fetch_field 325 | assert_equal(2, @res.field_tell) 326 | @res.field_seek(1) 327 | assert_equal(1, @res.field_tell) 328 | end 329 | 330 | def test_fetch_field() 331 | f = @res.fetch_field 332 | assert_equal("id", f.name) 333 | assert_equal("t", f.table) 334 | assert_equal(nil, f.def) 335 | assert_equal(Mysql::Field::TYPE_LONG, f.type) 336 | assert_equal(11, f.length) 337 | assert_equal(1, f.max_length) 338 | assert_equal(Mysql::Field::NUM_FLAG|Mysql::Field::PRI_KEY_FLAG|Mysql::Field::PART_KEY_FLAG|Mysql::Field::NOT_NULL_FLAG, f.flags) 339 | assert_equal(0, f.decimals) 340 | f = @res.fetch_field 341 | assert_equal("str", f.name) 342 | assert_equal("t", f.table) 343 | assert_equal(nil, f.def) 344 | assert_equal(Mysql::Field::TYPE_STRING, f.type) 345 | assert_equal(30, f.length) 346 | assert_equal(4, f.max_length) 347 | assert_equal(0, f.flags) 348 | assert_equal(0, f.decimals) 349 | f = @res.fetch_field 350 | assert_equal(nil, f) 351 | end 352 | 353 | def test_fetch_fields() 354 | a = @res.fetch_fields 355 | assert_equal(2, a.size) 356 | assert_equal("id", a[0].name) 357 | assert_equal("str", a[1].name) 358 | end 359 | 360 | def test_fetch_field_direct() 361 | f = @res.fetch_field_direct(0) 362 | assert_equal("id", f.name) 363 | f = @res.fetch_field_direct(1) 364 | assert_equal("str", f.name) 365 | assert_raises(Mysql::Error){@res.fetch_field_direct(-1)} 366 | assert_raises(Mysql::Error){@res.fetch_field_direct(2)} 367 | end 368 | 369 | def test_fetch_lengths() 370 | assert_equal(nil, @res.fetch_lengths()) 371 | @res.fetch_row 372 | assert_equal([1, 3], @res.fetch_lengths()) 373 | @res.fetch_row 374 | assert_equal([1, 4], @res.fetch_lengths()) 375 | @res.fetch_row 376 | assert_equal([1, 2], @res.fetch_lengths()) 377 | @res.fetch_row 378 | assert_equal([1, 0], @res.fetch_lengths()) 379 | @res.fetch_row 380 | assert_equal(nil, @res.fetch_lengths()) 381 | end 382 | 383 | def test_field_hash() 384 | f = @res.fetch_field 385 | h = { 386 | "name" => "id", 387 | "table" => "t", 388 | "def" => nil, 389 | "type" => Mysql::Field::TYPE_LONG, 390 | "length" => 11, 391 | "max_length" => 1, 392 | "flags" => Mysql::Field::NUM_FLAG|Mysql::Field::PRI_KEY_FLAG|Mysql::Field::PART_KEY_FLAG|Mysql::Field::NOT_NULL_FLAG, 393 | "decimals" => 0, 394 | } 395 | assert_equal(h, f.hash) 396 | f = @res.fetch_field 397 | h = { 398 | "name" => "str", 399 | "table" => "t", 400 | "def" => nil, 401 | "type" => Mysql::Field::TYPE_STRING, 402 | "length" => 30, 403 | "max_length" => 4, 404 | "flags" => 0, 405 | "decimals" => 0, 406 | } 407 | assert_equal(h, f.hash) 408 | end 409 | 410 | def test_field_inspect() 411 | f = @res.fetch_field 412 | assert_equal("#", f.inspect) 413 | f = @res.fetch_field 414 | assert_equal("#", f.inspect) 415 | end 416 | 417 | def test_is_num() 418 | f = @res.fetch_field 419 | assert_equal(true, f.is_num?) 420 | f = @res.fetch_field 421 | assert_equal(false, f.is_num?) 422 | end 423 | 424 | def test_is_not_null() 425 | f = @res.fetch_field 426 | assert_equal(true, f.is_not_null?) 427 | f = @res.fetch_field 428 | assert_equal(false, f.is_not_null?) 429 | end 430 | 431 | def test_is_pri_key() 432 | f = @res.fetch_field 433 | assert_equal(true, f.is_pri_key?) 434 | f = @res.fetch_field 435 | assert_equal(false, f.is_pri_key?) 436 | end 437 | 438 | end 439 | 440 | class TC_MysqlStmt < Test::Unit::TestCase 441 | def setup() 442 | @host = CONFIG.host 443 | @user = CONFIG.user 444 | @pass = CONFIG.pass 445 | @db = CONFIG.database 446 | 447 | @port = CONFIG.port.to_i 448 | @sock = CONFIG.sock 449 | @flag = CONFIG.flag.to_i 450 | 451 | @m = Mysql.new(@host, @user, @pass, @db, @port, @sock, @flag) 452 | end 453 | 454 | def teardown() 455 | end 456 | 457 | def test_init() 458 | if @m.server_version >= 40100 then 459 | s = @m.stmt_init() 460 | assert_equal(Mysql::Stmt, s.class) 461 | s.close 462 | end 463 | end 464 | 465 | def test_prepare() 466 | if @m.server_version >= 40100 then 467 | s = @m.prepare("select 1") 468 | assert_equal(Mysql::Stmt, s.class) 469 | s.close 470 | end 471 | end 472 | 473 | end if Mysql.client_version >= 40100 474 | 475 | class TC_MysqlStmt2 < Test::Unit::TestCase 476 | def setup() 477 | @host = CONFIG.host 478 | @user = CONFIG.user 479 | @pass = CONFIG.pass 480 | @db = CONFIG.database 481 | 482 | @port = CONFIG.port.to_i 483 | @sock = CONFIG.sock 484 | @flag = CONFIG.flag.to_i 485 | 486 | @m = Mysql.new(@host, @user, @pass, @db, @port, @sock, @flag) 487 | @s = @m.stmt_init() 488 | end 489 | 490 | def teardown() 491 | @s.close 492 | @m.close 493 | end 494 | 495 | def test_affected_rows() 496 | if @m.server_version >= 40100 then 497 | @m.query("create temporary table t (i int, c char(10))") 498 | @s.prepare("insert into t values (?,?)") 499 | @s.execute(1, "hoge") 500 | assert_equal(1, @s.affected_rows()) 501 | @s.execute(2, "hoge") 502 | @s.execute(3, "hoge") 503 | @s.prepare("update t set c=?") 504 | @s.execute("fuga") 505 | assert_equal(3, @s.affected_rows()) 506 | end 507 | end 508 | 509 | =begin 510 | def test_attr_get() 511 | assert_equal(false, @s.attr_get(Mysql::Stmt::ATTR_UPDATE_MAX_LENGTH)) 512 | assert_raises(Mysql::Error){@s.attr_get(999)} 513 | end 514 | 515 | def test_attr_set() 516 | @s.attr_set(Mysql::Stmt::ATTR_UPDATE_MAX_LENGTH, true) 517 | assert_equal(true, @s.attr_get(Mysql::Stmt::ATTR_UPDATE_MAX_LENGTH)) 518 | @s.attr_set(Mysql::Stmt::ATTR_UPDATE_MAX_LENGTH, false) 519 | assert_equal(false, @s.attr_get(Mysql::Stmt::ATTR_UPDATE_MAX_LENGTH)) 520 | assert_raises(Mysql::Error){@s.attr_set(999, true)} 521 | end 522 | 523 | def test_bind_param() 524 | @s.prepare("insert into t values (?,?)") 525 | @s.bind_param(123, "abc") 526 | @s.bind_param(Time.now, nil) 527 | assert_raises(Mysql::Error){@s.bind_param(1, 2, 3)} 528 | b = @s.bind_param(Bind.new(Mysql::TYPE_TINY, 99, false)) 529 | @s.bind_param(98.765, b) 530 | end 531 | =end 532 | 533 | def test_bind_result_nil() 534 | if @m.server_version >= 40100 then 535 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 536 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 537 | @s.prepare("select * from t") 538 | @s.bind_result(nil,nil,nil,nil) 539 | @s.execute 540 | a = @s.fetch 541 | assert_equal([123, "9abcdefg", 1.2345, Mysql::Time.new(2005,8,2,23,50,11)], a) 542 | end 543 | end 544 | 545 | def test_bind_result_numeric() 546 | if @m.server_version >= 40100 then 547 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 548 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 549 | @s.prepare("select * from t") 550 | @s.bind_result(Numeric, Numeric, Numeric, Numeric) 551 | @s.execute 552 | a = @s.fetch 553 | if Mysql.client_version < 50000 then 554 | assert_equal([123, 9, 1, 2005], a) 555 | else 556 | assert_equal([123, 9, 1, 20050802235011], a) 557 | end 558 | end 559 | end 560 | 561 | def test_bind_result_integer() 562 | if @m.server_version >= 40100 then 563 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 564 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 565 | @s.prepare("select * from t") 566 | @s.bind_result(Integer, Integer, Integer, Integer) 567 | @s.execute 568 | a = @s.fetch 569 | if Mysql.client_version < 50000 then 570 | assert_equal([123, 9, 1, 2005], a) 571 | else 572 | assert_equal([123, 9, 1, 20050802235011], a) 573 | end 574 | end 575 | end 576 | 577 | def test_bind_result_fixnum() 578 | if @m.server_version >= 40100 then 579 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 580 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 581 | @s.prepare("select * from t") 582 | @s.bind_result(Fixnum, Fixnum, Fixnum, Fixnum) 583 | @s.execute 584 | a = @s.fetch 585 | if Mysql.client_version < 50000 then 586 | assert_equal([123, 9, 1, 2005], a) 587 | else 588 | assert_equal([123, 9, 1, 20050802235011.0], a) 589 | end 590 | end 591 | end 592 | 593 | def test_bind_result_string() 594 | if @m.server_version >= 40100 then 595 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 596 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 597 | @s.prepare("select * from t") 598 | @s.bind_result(String, String, String, String) 599 | @s.execute 600 | a = @s.fetch 601 | assert_equal(["123", "9abcdefg", "1.2345", "2005-08-02 23:50:11"], a) 602 | end 603 | end 604 | 605 | def test_bind_result_float() 606 | if @m.server_version >= 40100 then 607 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 608 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 609 | @s.prepare("select * from t") 610 | @s.bind_result(Float, Float, Float, Float) 611 | @s.execute 612 | a = @s.fetch 613 | if Mysql.client_version < 50000 then 614 | assert_equal([123.0, 9.0, 1.2345, 2005.0], a) 615 | else 616 | assert_equal([123.0, 9.0, 1.2345, 20050802235011.0], a) 617 | end 618 | end 619 | end 620 | 621 | def test_bind_result_mysqltime() 622 | if @m.server_version >= 40100 then 623 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 624 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 625 | @s.prepare("select * from t") 626 | @s.bind_result(Mysql::Time, Mysql::Time, Mysql::Time, Mysql::Time) 627 | @s.execute 628 | a = @s.fetch 629 | if Mysql.client_version < 50000 then 630 | assert_equal([Mysql::Time.new, Mysql::Time.new, Mysql::Time.new, Mysql::Time.new(2005,8,2,23,50,11)], a) 631 | else 632 | assert_equal([Mysql::Time.new(2000,1,23), Mysql::Time.new, Mysql::Time.new, Mysql::Time.new(2005,8,2,23,50,11)], a) 633 | end 634 | end 635 | end 636 | 637 | def test_bind_result_unknown() 638 | if @m.server_version >= 40100 then 639 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 640 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 641 | @s.prepare("select * from t") 642 | assert_raises(TypeError){@s.bind_result(Time, nil, nil, nil)} 643 | end 644 | end 645 | 646 | def test_bind_result_unmatch_count() 647 | if @m.server_version >= 40100 then 648 | @m.query("create temporary table t (i int, c char(10), d double, t datetime)") 649 | @m.query("insert into t values (123, '9abcdefg', 1.2345, 20050802235011)") 650 | @s.prepare("select * from t") 651 | assert_raises(Mysql::Error){@s.bind_result(nil, nil)} 652 | end 653 | end 654 | 655 | def test_data_seek() 656 | if @m.server_version >= 40100 then 657 | @m.query("create temporary table t (i int)") 658 | @m.query("insert into t values (0),(1),(2),(3),(4),(5)") 659 | @s.prepare("select i from t") 660 | @s.execute 661 | assert_equal([0], @s.fetch) 662 | assert_equal([1], @s.fetch) 663 | assert_equal([2], @s.fetch) 664 | @s.data_seek(5) 665 | assert_equal([5], @s.fetch) 666 | @s.data_seek(1) 667 | assert_equal([1], @s.fetch) 668 | end 669 | end 670 | 671 | =begin 672 | def test_errno() 673 | @s.errno() 674 | end 675 | 676 | def test_error() 677 | @s.error() 678 | end 679 | =end 680 | 681 | def test_execute() 682 | if @m.server_version >= 40100 then 683 | @m.query("create temporary table t (i int)") 684 | @s.prepare("insert into t values (123)") 685 | @s.execute() 686 | assert_equal(1, @s.affected_rows) 687 | @s.execute() 688 | assert_equal(1, @s.affected_rows) 689 | assert_equal(2, @m.query("select count(*) from t").fetch_row[0].to_i) 690 | end 691 | end 692 | 693 | def test_execute2() 694 | if @m.server_version >= 40100 then 695 | @m.query("create temporary table t (i int)") 696 | @s.prepare("insert into t values (?)") 697 | @s.execute(123) 698 | @s.execute("456") 699 | @s.prepare("select * from t") 700 | @s.execute 701 | assert_equal([123], @s.fetch) 702 | assert_equal([456], @s.fetch) 703 | end 704 | end 705 | 706 | def test_execute3() 707 | if @m.server_version >= 40100 then 708 | @m.query("create temporary table t (i int, c char(255), t timestamp)") 709 | @s.prepare("insert into t values (?,?,?)") 710 | @s.execute(123, "hoge", Time.local(2005,7,19,23,53,0)); 711 | assert_raises(Mysql::Error){@s.execute(123, "hoge")} 712 | assert_raises(Mysql::Error){@s.execute(123, "hoge", 0, "fuga")} 713 | @s.prepare("select * from t") 714 | @s.execute 715 | assert_equal([123, "hoge", Mysql::Time.new(2005,7,19,23,53,0)], @s.fetch) 716 | end 717 | end 718 | 719 | def test_execute4() 720 | if @m.server_version >= 40100 then 721 | @m.query("create temporary table t (i int, c char(255), t timestamp)") 722 | @s.prepare("insert into t values (?,?,?)") 723 | @s.execute(nil, "hoge", Mysql::Time.new(2005,7,19,23,53,0)); 724 | @s.prepare("select * from t") 725 | @s.execute 726 | assert_equal([nil, "hoge", Mysql::Time.new(2005,7,19,23,53,0)], @s.fetch) 727 | end 728 | end 729 | 730 | def test_execute5() 731 | if @m.server_version >= 40100 then 732 | [30, 31, 32, 62, 63].each do |i| 733 | v, = @m.prepare("select cast(? as signed)").execute(2**i-1).fetch 734 | assert_equal(2**i-1, v) 735 | v, = @m.prepare("select cast(? as signed)").execute(-(2**i)).fetch 736 | assert_equal(-(2**i), v) 737 | end 738 | end 739 | end 740 | 741 | def test_fetch() 742 | if @m.server_version >= 40100 then 743 | @s.prepare("select 123, 'abc', null") 744 | @s.execute() 745 | assert_equal([123, "abc", nil], @s.fetch()) 746 | end 747 | end 748 | 749 | def test_fetch_bit() 750 | if @m.client_version >= 50003 and @m.server_version >= 50003 then 751 | @m.query("create temporary table t (i bit(8))") 752 | @m.query("insert into t values (0),(-1),(127),(-128),(255),(-255),(256)") 753 | @s.prepare("select i from t") 754 | @s.execute 755 | assert_equal(["\x00"], @s.fetch) 756 | assert_equal(["\xff"], @s.fetch) 757 | assert_equal(["\x7f"], @s.fetch) 758 | assert_equal(["\xff"], @s.fetch) 759 | assert_equal(["\xff"], @s.fetch) 760 | assert_equal(["\xff"], @s.fetch) 761 | assert_equal(["\xff"], @s.fetch) 762 | @m.query("create temporary table t2 (i bit(64))") 763 | @m.query("insert into t2 values (0),(-1),(4294967296),(18446744073709551615),(18446744073709551616)") 764 | @s.prepare("select i from t2") 765 | @s.execute 766 | assert_equal(["\x00\x00\x00\x00\x00\x00\x00\x00"], @s.fetch) 767 | assert_equal(["\xff\xff\xff\xff\xff\xff\xff\xff"], @s.fetch) 768 | assert_equal(["\x00\x00\x00\x01\x00\x00\x00\x00"], @s.fetch) 769 | assert_equal(["\xff\xff\xff\xff\xff\xff\xff\xff"], @s.fetch) 770 | assert_equal(["\xff\xff\xff\xff\xff\xff\xff\xff"], @s.fetch) 771 | end 772 | end 773 | 774 | def test_fetch_tinyint() 775 | if @m.server_version >= 40100 then 776 | @m.query("create temporary table t (i tinyint)") 777 | @m.query("insert into t values (0),(-1),(127),(-128),(255),(-255)") 778 | @s.prepare("select i from t") 779 | @s.execute 780 | assert_equal([0], @s.fetch) 781 | assert_equal([-1], @s.fetch) 782 | assert_equal([127], @s.fetch) 783 | assert_equal([-128], @s.fetch) 784 | assert_equal([127], @s.fetch) 785 | assert_equal([-128], @s.fetch) 786 | end 787 | end 788 | 789 | def test_fetch_tinyint_unsigned() 790 | if @m.server_version >= 40100 then 791 | @m.query("create temporary table t (i tinyint unsigned)") 792 | @m.query("insert into t values (0),(-1),(127),(-128),(255),(-255),(256)") 793 | @s.prepare("select i from t") 794 | @s.execute 795 | assert_equal([0], @s.fetch) 796 | assert_equal([0], @s.fetch) 797 | assert_equal([127], @s.fetch) 798 | assert_equal([0], @s.fetch) 799 | assert_equal([255], @s.fetch) 800 | assert_equal([0], @s.fetch) 801 | assert_equal([255], @s.fetch) 802 | end 803 | end 804 | 805 | def test_fetch_smallint() 806 | if @m.server_version >= 40100 then 807 | @m.query("create temporary table t (i smallint)") 808 | @m.query("insert into t values (0),(-1),(32767),(-32768),(65535),(-65535),(65536)") 809 | @s.prepare("select i from t") 810 | @s.execute 811 | assert_equal([0], @s.fetch) 812 | assert_equal([-1], @s.fetch) 813 | assert_equal([32767], @s.fetch) 814 | assert_equal([-32768], @s.fetch) 815 | assert_equal([32767], @s.fetch) 816 | assert_equal([-32768], @s.fetch) 817 | end 818 | end 819 | 820 | def test_fetch_smallint_unsigned() 821 | if @m.server_version >= 40100 then 822 | @m.query("create temporary table t (i smallint unsigned)") 823 | @m.query("insert into t values (0),(-1),(32767),(-32768),(65535),(-65535),(65536)") 824 | @s.prepare("select i from t") 825 | @s.execute 826 | assert_equal([0], @s.fetch) 827 | assert_equal([0], @s.fetch) 828 | assert_equal([32767], @s.fetch) 829 | assert_equal([0], @s.fetch) 830 | assert_equal([65535], @s.fetch) 831 | assert_equal([0], @s.fetch) 832 | assert_equal([65535], @s.fetch) 833 | end 834 | end 835 | 836 | def test_fetch_mediumint() 837 | if @m.server_version >= 40100 then 838 | @m.query("create temporary table t (i mediumint)") 839 | @m.query("insert into t values (0),(-1),(8388607),(-8388608),(16777215),(-16777215),(16777216)") 840 | @s.prepare("select i from t") 841 | @s.execute 842 | assert_equal([0], @s.fetch) 843 | assert_equal([-1], @s.fetch) 844 | assert_equal([8388607], @s.fetch) 845 | assert_equal([-8388608], @s.fetch) 846 | assert_equal([8388607], @s.fetch) 847 | assert_equal([-8388608], @s.fetch) 848 | end 849 | end 850 | 851 | def test_fetch_mediumint_unsigned() 852 | if @m.server_version >= 40100 then 853 | @m.query("create temporary table t (i mediumint unsigned)") 854 | @m.query("insert into t values (0),(-1),(8388607),(-8388608),(16777215),(-16777215),(16777216)") 855 | @s.prepare("select i from t") 856 | @s.execute 857 | assert_equal([0], @s.fetch) 858 | assert_equal([0], @s.fetch) 859 | assert_equal([8388607], @s.fetch) 860 | assert_equal([0], @s.fetch) 861 | assert_equal([16777215], @s.fetch) 862 | assert_equal([0], @s.fetch) 863 | assert_equal([16777215], @s.fetch) 864 | end 865 | end 866 | 867 | def test_fetch_int() 868 | if @m.server_version >= 40100 then 869 | @m.query("create temporary table t (i int)") 870 | @m.query("insert into t values (0),(-1),(2147483647),(-2147483648),(4294967295),(-4294967295),(4294967296)") 871 | @s.prepare("select i from t") 872 | @s.execute 873 | assert_equal([0], @s.fetch) 874 | assert_equal([-1], @s.fetch) 875 | assert_equal([2147483647], @s.fetch) 876 | assert_equal([-2147483648], @s.fetch) 877 | assert_equal([2147483647], @s.fetch) 878 | assert_equal([-2147483648], @s.fetch) 879 | end 880 | end 881 | 882 | def test_fetch_int_unsigned() 883 | if @m.server_version >= 40100 then 884 | @m.query("create temporary table t (i int unsigned)") 885 | @m.query("insert into t values (0),(-1),(2147483647),(-2147483648),(4294967295),(-4294967295),(4294967296)") 886 | @s.prepare("select i from t") 887 | @s.execute 888 | assert_equal([0], @s.fetch) 889 | assert_equal([0], @s.fetch) 890 | assert_equal([2147483647], @s.fetch) 891 | assert_equal([0], @s.fetch) 892 | assert_equal([4294967295], @s.fetch) 893 | assert_equal([0], @s.fetch) 894 | assert_equal([4294967295], @s.fetch) 895 | end 896 | end 897 | 898 | def test_fetch_bigint() 899 | if @m.server_version >= 40100 then 900 | @m.query("create temporary table t (i bigint)") 901 | @m.query("insert into t values (0),(-1),(9223372036854775807),(-9223372036854775808),(18446744073709551615),(-18446744073709551615),(18446744073709551616)") 902 | @s.prepare("select i from t") 903 | @s.execute 904 | assert_equal([0], @s.fetch) 905 | assert_equal([-1], @s.fetch) 906 | assert_equal([9223372036854775807], @s.fetch) 907 | assert_equal([-9223372036854775808], @s.fetch) 908 | if @m.server_version >= 50000 then 909 | assert_equal([9223372036854775807], @s.fetch) 910 | else 911 | assert_equal([-1], @s.fetch) # MySQL problem 912 | end 913 | assert_equal([-9223372036854775808], @s.fetch) 914 | assert_equal([9223372036854775807], @s.fetch) 915 | end 916 | end 917 | 918 | def test_fetch_bigint_unsigned() 919 | if @m.server_version >= 40100 then 920 | @m.query("create temporary table t (i bigint unsigned)") 921 | @m.query("insert into t values (0),(-1),(9223372036854775807),(-9223372036854775808),(18446744073709551615),(-18446744073709551615),(18446744073709551616)") 922 | @s.prepare("select i from t") 923 | @s.execute 924 | assert_equal([0], @s.fetch) 925 | if @m.server_version >= 50000 then 926 | assert_equal([0], @s.fetch) 927 | else 928 | assert_equal([18446744073709551615], @s.fetch) # MySQL problem 929 | end 930 | assert_equal([9223372036854775807], @s.fetch) 931 | if @m.server_version >= 50000 then 932 | assert_equal([0], @s.fetch) 933 | else 934 | assert_equal([9223372036854775808], @s.fetch) # MySQL problem 935 | end 936 | assert_equal([18446744073709551615], @s.fetch) 937 | assert_equal([0], @s.fetch) 938 | assert_equal([18446744073709551615], @s.fetch) 939 | end 940 | end 941 | 942 | def test_fetch_float() 943 | if @m.server_version >= 40100 then 944 | @m.query("create temporary table t (i float)") 945 | @m.query("insert into t values (0),(-3.402823466E+38),(-1.175494351E-38),(1.175494351E-38),(3.402823466E+38)") 946 | @s.prepare("select i from t") 947 | @s.execute 948 | assert_equal([0], @s.fetch) 949 | assert_in_delta(-3.402823466E+38, @s.fetch[0], 0.000000001E+38) 950 | assert_in_delta(-1.175494351E-38, @s.fetch[0], 0.000000001E-38) 951 | assert_in_delta(1.175494351E-38, @s.fetch[0], 0.000000001E-38) 952 | assert_in_delta(3.402823466E+38, @s.fetch[0], 0.000000001E+38) 953 | end 954 | end 955 | 956 | def test_fetch_float_unsigned() 957 | if @m.server_version >= 40100 then 958 | @m.query("create temporary table t (i float unsigned)") 959 | @m.query("insert into t values (0),(-3.402823466E+38),(-1.175494351E-38),(1.175494351E-38),(3.402823466E+38)") 960 | @s.prepare("select i from t") 961 | @s.execute 962 | assert_equal([0], @s.fetch) 963 | assert_equal([0], @s.fetch) 964 | assert_equal([0], @s.fetch) 965 | assert_in_delta(1.175494351E-38, @s.fetch[0], 0.000000001E-38) 966 | assert_in_delta(3.402823466E+38, @s.fetch[0], 0.000000001E+38) 967 | end 968 | end 969 | 970 | def test_fetch_double() 971 | if @m.server_version >= 40100 then 972 | @m.query("create temporary table t (i double)") 973 | @m.query("insert into t values (0),(-1.7976931348623157E+308),(-2.2250738585072014E-308),(2.2250738585072014E-308),(1.7976931348623157E+308)") 974 | @s.prepare("select i from t") 975 | @s.execute 976 | assert_equal([0], @s.fetch) 977 | assert_in_delta(-Float::MAX, @s.fetch[0], Float::EPSILON) 978 | assert_in_delta(-Float::MIN, @s.fetch[0], Float::EPSILON) 979 | assert_in_delta(Float::MIN, @s.fetch[0], Float::EPSILON) 980 | assert_in_delta(Float::MAX, @s.fetch[0], Float::EPSILON) 981 | end 982 | end 983 | 984 | def test_fetch_double_unsigned() 985 | if @m.server_version >= 40100 then 986 | @m.query("create temporary table t (i double unsigned)") 987 | @m.query("insert into t values (0),(-1.7976931348623157E+308),(-2.2250738585072014E-308),(2.2250738585072014E-308),(1.7976931348623157E+308)") 988 | @s.prepare("select i from t") 989 | @s.execute 990 | assert_equal([0], @s.fetch) 991 | assert_equal([0], @s.fetch) 992 | assert_equal([0], @s.fetch) 993 | assert_in_delta(Float::MIN, @s.fetch[0], Float::EPSILON) 994 | assert_in_delta(Float::MAX, @s.fetch[0], Float::EPSILON) 995 | end 996 | end 997 | 998 | def test_fetch_decimal() 999 | if (@m.server_version >= 50000 and Mysql.client_version >= 50000) or (@m.server_version >= 40100 and @m.server_version < 50000) then 1000 | @m.query("create temporary table t (i decimal)") 1001 | @m.query("insert into t values (0),(9999999999),(-9999999999),(10000000000),(-10000000000)") 1002 | @s.prepare("select i from t") 1003 | @s.execute 1004 | assert_equal(["0"], @s.fetch) 1005 | assert_equal(["9999999999"], @s.fetch) 1006 | assert_equal(["-9999999999"], @s.fetch) 1007 | if @m.server_version < 50000 then 1008 | assert_equal(["10000000000"], @s.fetch) # MySQL problem 1009 | else 1010 | assert_equal(["9999999999"], @s.fetch) 1011 | end 1012 | assert_equal(["-9999999999"], @s.fetch) 1013 | end 1014 | end 1015 | 1016 | def test_fetch_decimal_unsigned() 1017 | if (@m.server_version >= 50000 and Mysql.client_version >= 50000) or (@m.server_version >= 40100 and @m.server_version < 50000) then 1018 | @m.query("create temporary table t (i decimal unsigned)") 1019 | @m.query("insert into t values (0),(9999999998),(9999999999),(-9999999998),(-9999999999),(10000000000),(-10000000000)") 1020 | @s.prepare("select i from t") 1021 | @s.execute 1022 | assert_equal(["0"], @s.fetch) 1023 | assert_equal(["9999999998"], @s.fetch) 1024 | assert_equal(["9999999999"], @s.fetch) 1025 | assert_equal(["0"], @s.fetch) 1026 | assert_equal(["0"], @s.fetch) 1027 | assert_equal(["9999999999"], @s.fetch) 1028 | assert_equal(["0"], @s.fetch) 1029 | end 1030 | end 1031 | 1032 | def test_fetch_date() 1033 | if @m.server_version >= 40100 then 1034 | @m.query("create temporary table t (i date)") 1035 | @m.query("insert into t values ('0000-00-00'),('1000-01-01'),('9999-12-31')") 1036 | @s.prepare("select i from t") 1037 | @s.execute 1038 | assert_equal([Mysql::Time.new(0,0,0)], @s.fetch) 1039 | assert_equal([Mysql::Time.new(1000,1,1)], @s.fetch) 1040 | assert_equal([Mysql::Time.new(9999,12,31)], @s.fetch) 1041 | end 1042 | end 1043 | 1044 | def test_fetch_datetime() 1045 | if @m.server_version >= 40100 then 1046 | @m.query("create temporary table t (i datetime)") 1047 | @m.query("insert into t values ('0000-00-00 00:00:00'),('1000-01-01 00:00:00'),('9999-12-31 23:59:59')") 1048 | @s.prepare("select i from t") 1049 | @s.execute 1050 | assert_equal([Mysql::Time.new(0,0,0,0,0,0)], @s.fetch) 1051 | assert_equal([Mysql::Time.new(1000,1,1,0,0,0)], @s.fetch) 1052 | assert_equal([Mysql::Time.new(9999,12,31,23,59,59)], @s.fetch) 1053 | end 1054 | end 1055 | 1056 | def test_fetch_timestamp() 1057 | if @m.server_version >= 40100 then 1058 | @m.query("create temporary table t (i timestamp)") 1059 | @m.query("insert into t values ('1970-01-02 00:00:00'),('2037-12-30 23:59:59')") 1060 | @s.prepare("select i from t") 1061 | @s.execute 1062 | assert_equal([Mysql::Time.new(1970,1,2,0,0,0)], @s.fetch) 1063 | assert_equal([Mysql::Time.new(2037,12,30,23,59,59)], @s.fetch) 1064 | end 1065 | end 1066 | 1067 | def test_fetch_time() 1068 | if @m.server_version >= 40100 then 1069 | @m.query("create temporary table t (i time)") 1070 | @m.query("insert into t values ('-838:59:59'),(0),('838:59:59')") 1071 | @s.prepare("select i from t") 1072 | @s.execute 1073 | assert_equal([Mysql::Time.new(0,0,0,838,59,59,true)], @s.fetch) 1074 | assert_equal([Mysql::Time.new(0,0,0,0,0,0,false)], @s.fetch) 1075 | assert_equal([Mysql::Time.new(0,0,0,838,59,59,false)], @s.fetch) 1076 | end 1077 | end 1078 | 1079 | def test_fetch_year() 1080 | if @m.server_version >= 40100 then 1081 | @m.query("create temporary table t (i year)") 1082 | @m.query("insert into t values (0),(70),(69),(1901),(2155)") 1083 | @s.prepare("select i from t") 1084 | @s.execute 1085 | assert_equal([0], @s.fetch) 1086 | assert_equal([1970], @s.fetch) 1087 | assert_equal([2069], @s.fetch) 1088 | assert_equal([1901], @s.fetch) 1089 | assert_equal([2155], @s.fetch) 1090 | end 1091 | end 1092 | 1093 | def test_fetch_char() 1094 | if @m.server_version >= 40100 then 1095 | @m.query("create temporary table t (i char(10))") 1096 | @m.query("insert into t values (null),('abc')") 1097 | @s.prepare("select i from t") 1098 | @s.execute 1099 | assert_equal([nil], @s.fetch) 1100 | assert_equal(["abc"], @s.fetch) 1101 | end 1102 | end 1103 | 1104 | def test_fetch_varchar() 1105 | if @m.server_version >= 40100 then 1106 | @m.query("create temporary table t (i varchar(10))") 1107 | @m.query("insert into t values (null),('abc')") 1108 | @s.prepare("select i from t") 1109 | @s.execute 1110 | assert_equal([nil], @s.fetch) 1111 | assert_equal(["abc"], @s.fetch) 1112 | end 1113 | end 1114 | 1115 | def test_fetch_binary() 1116 | if @m.server_version >= 40100 then 1117 | @m.query("create temporary table t (i binary(10))") 1118 | @m.query("insert into t values (null),('abc')") 1119 | @s.prepare("select i from t") 1120 | @s.execute 1121 | assert_equal([nil], @s.fetch) 1122 | if @m.server_version >= 50000 then 1123 | assert_equal(["abc\0\0\0\0\0\0\0"], @s.fetch) 1124 | else 1125 | assert_equal(["abc"], @s.fetch) 1126 | end 1127 | end 1128 | end 1129 | 1130 | def test_fetch_varbinary() 1131 | if @m.server_version >= 40100 then 1132 | @m.query("create temporary table t (i varbinary(10))") 1133 | @m.query("insert into t values (null),('abc')") 1134 | @s.prepare("select i from t") 1135 | @s.execute 1136 | assert_equal([nil], @s.fetch) 1137 | assert_equal(["abc"], @s.fetch) 1138 | end 1139 | end 1140 | 1141 | def test_fetch_tinyblob() 1142 | if @m.server_version >= 40100 then 1143 | @m.query("create temporary table t (i tinyblob)") 1144 | @m.query("insert into t values (null),('abc')") 1145 | @s.prepare("select i from t") 1146 | @s.execute 1147 | assert_equal([nil], @s.fetch) 1148 | assert_equal(["abc"], @s.fetch) 1149 | end 1150 | end 1151 | 1152 | def test_fetch_tinytext() 1153 | if @m.server_version >= 40100 then 1154 | @m.query("create temporary table t (i tinytext)") 1155 | @m.query("insert into t values (null),('abc')") 1156 | @s.prepare("select i from t") 1157 | @s.execute 1158 | assert_equal([nil], @s.fetch) 1159 | assert_equal(["abc"], @s.fetch) 1160 | end 1161 | end 1162 | 1163 | def test_fetch_blob() 1164 | if @m.server_version >= 40100 then 1165 | @m.query("create temporary table t (i blob)") 1166 | @m.query("insert into t values (null),('abc')") 1167 | @s.prepare("select i from t") 1168 | @s.execute 1169 | assert_equal([nil], @s.fetch) 1170 | assert_equal(["abc"], @s.fetch) 1171 | end 1172 | end 1173 | 1174 | def test_fetch_text() 1175 | if @m.server_version >= 40100 then 1176 | @m.query("create temporary table t (i text)") 1177 | @m.query("insert into t values (null),('abc')") 1178 | @s.prepare("select i from t") 1179 | @s.execute 1180 | assert_equal([nil], @s.fetch) 1181 | assert_equal(["abc"], @s.fetch) 1182 | end 1183 | end 1184 | 1185 | def test_fetch_mediumblob() 1186 | if @m.server_version >= 40100 then 1187 | @m.query("create temporary table t (i mediumblob)") 1188 | @m.query("insert into t values (null),('abc')") 1189 | @s.prepare("select i from t") 1190 | @s.execute 1191 | assert_equal([nil], @s.fetch) 1192 | assert_equal(["abc"], @s.fetch) 1193 | end 1194 | end 1195 | 1196 | def test_fetch_mediumtext() 1197 | if @m.server_version >= 40100 then 1198 | @m.query("create temporary table t (i mediumtext)") 1199 | @m.query("insert into t values (null),('abc')") 1200 | @s.prepare("select i from t") 1201 | @s.execute 1202 | assert_equal([nil], @s.fetch) 1203 | assert_equal(["abc"], @s.fetch) 1204 | end 1205 | end 1206 | 1207 | def test_fetch_longblob() 1208 | if @m.server_version >= 40100 then 1209 | @m.query("create temporary table t (i longblob)") 1210 | @m.query("insert into t values (null),('abc')") 1211 | @s.prepare("select i from t") 1212 | @s.execute 1213 | assert_equal([nil], @s.fetch) 1214 | assert_equal(["abc"], @s.fetch) 1215 | end 1216 | end 1217 | 1218 | def test_fetch_longtext() 1219 | if @m.server_version >= 40100 then 1220 | @m.query("create temporary table t (i longtext)") 1221 | @m.query("insert into t values (null),('abc')") 1222 | @s.prepare("select i from t") 1223 | @s.execute 1224 | assert_equal([nil], @s.fetch) 1225 | assert_equal(["abc"], @s.fetch) 1226 | end 1227 | end 1228 | 1229 | def test_fetch_enum() 1230 | if @m.server_version >= 40100 then 1231 | @m.query("create temporary table t (i enum('abc','def'))") 1232 | @m.query("insert into t values (null),(0),(1),(2),('abc'),('def'),('ghi')") 1233 | @s.prepare("select i from t") 1234 | @s.execute 1235 | assert_equal([nil], @s.fetch) 1236 | assert_equal([""], @s.fetch) 1237 | assert_equal(["abc"], @s.fetch) 1238 | assert_equal(["def"], @s.fetch) 1239 | assert_equal(["abc"], @s.fetch) 1240 | assert_equal(["def"], @s.fetch) 1241 | assert_equal([""], @s.fetch) 1242 | end 1243 | end 1244 | 1245 | def test_fetch_set() 1246 | if @m.server_version >= 40100 then 1247 | @m.query("create temporary table t (i set('abc','def'))") 1248 | @m.query("insert into t values (null),(0),(1),(2),(3),('abc'),('def'),('abc,def'),('ghi')") 1249 | @s.prepare("select i from t") 1250 | @s.execute 1251 | assert_equal([nil], @s.fetch) 1252 | assert_equal([""], @s.fetch) 1253 | assert_equal(["abc"], @s.fetch) 1254 | assert_equal(["def"], @s.fetch) 1255 | assert_equal(["abc,def"], @s.fetch) 1256 | assert_equal(["abc"], @s.fetch) 1257 | assert_equal(["def"], @s.fetch) 1258 | assert_equal(["abc,def"], @s.fetch) 1259 | assert_equal([""], @s.fetch) 1260 | end 1261 | end 1262 | 1263 | def test_each() 1264 | if @m.server_version >= 40100 then 1265 | @m.query("create temporary table t (i int, c char(255), d datetime)") 1266 | @m.query("insert into t values (1,'abc','19701224235905'),(2,'def','21120903123456'),(3,'123',null)") 1267 | @s.prepare("select * from t") 1268 | @s.execute 1269 | c = 0 1270 | @s.each do |a| 1271 | case c 1272 | when 0 1273 | assert_equal([1,"abc",Mysql::Time.new(1970,12,24,23,59,05)], a) 1274 | when 1 1275 | assert_equal([2,"def",Mysql::Time.new(2112,9,3,12,34,56)], a) 1276 | when 2 1277 | assert_equal([3,"123",nil], a) 1278 | else 1279 | raise 1280 | end 1281 | c += 1 1282 | end 1283 | end 1284 | end 1285 | 1286 | def test_field_count() 1287 | if @m.server_version >= 40100 then 1288 | @s.prepare("select 1,2,3") 1289 | @s.execute() 1290 | assert_equal(3, @s.field_count()) 1291 | @s.prepare("set @a=1") 1292 | @s.execute() 1293 | assert_equal(0, @s.field_count()) 1294 | end 1295 | end 1296 | 1297 | def test_free_result() 1298 | if @m.server_version >= 40100 then 1299 | @s.free_result() 1300 | @s.prepare("select 1,2,3") 1301 | @s.execute() 1302 | @s.free_result() 1303 | end 1304 | end 1305 | 1306 | def test_insert_id() 1307 | if @m.server_version >= 40100 then 1308 | @m.query("create temporary table t (i bigint auto_increment, unique(i))") 1309 | @s.prepare("insert into t values (?)") 1310 | @s.execute(0) 1311 | assert_equal(1, @s.insert_id()) 1312 | @s.execute(0) 1313 | assert_equal(2, @s.insert_id()) 1314 | @s.execute(2**32) 1315 | assert_equal(2**32, @s.insert_id()) 1316 | @s.execute(0) 1317 | assert_equal(2**32+1, @s.insert_id()) 1318 | end 1319 | end 1320 | 1321 | def test_num_rows() 1322 | if @m.server_version >= 40100 then 1323 | @m.query("create temporary table t (i int)") 1324 | @m.query("insert into t values (1),(2),(3),(4)") 1325 | @s.prepare("select * from t") 1326 | @s.execute 1327 | assert_equal(4, @s.num_rows()) 1328 | end 1329 | end 1330 | 1331 | def test_param_count() 1332 | if @m.server_version >= 40100 then 1333 | @m.query("create temporary table t (a int, b int, c int)") 1334 | @s.prepare("select * from t") 1335 | assert_equal(0, @s.param_count()) 1336 | @s.prepare("insert into t values (?,?,?)") 1337 | assert_equal(3, @s.param_count()) 1338 | end 1339 | end 1340 | 1341 | =begin 1342 | def test_param_metadata() 1343 | @s.param_metadata() 1344 | end 1345 | =end 1346 | 1347 | def test_prepare() 1348 | if @m.server_version >= 40100 then 1349 | @s.prepare("select 1") 1350 | assert_raises(Mysql::Error){@s.prepare("invalid syntax")} 1351 | end 1352 | end 1353 | 1354 | =begin 1355 | def test_reset() 1356 | @s.reset() 1357 | end 1358 | =end 1359 | 1360 | def test_result_metadata() 1361 | if @m.server_version >= 40100 then 1362 | @s.prepare("select 1 foo, 2 bar") 1363 | res = @s.result_metadata() 1364 | f = res.fetch_fields 1365 | assert_equal("foo", f[0].name) 1366 | assert_equal("bar", f[1].name) 1367 | end 1368 | end 1369 | 1370 | def test_result_metadata_nodata() 1371 | if @m.server_version >= 40100 then 1372 | @m.query("create temporary table t (i int)") 1373 | @s.prepare("insert into t values (1)") 1374 | assert_equal(nil, @s.result_metadata()) 1375 | end 1376 | end 1377 | 1378 | def test_row_seek_tell() 1379 | if @m.server_version >= 40100 then 1380 | @m.query("create temporary table t (i int)") 1381 | @m.query("insert into t values (0),(1),(2),(3),(4)") 1382 | @s.prepare("select * from t") 1383 | @s.execute 1384 | row0 = @s.row_tell 1385 | assert_equal([0], @s.fetch) 1386 | assert_equal([1], @s.fetch) 1387 | row2 = @s.row_seek(row0) 1388 | assert_equal([0], @s.fetch) 1389 | @s.row_seek(row2) 1390 | assert_equal([2], @s.fetch) 1391 | end 1392 | end 1393 | 1394 | =begin 1395 | def test_send_long_data() 1396 | @m.query("create temporary table t (i int, t text)") 1397 | @s.prepare("insert into t values (?,?)") 1398 | @s.send_long_data(1, "long long data ") 1399 | @s.send_long_data(1, "long long data2") 1400 | assert_raises(Mysql::Error){@s.send_long_data(9, "invalid param number")} 1401 | @s.execute(99, "hoge") 1402 | assert_equal("long long data long long data2", @m.query("select t from t").fetch_row[0]) 1403 | end 1404 | =end 1405 | 1406 | def test_sqlstate() 1407 | if @m.server_version >= 40100 then 1408 | @s.prepare("select 1") 1409 | if @m.client_version >= 50000 then 1410 | assert_equal("00000", @s.sqlstate) 1411 | else 1412 | assert_equal("", @s.sqlstate) 1413 | end 1414 | assert_raises(Mysql::Error){@s.prepare("hogehoge")} 1415 | assert_equal("42000", @s.sqlstate) 1416 | end 1417 | end 1418 | 1419 | =begin 1420 | def test_store_result() 1421 | @s.store_result() 1422 | end 1423 | =end 1424 | 1425 | end if Mysql.client_version >= 40100 1426 | 1427 | class TC_MysqlTime < Test::Unit::TestCase 1428 | def setup() 1429 | end 1430 | def teardown() 1431 | end 1432 | 1433 | def test_init() 1434 | t = Mysql::Time.new 1435 | assert_equal(0, t.year); 1436 | assert_equal(0, t.month); 1437 | assert_equal(0, t.day); 1438 | assert_equal(0, t.hour); 1439 | assert_equal(0, t.minute); 1440 | assert_equal(0, t.second); 1441 | assert_equal(false, t.neg); 1442 | assert_equal(0, t.second_part); 1443 | end 1444 | 1445 | def test_year() 1446 | t = Mysql::Time.new 1447 | assert_equal(2005, t.year = 2005) 1448 | assert_equal(2005, t.year) 1449 | end 1450 | 1451 | def test_month() 1452 | t = Mysql::Time.new 1453 | assert_equal(11, t.month = 11) 1454 | assert_equal(11, t.month) 1455 | end 1456 | 1457 | def test_day() 1458 | t = Mysql::Time.new 1459 | assert_equal(23, t.day = 23) 1460 | assert_equal(23, t.day) 1461 | end 1462 | 1463 | def test_hour() 1464 | t = Mysql::Time.new 1465 | assert_equal(15, t.hour = 15) 1466 | assert_equal(15, t.hour) 1467 | end 1468 | 1469 | def test_minute() 1470 | t = Mysql::Time.new 1471 | assert_equal(58, t.month = 58) 1472 | assert_equal(58, t.month) 1473 | end 1474 | 1475 | def test_second() 1476 | t = Mysql::Time.new 1477 | assert_equal(34, t.second = 34) 1478 | assert_equal(34, t.second) 1479 | end 1480 | 1481 | def test_tos() 1482 | t = Mysql::Time.new(2005, 7, 19, 10, 15, 49) 1483 | assert_equal("2005-07-19 10:15:49", t.to_s) 1484 | end 1485 | 1486 | def test_eql() 1487 | t1 = Mysql::Time.new(2005,7,19,23,56,13) 1488 | t2 = Mysql::Time.new(2005,7,19,23,56,13) 1489 | assert_equal(t1, t2) 1490 | end 1491 | 1492 | end if Mysql.client_version >= 40100 1493 | -------------------------------------------------------------------------------- /ext/mysql_api/mysql.c: -------------------------------------------------------------------------------- 1 | /* ruby mysql module 2 | * $Id: mysql.c 250 2010-02-11 10:42:54Z tommy $ 3 | */ 4 | 5 | #include 6 | #ifndef RSTRING_PTR 7 | #define RSTRING_PTR(str) RSTRING(str)->ptr 8 | #endif 9 | #ifndef RSTRING_LEN 10 | #define RSTRING_LEN(str) RSTRING(str)->len 11 | #endif 12 | #ifndef RARRAY_PTR 13 | #define RARRAY_PTR(ary) RARRAY(ary)->ptr 14 | #endif 15 | #ifndef HAVE_RB_STR_SET_LEN 16 | #define rb_str_set_len(str, length) (RSTRING_LEN(str) = (length)) 17 | #endif 18 | 19 | #ifdef HAVE_MYSQL_H 20 | #include 21 | #include 22 | #include 23 | #else 24 | #include 25 | #include 26 | #include 27 | #endif 28 | 29 | #define MYSQL_RUBY_VERSION 20802 30 | 31 | #define GC_STORE_RESULT_LIMIT 20 32 | 33 | #if MYSQL_VERSION_ID < 32224 34 | #define mysql_field_count mysql_num_fields 35 | #endif 36 | 37 | #define NILorSTRING(obj) (NIL_P(obj)? NULL: StringValuePtr(obj)) 38 | #define NILorINT(obj) (NIL_P(obj)? 0: NUM2INT(obj)) 39 | 40 | #define GetMysqlStruct(obj) (Check_Type(obj, T_DATA), (struct mysql*)DATA_PTR(obj)) 41 | #define GetHandler(obj) (Check_Type(obj, T_DATA), &(((struct mysql*)DATA_PTR(obj))->handler)) 42 | #define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res) 43 | #define GetMysqlStmt(obj) (Check_Type(obj, T_DATA), ((struct mysql_stmt*)DATA_PTR(obj))->stmt) 44 | 45 | VALUE cMysql; 46 | VALUE cMysqlRes; 47 | VALUE cMysqlField; 48 | VALUE cMysqlStmt; 49 | VALUE cMysqlRowOffset; 50 | VALUE cMysqlTime; 51 | VALUE eMysql; 52 | 53 | static int store_result_count = 0; 54 | 55 | struct mysql { 56 | MYSQL handler; 57 | char connection; 58 | char query_with_result; 59 | }; 60 | 61 | struct mysql_res { 62 | MYSQL_RES* res; 63 | char freed; 64 | }; 65 | 66 | #if MYSQL_VERSION_ID >= 40101 67 | struct mysql_stmt { 68 | MYSQL_STMT *stmt; 69 | char closed; 70 | struct { 71 | int n; 72 | MYSQL_BIND *bind; 73 | unsigned long *length; 74 | MYSQL_TIME *buffer; 75 | } param; 76 | struct { 77 | int n; 78 | MYSQL_BIND *bind; 79 | my_bool *is_null; 80 | unsigned long *length; 81 | } result; 82 | MYSQL_RES *res; 83 | }; 84 | #endif 85 | 86 | /* free Mysql class object */ 87 | static void free_mysql(struct mysql* my) 88 | { 89 | if (my->connection == Qtrue) 90 | mysql_close(&my->handler); 91 | xfree(my); 92 | } 93 | 94 | static void free_mysqlres(struct mysql_res* resp) 95 | { 96 | if (resp->freed == Qfalse) { 97 | mysql_free_result(resp->res); 98 | store_result_count--; 99 | } 100 | xfree(resp); 101 | } 102 | 103 | #if MYSQL_VERSION_ID >= 40101 104 | static void free_mysqlstmt_memory(struct mysql_stmt *s) 105 | { 106 | if (s->param.bind) { 107 | xfree(s->param.bind); 108 | s->param.bind = NULL; 109 | } 110 | if (s->param.length) { 111 | xfree(s->param.length); 112 | s->param.length = NULL; 113 | } 114 | if (s->param.buffer) { 115 | xfree(s->param.buffer); 116 | s->param.buffer = NULL; 117 | } 118 | s->param.n = 0; 119 | if (s->res) { 120 | mysql_free_result(s->res); 121 | s->res = NULL; 122 | } 123 | if (s->result.bind) { 124 | int i; 125 | for (i = 0; i < s->result.n; i++) { 126 | if (s->result.bind[i].buffer) 127 | xfree(s->result.bind[i].buffer); 128 | s->result.bind[i].buffer = NULL; 129 | } 130 | xfree(s->result.bind); 131 | s->result.bind = NULL; 132 | } 133 | if (s->result.is_null) { 134 | xfree(s->result.is_null); 135 | s->result.is_null = NULL; 136 | } 137 | if (s->result.length) { 138 | xfree(s->result.length); 139 | s->result.length = NULL; 140 | } 141 | s->result.n = 0; 142 | } 143 | 144 | static void free_execute_memory(struct mysql_stmt *s) 145 | { 146 | if (s->res && s->result.bind) { 147 | int i; 148 | for (i = 0; i < s->result.n; i++) { 149 | if (s->result.bind[i].buffer) 150 | xfree(s->result.bind[i].buffer); 151 | s->result.bind[i].buffer = NULL; 152 | } 153 | } 154 | mysql_stmt_free_result(s->stmt); 155 | } 156 | 157 | static void free_mysqlstmt(struct mysql_stmt* s) 158 | { 159 | free_mysqlstmt_memory(s); 160 | if (s->closed == Qfalse) 161 | mysql_stmt_close(s->stmt); 162 | if (s->res) 163 | mysql_free_result(s->res); 164 | xfree(s); 165 | } 166 | #endif 167 | 168 | static void mysql_raise(MYSQL* m) 169 | { 170 | VALUE e = rb_exc_new2(eMysql, mysql_error(m)); 171 | rb_iv_set(e, "errno", INT2FIX(mysql_errno(m))); 172 | #if MYSQL_VERSION_ID >= 40101 173 | rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_sqlstate(m))); 174 | #endif 175 | rb_exc_raise(e); 176 | } 177 | 178 | static VALUE mysqlres2obj(MYSQL_RES* res) 179 | { 180 | VALUE obj; 181 | struct mysql_res* resp; 182 | obj = Data_Make_Struct(cMysqlRes, struct mysql_res, 0, free_mysqlres, resp); 183 | rb_iv_set(obj, "colname", Qnil); 184 | rb_iv_set(obj, "tblcolname", Qnil); 185 | resp->res = res; 186 | resp->freed = Qfalse; 187 | rb_obj_call_init(obj, 0, NULL); 188 | if (++store_result_count > GC_STORE_RESULT_LIMIT) 189 | rb_gc(); 190 | return obj; 191 | } 192 | 193 | /* make Mysql::Field object */ 194 | static VALUE make_field_obj(MYSQL_FIELD* f) 195 | { 196 | VALUE obj; 197 | if (f == NULL) 198 | return Qnil; 199 | obj = rb_obj_alloc(cMysqlField); 200 | rb_iv_set(obj, "name", f->name? rb_str_freeze(rb_tainted_str_new2(f->name)): Qnil); 201 | rb_iv_set(obj, "table", f->table? rb_str_freeze(rb_tainted_str_new2(f->table)): Qnil); 202 | rb_iv_set(obj, "def", f->def? rb_str_freeze(rb_tainted_str_new2(f->def)): Qnil); 203 | rb_iv_set(obj, "type", INT2NUM(f->type)); 204 | rb_iv_set(obj, "length", INT2NUM(f->length)); 205 | rb_iv_set(obj, "max_length", INT2NUM(f->max_length)); 206 | rb_iv_set(obj, "flags", INT2NUM(f->flags)); 207 | rb_iv_set(obj, "decimals", INT2NUM(f->decimals)); 208 | return obj; 209 | } 210 | 211 | /*------------------------------- 212 | * Mysql class method 213 | */ 214 | 215 | /* init() */ 216 | static VALUE init(VALUE klass) 217 | { 218 | struct mysql* myp; 219 | VALUE obj; 220 | 221 | obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp); 222 | mysql_init(&myp->handler); 223 | myp->connection = Qfalse; 224 | myp->query_with_result = Qtrue; 225 | rb_obj_call_init(obj, 0, NULL); 226 | return obj; 227 | } 228 | 229 | /* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */ 230 | static VALUE real_connect(int argc, VALUE* argv, VALUE klass) 231 | { 232 | VALUE host, user, passwd, db, port, sock, flag; 233 | char *h, *u, *p, *d, *s; 234 | unsigned int pp, f; 235 | struct mysql* myp; 236 | VALUE obj; 237 | 238 | #if MYSQL_VERSION_ID >= 32200 239 | rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag); 240 | d = NILorSTRING(db); 241 | f = NILorINT(flag); 242 | #elif MYSQL_VERSION_ID >= 32115 243 | rb_scan_args(argc, argv, "06", &host, &user, &passwd, &port, &sock, &flag); 244 | f = NILorINT(flag); 245 | #else 246 | rb_scan_args(argc, argv, "05", &host, &user, &passwd, &port, &sock); 247 | #endif 248 | h = NILorSTRING(host); 249 | u = NILorSTRING(user); 250 | p = NILorSTRING(passwd); 251 | pp = NILorINT(port); 252 | s = NILorSTRING(sock); 253 | 254 | #ifdef HAVE_RB_THREAD_START_TIMER 255 | rb_thread_stop_timer(); 256 | #endif 257 | obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp); 258 | #if MYSQL_VERSION_ID >= 32200 259 | mysql_init(&myp->handler); 260 | if (mysql_real_connect(&myp->handler, h, u, p, d, pp, s, f) == NULL) 261 | #elif MYSQL_VERSION_ID >= 32115 262 | if (mysql_real_connect(&myp->handler, h, u, p, pp, s, f) == NULL) 263 | #else 264 | if (mysql_real_connect(&myp->handler, h, u, p, pp, s) == NULL) 265 | #endif 266 | { 267 | #ifdef HAVE_RB_THREAD_START_TIMER 268 | rb_thread_start_timer(); 269 | #endif 270 | mysql_raise(&myp->handler); 271 | } 272 | #ifdef HAVE_RB_THREAD_START_TIMER 273 | rb_thread_start_timer(); 274 | #endif 275 | 276 | myp->handler.reconnect = 0; 277 | myp->connection = Qtrue; 278 | myp->query_with_result = Qtrue; 279 | rb_obj_call_init(obj, argc, argv); 280 | 281 | return obj; 282 | } 283 | 284 | /* escape_string(string) */ 285 | static VALUE escape_string(VALUE klass, VALUE str) 286 | { 287 | VALUE ret; 288 | Check_Type(str, T_STRING); 289 | ret = rb_str_new(0, (RSTRING_LEN(str))*2+1); 290 | rb_str_set_len(ret, mysql_escape_string(RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str))); 291 | return ret; 292 | } 293 | 294 | /* client_info() */ 295 | static VALUE client_info(VALUE klass) 296 | { 297 | return rb_tainted_str_new2(mysql_get_client_info()); 298 | } 299 | 300 | #if MYSQL_VERSION_ID >= 32332 301 | /* my_debug(string) */ 302 | static VALUE my_debug(VALUE obj, VALUE str) 303 | { 304 | mysql_debug(StringValuePtr(str)); 305 | return obj; 306 | } 307 | #endif 308 | 309 | #if MYSQL_VERSION_ID >= 40000 310 | /* client_version() */ 311 | static VALUE client_version(VALUE obj) 312 | { 313 | return INT2NUM(mysql_get_client_version()); 314 | } 315 | #endif 316 | 317 | /*------------------------------- 318 | * Mysql object method 319 | */ 320 | 321 | #if MYSQL_VERSION_ID >= 32200 322 | /* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */ 323 | static VALUE real_connect2(int argc, VALUE* argv, VALUE obj) 324 | { 325 | VALUE host, user, passwd, db, port, sock, flag; 326 | char *h, *u, *p, *d, *s; 327 | unsigned int pp, f; 328 | MYSQL* m = GetHandler(obj); 329 | rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag); 330 | d = NILorSTRING(db); 331 | f = NILorINT(flag); 332 | h = NILorSTRING(host); 333 | u = NILorSTRING(user); 334 | p = NILorSTRING(passwd); 335 | pp = NILorINT(port); 336 | s = NILorSTRING(sock); 337 | 338 | #ifdef HAVE_RB_THREAD_START_TIMER 339 | rb_thread_stop_timer(); 340 | #endif 341 | if (mysql_real_connect(m, h, u, p, d, pp, s, f) == NULL) { 342 | #ifdef HAVE_RB_THREAD_START_TIMER 343 | rb_thread_start_timer(); 344 | #endif 345 | mysql_raise(m); 346 | } 347 | #ifdef HAVE_RB_THREAD_START_TIMER 348 | rb_thread_start_timer(); 349 | #endif 350 | m->reconnect = 0; 351 | GetMysqlStruct(obj)->connection = Qtrue; 352 | 353 | return obj; 354 | } 355 | 356 | /* options(opt, value=nil) */ 357 | static VALUE options(int argc, VALUE* argv, VALUE obj) 358 | { 359 | VALUE opt, val; 360 | int n; 361 | my_bool b; 362 | char* v; 363 | MYSQL* m = GetHandler(obj); 364 | 365 | rb_scan_args(argc, argv, "11", &opt, &val); 366 | switch(NUM2INT(opt)) { 367 | case MYSQL_OPT_CONNECT_TIMEOUT: 368 | #if MYSQL_VERSION_ID >= 40100 369 | case MYSQL_OPT_PROTOCOL: 370 | #endif 371 | #if MYSQL_VERSION_ID >= 40101 372 | case MYSQL_OPT_READ_TIMEOUT: 373 | case MYSQL_OPT_WRITE_TIMEOUT: 374 | #endif 375 | if (val == Qnil) 376 | rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)"); 377 | n = NUM2INT(val); 378 | v = (char*)&n; 379 | break; 380 | case MYSQL_INIT_COMMAND: 381 | case MYSQL_READ_DEFAULT_FILE: 382 | case MYSQL_READ_DEFAULT_GROUP: 383 | #if MYSQL_VERSION_ID >= 32349 384 | case MYSQL_SET_CHARSET_DIR: 385 | case MYSQL_SET_CHARSET_NAME: 386 | #endif 387 | #if MYSQL_VERSION_ID >= 40100 388 | case MYSQL_SHARED_MEMORY_BASE_NAME: 389 | #endif 390 | #if MYSQL_VERSION_ID >= 40101 391 | case MYSQL_SET_CLIENT_IP: 392 | #endif 393 | if (val == Qnil) 394 | rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)"); 395 | v = StringValuePtr(val); 396 | break; 397 | #if MYSQL_VERSION_ID >= 40101 398 | case MYSQL_SECURE_AUTH: 399 | if (val == Qnil || val == Qfalse) 400 | b = 1; 401 | else 402 | b = 0; 403 | v = (char*)&b; 404 | break; 405 | #endif 406 | #if MYSQL_VERSION_ID >= 32349 407 | case MYSQL_OPT_LOCAL_INFILE: 408 | if (val == Qnil || val == Qfalse) 409 | v = NULL; 410 | else { 411 | n = 1; 412 | v = (char*)&n; 413 | } 414 | break; 415 | #endif 416 | default: 417 | v = NULL; 418 | } 419 | 420 | if (mysql_options(m, NUM2INT(opt), v) != 0) 421 | rb_raise(eMysql, "unknown option: %d", NUM2INT(opt)); 422 | return obj; 423 | } 424 | #endif 425 | 426 | #if MYSQL_VERSION_ID >= 32332 427 | /* real_escape_string(string) */ 428 | static VALUE real_escape_string(VALUE obj, VALUE str) 429 | { 430 | MYSQL* m = GetHandler(obj); 431 | VALUE ret; 432 | Check_Type(str, T_STRING); 433 | ret = rb_str_new(0, (RSTRING_LEN(str))*2+1); 434 | rb_str_set_len(ret, mysql_real_escape_string(m, RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str))); 435 | return ret; 436 | } 437 | #endif 438 | 439 | /* initialize() */ 440 | static VALUE initialize(int argc, VALUE* argv, VALUE obj) 441 | { 442 | return obj; 443 | } 444 | 445 | /* affected_rows() */ 446 | static VALUE affected_rows(VALUE obj) 447 | { 448 | return ULL2NUM(mysql_affected_rows(GetHandler(obj))); 449 | } 450 | 451 | #if MYSQL_VERSION_ID >= 32303 452 | /* change_user(user=nil, passwd=nil, db=nil) */ 453 | static VALUE change_user(int argc, VALUE* argv, VALUE obj) 454 | { 455 | VALUE user, passwd, db; 456 | char *u, *p, *d; 457 | MYSQL* m = GetHandler(obj); 458 | rb_scan_args(argc, argv, "03", &user, &passwd, &db); 459 | u = NILorSTRING(user); 460 | p = NILorSTRING(passwd); 461 | d = NILorSTRING(db); 462 | if (mysql_change_user(m, u, p, d) != 0) 463 | mysql_raise(m); 464 | return obj; 465 | } 466 | #endif 467 | 468 | #if MYSQL_VERSION_ID >= 32321 469 | /* character_set_name() */ 470 | static VALUE character_set_name(VALUE obj) 471 | { 472 | return rb_tainted_str_new2(mysql_character_set_name(GetHandler(obj))); 473 | } 474 | #endif 475 | 476 | /* close() */ 477 | static VALUE my_close(VALUE obj) 478 | { 479 | MYSQL* m = GetHandler(obj); 480 | mysql_close(m); 481 | GetMysqlStruct(obj)->connection = Qfalse; 482 | return obj; 483 | } 484 | 485 | #if MYSQL_VERSION_ID < 40000 486 | /* create_db(db) */ 487 | static VALUE create_db(VALUE obj, VALUE db) 488 | { 489 | MYSQL* m = GetHandler(obj); 490 | if (mysql_create_db(m, StringValuePtr(db)) != 0) 491 | mysql_raise(m); 492 | return obj; 493 | } 494 | 495 | /* drop_db(db) */ 496 | static VALUE drop_db(VALUE obj, VALUE db) 497 | { 498 | MYSQL* m = GetHandler(obj); 499 | if (mysql_drop_db(m, StringValuePtr(db)) != 0) 500 | mysql_raise(m); 501 | return obj; 502 | } 503 | #endif 504 | 505 | #if MYSQL_VERSION_ID >= 32332 506 | /* dump_debug_info() */ 507 | static VALUE dump_debug_info(VALUE obj) 508 | { 509 | MYSQL* m = GetHandler(obj); 510 | if (mysql_dump_debug_info(m) != 0) 511 | mysql_raise(m); 512 | return obj; 513 | } 514 | #endif 515 | 516 | /* errno() */ 517 | static VALUE my_errno(VALUE obj) 518 | { 519 | return INT2NUM(mysql_errno(GetHandler(obj))); 520 | } 521 | 522 | /* error() */ 523 | static VALUE my_error(VALUE obj) 524 | { 525 | return rb_str_new2(mysql_error(GetHandler(obj))); 526 | } 527 | 528 | /* field_count() */ 529 | static VALUE field_count(VALUE obj) 530 | { 531 | return INT2NUM(mysql_field_count(GetHandler(obj))); 532 | } 533 | 534 | /* host_info() */ 535 | static VALUE host_info(VALUE obj) 536 | { 537 | return rb_tainted_str_new2(mysql_get_host_info(GetHandler(obj))); 538 | } 539 | 540 | /* proto_info() */ 541 | static VALUE proto_info(VALUE obj) 542 | { 543 | return INT2NUM(mysql_get_proto_info(GetHandler(obj))); 544 | } 545 | 546 | /* server_info() */ 547 | static VALUE server_info(VALUE obj) 548 | { 549 | return rb_tainted_str_new2(mysql_get_server_info(GetHandler(obj))); 550 | } 551 | 552 | /* info() */ 553 | static VALUE info(VALUE obj) 554 | { 555 | const char* p = mysql_info(GetHandler(obj)); 556 | return p? rb_tainted_str_new2(p): Qnil; 557 | } 558 | 559 | /* insert_id() */ 560 | static VALUE insert_id(VALUE obj) 561 | { 562 | return ULL2NUM(mysql_insert_id(GetHandler(obj))); 563 | } 564 | 565 | /* kill(pid) */ 566 | static VALUE my_kill(VALUE obj, VALUE pid) 567 | { 568 | int p = NUM2INT(pid); 569 | MYSQL* m = GetHandler(obj); 570 | if (mysql_kill(m, p) != 0) 571 | mysql_raise(m); 572 | return obj; 573 | } 574 | 575 | /* list_dbs(db=nil) */ 576 | static VALUE list_dbs(int argc, VALUE* argv, VALUE obj) 577 | { 578 | unsigned int i, n; 579 | VALUE db, ret; 580 | MYSQL* m = GetHandler(obj); 581 | MYSQL_RES* res; 582 | 583 | rb_scan_args(argc, argv, "01", &db); 584 | res = mysql_list_dbs(m, NILorSTRING(db)); 585 | if (res == NULL) 586 | mysql_raise(m); 587 | 588 | n = mysql_num_rows(res); 589 | ret = rb_ary_new2(n); 590 | for (i=0; i= 40103 685 | if (mysql_shutdown(m, NIL_P(level) ? SHUTDOWN_DEFAULT : NUM2INT(level)) != 0) 686 | #else 687 | if (mysql_shutdown(m) != 0) 688 | #endif 689 | mysql_raise(m); 690 | return obj; 691 | } 692 | 693 | /* stat() */ 694 | static VALUE my_stat(VALUE obj) 695 | { 696 | MYSQL* m = GetHandler(obj); 697 | const char* s = mysql_stat(m); 698 | if (s == NULL) 699 | mysql_raise(m); 700 | return rb_tainted_str_new2(s); 701 | } 702 | 703 | /* store_result() */ 704 | static VALUE store_result(VALUE obj) 705 | { 706 | MYSQL* m = GetHandler(obj); 707 | MYSQL_RES* res = mysql_store_result(m); 708 | if (res == NULL) 709 | mysql_raise(m); 710 | return mysqlres2obj(res); 711 | } 712 | 713 | /* thread_id() */ 714 | static VALUE thread_id(VALUE obj) 715 | { 716 | return INT2NUM(mysql_thread_id(GetHandler(obj))); 717 | } 718 | 719 | /* use_result() */ 720 | static VALUE use_result(VALUE obj) 721 | { 722 | MYSQL* m = GetHandler(obj); 723 | MYSQL_RES* res = mysql_use_result(m); 724 | if (res == NULL) 725 | mysql_raise(m); 726 | return mysqlres2obj(res); 727 | } 728 | 729 | static VALUE res_free(VALUE); 730 | /* query(sql) */ 731 | static VALUE query(VALUE obj, VALUE sql) 732 | { 733 | int loop = 0; 734 | VALUE e; 735 | MYSQL* m = GetHandler(obj); 736 | Check_Type(sql, T_STRING); 737 | if (GetMysqlStruct(obj)->connection == Qfalse) { 738 | e = rb_exc_new2(eMysql, "query: not connected"); 739 | rb_iv_set(e, "errno", Qnil); 740 | rb_exc_raise(e); 741 | } 742 | if (rb_block_given_p()) { 743 | if (mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0) 744 | mysql_raise(m); 745 | do { 746 | MYSQL_RES* res = mysql_store_result(m); 747 | if (res == NULL) { 748 | if (mysql_field_count(m) != 0) 749 | mysql_raise(m); 750 | } else { 751 | VALUE robj = mysqlres2obj(res); 752 | rb_ensure(rb_yield, robj, res_free, robj); 753 | } 754 | #if MYSQL_VERSION_ID >= 40101 755 | if ((loop = mysql_next_result(m)) > 0) 756 | mysql_raise(m); 757 | } while (loop == 0); 758 | #else 759 | } while (0); 760 | #endif 761 | return obj; 762 | } 763 | if (mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0) 764 | mysql_raise(m); 765 | if (GetMysqlStruct(obj)->query_with_result == Qfalse) 766 | return obj; 767 | if (mysql_field_count(m) == 0) 768 | return Qnil; 769 | return store_result(obj); 770 | } 771 | 772 | #if MYSQL_VERSION_ID >= 40100 773 | /* server_version() */ 774 | static VALUE server_version(VALUE obj) 775 | { 776 | return INT2NUM(mysql_get_server_version(GetHandler(obj))); 777 | } 778 | 779 | /* warning_count() */ 780 | static VALUE warning_count(VALUE obj) 781 | { 782 | return INT2NUM(mysql_warning_count(GetHandler(obj))); 783 | } 784 | 785 | /* commit() */ 786 | static VALUE commit(VALUE obj) 787 | { 788 | MYSQL* m = GetHandler(obj); 789 | if (mysql_commit(m) != 0) 790 | mysql_raise(m); 791 | return obj; 792 | } 793 | 794 | /* rollback() */ 795 | static VALUE rollback(VALUE obj) 796 | { 797 | MYSQL* m = GetHandler(obj); 798 | if (mysql_rollback(m) != 0) 799 | mysql_raise(m); 800 | return obj; 801 | } 802 | 803 | /* autocommit() */ 804 | static VALUE autocommit(VALUE obj, VALUE mode) 805 | { 806 | MYSQL* m = GetHandler(obj); 807 | int f; 808 | f = (mode == Qnil || mode == Qfalse || (rb_type(mode) == T_FIXNUM && NUM2INT(mode) == 0)) ? 0 : 1; 809 | if (mysql_autocommit(m, f) != 0) 810 | mysql_raise(m); 811 | return obj; 812 | } 813 | #endif 814 | 815 | #ifdef HAVE_MYSQL_SSL_SET 816 | /* ssl_set(key=nil, cert=nil, ca=nil, capath=nil, cipher=nil) */ 817 | static VALUE ssl_set(int argc, VALUE* argv, VALUE obj) 818 | { 819 | VALUE key, cert, ca, capath, cipher; 820 | char *s_key, *s_cert, *s_ca, *s_capath, *s_cipher; 821 | MYSQL* m = GetHandler(obj); 822 | rb_scan_args(argc, argv, "05", &key, &cert, &ca, &capath, &cipher); 823 | s_key = NILorSTRING(key); 824 | s_cert = NILorSTRING(cert); 825 | s_ca = NILorSTRING(ca); 826 | s_capath = NILorSTRING(capath); 827 | s_cipher = NILorSTRING(cipher); 828 | mysql_ssl_set(m, s_key, s_cert, s_ca, s_capath, s_cipher); 829 | return obj; 830 | } 831 | #endif 832 | 833 | #if MYSQL_VERSION_ID >= 40100 834 | /* more_results() */ 835 | static VALUE more_results(VALUE obj) 836 | { 837 | if (mysql_more_results(GetHandler(obj)) == 0) 838 | return Qfalse; 839 | else 840 | return Qtrue; 841 | } 842 | 843 | static VALUE next_result(VALUE obj) 844 | { 845 | MYSQL* m = GetHandler(obj); 846 | int ret; 847 | ret = mysql_next_result(m); 848 | if (ret > 0) 849 | mysql_raise(m); 850 | if (ret == 0) 851 | return Qtrue; 852 | return Qfalse; 853 | } 854 | #endif 855 | 856 | #if MYSQL_VERSION_ID >= 40101 857 | /* set_server_option(option) */ 858 | static VALUE set_server_option(VALUE obj, VALUE option) 859 | { 860 | MYSQL *m = GetHandler(obj); 861 | if (mysql_set_server_option(m, NUM2INT(option)) != 0) 862 | mysql_raise(m); 863 | return obj; 864 | } 865 | 866 | /* sqlstate() */ 867 | static VALUE sqlstate(VALUE obj) 868 | { 869 | MYSQL *m = GetHandler(obj); 870 | return rb_tainted_str_new2(mysql_sqlstate(m)); 871 | } 872 | #endif 873 | 874 | #if MYSQL_VERSION_ID >= 40102 875 | /* stmt_init() */ 876 | static VALUE stmt_init(VALUE obj) 877 | { 878 | MYSQL *m = GetHandler(obj); 879 | MYSQL_STMT *s; 880 | struct mysql_stmt* stmt; 881 | my_bool true = 1; 882 | VALUE st_obj; 883 | 884 | if ((s = mysql_stmt_init(m)) == NULL) 885 | mysql_raise(m); 886 | if (mysql_stmt_attr_set(s, STMT_ATTR_UPDATE_MAX_LENGTH, &true)) 887 | rb_raise(rb_eArgError, "mysql_stmt_attr_set() failed"); 888 | st_obj = Data_Make_Struct(cMysqlStmt, struct mysql_stmt, 0, free_mysqlstmt, stmt); 889 | memset(stmt, 0, sizeof(*stmt)); 890 | stmt->stmt = s; 891 | stmt->closed = Qfalse; 892 | return st_obj; 893 | } 894 | 895 | static VALUE stmt_prepare(VALUE obj, VALUE query); 896 | /* prepare(query) */ 897 | static VALUE prepare(VALUE obj, VALUE query) 898 | { 899 | VALUE st; 900 | st = stmt_init(obj); 901 | return stmt_prepare(st, query); 902 | } 903 | #endif 904 | 905 | /* query_with_result() */ 906 | static VALUE query_with_result(VALUE obj) 907 | { 908 | return GetMysqlStruct(obj)->query_with_result? Qtrue: Qfalse; 909 | } 910 | 911 | /* query_with_result=(flag) */ 912 | static VALUE query_with_result_set(VALUE obj, VALUE flag) 913 | { 914 | if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE) 915 | rb_raise(rb_eTypeError, "invalid type, required true or false."); 916 | GetMysqlStruct(obj)->query_with_result = flag; 917 | return flag; 918 | } 919 | 920 | /* reconnect() */ 921 | static VALUE reconnect(VALUE obj) 922 | { 923 | return GetHandler(obj)->reconnect ? Qtrue : Qfalse; 924 | } 925 | 926 | /* reconnect=(flag) */ 927 | static VALUE reconnect_set(VALUE obj, VALUE flag) 928 | { 929 | GetHandler(obj)->reconnect = (flag == Qnil || flag == Qfalse) ? 0 : 1; 930 | return flag; 931 | } 932 | 933 | /*------------------------------- 934 | * Mysql::Result object method 935 | */ 936 | 937 | /* check if already freed */ 938 | static void check_free(VALUE obj) 939 | { 940 | struct mysql_res* resp = DATA_PTR(obj); 941 | if (resp->freed == Qtrue) 942 | rb_raise(eMysql, "Mysql::Result object is already freed"); 943 | } 944 | 945 | /* data_seek(offset) */ 946 | static VALUE data_seek(VALUE obj, VALUE offset) 947 | { 948 | check_free(obj); 949 | mysql_data_seek(GetMysqlRes(obj), NUM2INT(offset)); 950 | return obj; 951 | } 952 | 953 | /* fetch_field() */ 954 | static VALUE fetch_field(VALUE obj) 955 | { 956 | check_free(obj); 957 | return make_field_obj(mysql_fetch_field(GetMysqlRes(obj))); 958 | } 959 | 960 | /* fetch_fields() */ 961 | static VALUE fetch_fields(VALUE obj) 962 | { 963 | MYSQL_RES* res; 964 | MYSQL_FIELD* f; 965 | unsigned int n; 966 | VALUE ret; 967 | unsigned int i; 968 | check_free(obj); 969 | res = GetMysqlRes(obj); 970 | f = mysql_fetch_fields(res); 971 | n = mysql_num_fields(res); 972 | ret = rb_ary_new2(n); 973 | for (i=0; i= max) 989 | rb_raise(eMysql, "%d: out of range (max: %d)", n, max-1); 990 | #if MYSQL_VERSION_ID >= 32226 991 | return make_field_obj(mysql_fetch_field_direct(res, n)); 992 | #else 993 | return make_field_obj(&mysql_fetch_field_direct(res, n)); 994 | #endif 995 | } 996 | 997 | /* fetch_lengths() */ 998 | static VALUE fetch_lengths(VALUE obj) 999 | { 1000 | MYSQL_RES* res; 1001 | unsigned int n; 1002 | unsigned long* lengths; 1003 | VALUE ary; 1004 | unsigned int i; 1005 | check_free(obj); 1006 | res = GetMysqlRes(obj); 1007 | n = mysql_num_fields(res); 1008 | lengths = mysql_fetch_lengths(res); 1009 | if (lengths == NULL) 1010 | return Qnil; 1011 | ary = rb_ary_new2(n); 1012 | for (i=0; ires); 1118 | resp->freed = Qtrue; 1119 | store_result_count--; 1120 | return Qnil; 1121 | } 1122 | 1123 | /* num_fields() */ 1124 | static VALUE num_fields(VALUE obj) 1125 | { 1126 | check_free(obj); 1127 | return INT2NUM(mysql_num_fields(GetMysqlRes(obj))); 1128 | } 1129 | 1130 | /* num_rows() */ 1131 | static VALUE num_rows(VALUE obj) 1132 | { 1133 | check_free(obj); 1134 | return INT2NUM(mysql_num_rows(GetMysqlRes(obj))); 1135 | } 1136 | 1137 | /* row_seek(offset) */ 1138 | static VALUE row_seek(VALUE obj, VALUE offset) 1139 | { 1140 | MYSQL_ROW_OFFSET prev_offset; 1141 | if (CLASS_OF(offset) != cMysqlRowOffset) 1142 | rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset)); 1143 | check_free(obj); 1144 | prev_offset = mysql_row_seek(GetMysqlRes(obj), DATA_PTR(offset)); 1145 | return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset); 1146 | } 1147 | 1148 | /* row_tell() */ 1149 | static VALUE row_tell(VALUE obj) 1150 | { 1151 | MYSQL_ROW_OFFSET offset; 1152 | check_free(obj); 1153 | offset = mysql_row_tell(GetMysqlRes(obj)); 1154 | return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset); 1155 | } 1156 | 1157 | /* each {...} */ 1158 | static VALUE each(VALUE obj) 1159 | { 1160 | VALUE row; 1161 | check_free(obj); 1162 | while ((row = fetch_row(obj)) != Qnil) 1163 | rb_yield(row); 1164 | return obj; 1165 | } 1166 | 1167 | /* each_hash(with_table=false) {...} */ 1168 | static VALUE each_hash(int argc, VALUE* argv, VALUE obj) 1169 | { 1170 | VALUE with_table; 1171 | VALUE hash; 1172 | check_free(obj); 1173 | rb_scan_args(argc, argv, "01", &with_table); 1174 | if (with_table == Qnil) 1175 | with_table = Qfalse; 1176 | while ((hash = fetch_hash2(obj, with_table)) != Qnil) 1177 | rb_yield(hash); 1178 | return obj; 1179 | } 1180 | 1181 | /*------------------------------- 1182 | * Mysql::Field object method 1183 | */ 1184 | 1185 | /* hash */ 1186 | static VALUE field_hash(VALUE obj) 1187 | { 1188 | VALUE h = rb_hash_new(); 1189 | rb_hash_aset(h, rb_str_new2("name"), rb_iv_get(obj, "name")); 1190 | rb_hash_aset(h, rb_str_new2("table"), rb_iv_get(obj, "table")); 1191 | rb_hash_aset(h, rb_str_new2("def"), rb_iv_get(obj, "def")); 1192 | rb_hash_aset(h, rb_str_new2("type"), rb_iv_get(obj, "type")); 1193 | rb_hash_aset(h, rb_str_new2("length"), rb_iv_get(obj, "length")); 1194 | rb_hash_aset(h, rb_str_new2("max_length"), rb_iv_get(obj, "max_length")); 1195 | rb_hash_aset(h, rb_str_new2("flags"), rb_iv_get(obj, "flags")); 1196 | rb_hash_aset(h, rb_str_new2("decimals"), rb_iv_get(obj, "decimals")); 1197 | return h; 1198 | } 1199 | 1200 | /* inspect */ 1201 | static VALUE field_inspect(VALUE obj) 1202 | { 1203 | VALUE n = rb_iv_get(obj, "name"); 1204 | VALUE s = rb_str_new(0, RSTRING_LEN(n) + 16); 1205 | sprintf(RSTRING_PTR(s), "#", RSTRING_PTR(n)); 1206 | return s; 1207 | } 1208 | 1209 | #define DefineMysqlFieldMemberMethod(m)\ 1210 | static VALUE field_##m(VALUE obj)\ 1211 | {return rb_iv_get(obj, #m);} 1212 | 1213 | DefineMysqlFieldMemberMethod(name) 1214 | DefineMysqlFieldMemberMethod(table) 1215 | DefineMysqlFieldMemberMethod(def) 1216 | DefineMysqlFieldMemberMethod(type) 1217 | DefineMysqlFieldMemberMethod(length) 1218 | DefineMysqlFieldMemberMethod(max_length) 1219 | DefineMysqlFieldMemberMethod(flags) 1220 | DefineMysqlFieldMemberMethod(decimals) 1221 | 1222 | #ifdef IS_NUM 1223 | /* is_num? */ 1224 | static VALUE field_is_num(VALUE obj) 1225 | { 1226 | return IS_NUM(NUM2INT(rb_iv_get(obj, "type"))) ? Qtrue : Qfalse; 1227 | } 1228 | #endif 1229 | 1230 | #ifdef IS_NOT_NULL 1231 | /* is_not_null? */ 1232 | static VALUE field_is_not_null(VALUE obj) 1233 | { 1234 | return IS_NOT_NULL(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse; 1235 | } 1236 | #endif 1237 | 1238 | #ifdef IS_PRI_KEY 1239 | /* is_pri_key? */ 1240 | static VALUE field_is_pri_key(VALUE obj) 1241 | { 1242 | return IS_PRI_KEY(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse; 1243 | } 1244 | #endif 1245 | 1246 | #if MYSQL_VERSION_ID >= 40102 1247 | /*------------------------------- 1248 | * Mysql::Stmt object method 1249 | */ 1250 | 1251 | /* check if stmt is already closed */ 1252 | static void check_stmt_closed(VALUE obj) 1253 | { 1254 | struct mysql_stmt* s = DATA_PTR(obj); 1255 | if (s->closed == Qtrue) 1256 | rb_raise(eMysql, "Mysql::Stmt object is already closed"); 1257 | } 1258 | 1259 | static void mysql_stmt_raise(MYSQL_STMT* s) 1260 | { 1261 | VALUE e = rb_exc_new2(eMysql, mysql_stmt_error(s)); 1262 | rb_iv_set(e, "errno", INT2FIX(mysql_stmt_errno(s))); 1263 | rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_stmt_sqlstate(s))); 1264 | rb_exc_raise(e); 1265 | } 1266 | 1267 | /* affected_rows() */ 1268 | static VALUE stmt_affected_rows(VALUE obj) 1269 | { 1270 | struct mysql_stmt* s = DATA_PTR(obj); 1271 | my_ulonglong n; 1272 | check_stmt_closed(obj); 1273 | n = mysql_stmt_affected_rows(s->stmt); 1274 | return ULL2NUM(n); 1275 | } 1276 | 1277 | #if 0 1278 | /* attr_get(option) */ 1279 | static VALUE stmt_attr_get(VALUE obj, VALUE opt) 1280 | { 1281 | struct mysql_stmt* s = DATA_PTR(obj); 1282 | check_stmt_closed(obj); 1283 | if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) { 1284 | my_bool arg; 1285 | mysql_stmt_attr_get(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg); 1286 | return arg == 1 ? Qtrue : Qfalse; 1287 | } 1288 | rb_raise(eMysql, "unknown option: %d", NUM2INT(opt)); 1289 | } 1290 | 1291 | /* attr_set(option, arg) */ 1292 | static VALUE stmt_attr_set(VALUE obj, VALUE opt, VALUE val) 1293 | { 1294 | struct mysql_stmt* s = DATA_PTR(obj); 1295 | check_stmt_closed(obj); 1296 | if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) { 1297 | my_bool arg; 1298 | arg = (val == Qnil || val == Qfalse) ? 0 : 1; 1299 | mysql_stmt_attr_set(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg); 1300 | return obj; 1301 | } 1302 | rb_raise(eMysql, "unknown option: %d", NUM2INT(opt)); 1303 | } 1304 | #endif 1305 | 1306 | /* bind_result(bind,...) */ 1307 | static VALUE stmt_bind_result(int argc, VALUE *argv, VALUE obj) 1308 | { 1309 | struct mysql_stmt* s = DATA_PTR(obj); 1310 | int i; 1311 | MYSQL_FIELD *field; 1312 | 1313 | check_stmt_closed(obj); 1314 | if (argc != s->result.n) 1315 | rb_raise(eMysql, "bind_result: result value count(%d) != number of argument(%d)", s->result.n, argc); 1316 | for (i = 0; i < argc; i++) { 1317 | if (argv[i] == Qnil || argv[i] == rb_cNilClass) { 1318 | field = mysql_fetch_fields(s->res); 1319 | s->result.bind[i].buffer_type = field[i].type; 1320 | } 1321 | else if (argv[i] == rb_cString) 1322 | s->result.bind[i].buffer_type = MYSQL_TYPE_STRING; 1323 | else if (argv[i] == rb_cNumeric || argv[i] == rb_cInteger || argv[i] == rb_cFixnum) 1324 | s->result.bind[i].buffer_type = MYSQL_TYPE_LONGLONG; 1325 | else if (argv[i] == rb_cFloat) 1326 | s->result.bind[i].buffer_type = MYSQL_TYPE_DOUBLE; 1327 | else if (argv[i] == cMysqlTime) 1328 | s->result.bind[i].buffer_type = MYSQL_TYPE_DATETIME; 1329 | else 1330 | rb_raise(rb_eTypeError, "unrecognized class: %s", RSTRING_PTR(rb_inspect(argv[i]))); 1331 | if (mysql_stmt_bind_result(s->stmt, s->result.bind)) 1332 | mysql_stmt_raise(s->stmt); 1333 | } 1334 | return obj; 1335 | } 1336 | 1337 | /* close() */ 1338 | static VALUE stmt_close(VALUE obj) 1339 | { 1340 | struct mysql_stmt* s = DATA_PTR(obj); 1341 | check_stmt_closed(obj); 1342 | mysql_stmt_close(s->stmt); 1343 | s->closed = Qtrue; 1344 | return Qnil; 1345 | } 1346 | 1347 | /* data_seek(offset) */ 1348 | static VALUE stmt_data_seek(VALUE obj, VALUE offset) 1349 | { 1350 | struct mysql_stmt* s = DATA_PTR(obj); 1351 | check_stmt_closed(obj); 1352 | mysql_stmt_data_seek(s->stmt, NUM2INT(offset)); 1353 | return obj; 1354 | } 1355 | 1356 | /* execute(arg,...) */ 1357 | static VALUE stmt_execute(int argc, VALUE *argv, VALUE obj) 1358 | { 1359 | struct mysql_stmt *s = DATA_PTR(obj); 1360 | MYSQL_STMT *stmt = s->stmt; 1361 | int i; 1362 | 1363 | check_stmt_closed(obj); 1364 | free_execute_memory(s); 1365 | if (s->param.n != argc) 1366 | rb_raise(eMysql, "execute: param_count(%d) != number of argument(%d)", s->param.n, argc); 1367 | if (argc > 0) { 1368 | memset(s->param.bind, 0, sizeof(*(s->param.bind))*argc); 1369 | for (i = 0; i < argc; i++) { 1370 | switch (TYPE(argv[i])) { 1371 | case T_NIL: 1372 | s->param.bind[i].buffer_type = MYSQL_TYPE_NULL; 1373 | break; 1374 | case T_FIXNUM: 1375 | #if SIZEOF_INT < SIZEOF_LONG 1376 | s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG; 1377 | s->param.bind[i].buffer = &(s->param.buffer[i]); 1378 | *(LONG_LONG*)(s->param.bind[i].buffer) = FIX2LONG(argv[i]); 1379 | #else 1380 | s->param.bind[i].buffer_type = MYSQL_TYPE_LONG; 1381 | s->param.bind[i].buffer = &(s->param.buffer[i]); 1382 | *(int*)(s->param.bind[i].buffer) = FIX2INT(argv[i]); 1383 | #endif 1384 | break; 1385 | case T_BIGNUM: 1386 | s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG; 1387 | s->param.bind[i].buffer = &(s->param.buffer[i]); 1388 | *(LONG_LONG*)(s->param.bind[i].buffer) = rb_big2ll(argv[i]); 1389 | break; 1390 | case T_FLOAT: 1391 | s->param.bind[i].buffer_type = MYSQL_TYPE_DOUBLE; 1392 | s->param.bind[i].buffer = &(s->param.buffer[i]); 1393 | *(double*)(s->param.bind[i].buffer) = NUM2DBL(argv[i]); 1394 | break; 1395 | case T_STRING: 1396 | s->param.bind[i].buffer_type = MYSQL_TYPE_STRING; 1397 | s->param.bind[i].buffer = RSTRING_PTR(argv[i]); 1398 | s->param.bind[i].buffer_length = RSTRING_LEN(argv[i]); 1399 | s->param.length[i] = RSTRING_LEN(argv[i]); 1400 | s->param.bind[i].length = &(s->param.length[i]); 1401 | break; 1402 | default: 1403 | if (CLASS_OF(argv[i]) == rb_cTime) { 1404 | MYSQL_TIME t; 1405 | VALUE a = rb_funcall(argv[i], rb_intern("to_a"), 0); 1406 | s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME; 1407 | s->param.bind[i].buffer = &(s->param.buffer[i]); 1408 | memset(&t, 0, sizeof(t)); /* avoid warning */ 1409 | t.second_part = 0; 1410 | t.neg = 0; 1411 | t.second = FIX2INT(RARRAY_PTR(a)[0]); 1412 | t.minute = FIX2INT(RARRAY_PTR(a)[1]); 1413 | t.hour = FIX2INT(RARRAY_PTR(a)[2]); 1414 | t.day = FIX2INT(RARRAY_PTR(a)[3]); 1415 | t.month = FIX2INT(RARRAY_PTR(a)[4]); 1416 | t.year = FIX2INT(RARRAY_PTR(a)[5]); 1417 | *(MYSQL_TIME*)&(s->param.buffer[i]) = t; 1418 | } else if (CLASS_OF(argv[i]) == cMysqlTime) { 1419 | MYSQL_TIME t; 1420 | s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME; 1421 | s->param.bind[i].buffer = &(s->param.buffer[i]); 1422 | memset(&t, 0, sizeof(t)); /* avoid warning */ 1423 | t.second_part = 0; 1424 | t.neg = 0; 1425 | t.second = NUM2INT(rb_iv_get(argv[i], "second")); 1426 | t.minute = NUM2INT(rb_iv_get(argv[i], "minute")); 1427 | t.hour = NUM2INT(rb_iv_get(argv[i], "hour")); 1428 | t.day = NUM2INT(rb_iv_get(argv[i], "day")); 1429 | t.month = NUM2INT(rb_iv_get(argv[i], "month")); 1430 | t.year = NUM2INT(rb_iv_get(argv[i], "year")); 1431 | *(MYSQL_TIME*)&(s->param.buffer[i]) = t; 1432 | } else 1433 | rb_raise(rb_eTypeError, "unsupported type: %d", TYPE(argv[i])); 1434 | } 1435 | } 1436 | if (mysql_stmt_bind_param(stmt, s->param.bind)) 1437 | mysql_stmt_raise(stmt); 1438 | } 1439 | 1440 | if (mysql_stmt_execute(stmt)) 1441 | mysql_stmt_raise(stmt); 1442 | if (s->res) { 1443 | MYSQL_FIELD *field; 1444 | if (mysql_stmt_store_result(stmt)) 1445 | mysql_stmt_raise(stmt); 1446 | field = mysql_fetch_fields(s->res); 1447 | for (i = 0; i < s->result.n; i++) { 1448 | switch(s->result.bind[i].buffer_type) { 1449 | case MYSQL_TYPE_NULL: 1450 | break; 1451 | case MYSQL_TYPE_TINY: 1452 | case MYSQL_TYPE_SHORT: 1453 | case MYSQL_TYPE_YEAR: 1454 | case MYSQL_TYPE_INT24: 1455 | case MYSQL_TYPE_LONG: 1456 | case MYSQL_TYPE_LONGLONG: 1457 | case MYSQL_TYPE_FLOAT: 1458 | case MYSQL_TYPE_DOUBLE: 1459 | s->result.bind[i].buffer = xmalloc(8); 1460 | s->result.bind[i].buffer_length = 8; 1461 | memset(s->result.bind[i].buffer, 0, 8); 1462 | break; 1463 | case MYSQL_TYPE_DECIMAL: 1464 | case MYSQL_TYPE_STRING: 1465 | case MYSQL_TYPE_VAR_STRING: 1466 | case MYSQL_TYPE_TINY_BLOB: 1467 | case MYSQL_TYPE_BLOB: 1468 | case MYSQL_TYPE_MEDIUM_BLOB: 1469 | case MYSQL_TYPE_LONG_BLOB: 1470 | #if MYSQL_VERSION_ID >= 50003 1471 | case MYSQL_TYPE_NEWDECIMAL: 1472 | case MYSQL_TYPE_BIT: 1473 | #endif 1474 | s->result.bind[i].buffer = xmalloc(field[i].max_length); 1475 | memset(s->result.bind[i].buffer, 0, field[i].max_length); 1476 | s->result.bind[i].buffer_length = field[i].max_length; 1477 | break; 1478 | case MYSQL_TYPE_TIME: 1479 | case MYSQL_TYPE_DATE: 1480 | case MYSQL_TYPE_DATETIME: 1481 | case MYSQL_TYPE_TIMESTAMP: 1482 | s->result.bind[i].buffer = xmalloc(sizeof(MYSQL_TIME)); 1483 | s->result.bind[i].buffer_length = sizeof(MYSQL_TIME); 1484 | memset(s->result.bind[i].buffer, 0, sizeof(MYSQL_TIME)); 1485 | break; 1486 | default: 1487 | rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type); 1488 | } 1489 | } 1490 | if (mysql_stmt_bind_result(s->stmt, s->result.bind)) 1491 | mysql_stmt_raise(s->stmt); 1492 | } 1493 | return obj; 1494 | } 1495 | 1496 | /* fetch() */ 1497 | static VALUE stmt_fetch(VALUE obj) 1498 | { 1499 | struct mysql_stmt* s = DATA_PTR(obj); 1500 | VALUE ret; 1501 | int i; 1502 | int r; 1503 | 1504 | check_stmt_closed(obj); 1505 | r = mysql_stmt_fetch(s->stmt); 1506 | if (r == MYSQL_NO_DATA) 1507 | return Qnil; 1508 | #ifdef MYSQL_DATA_TRUNCATED 1509 | if (r == MYSQL_DATA_TRUNCATED) 1510 | rb_raise(rb_eRuntimeError, "unexpectedly data truncated"); 1511 | #endif 1512 | if (r == 1) 1513 | mysql_stmt_raise(s->stmt); 1514 | 1515 | ret = rb_ary_new2(s->result.n); 1516 | for (i = 0; i < s->result.n; i++) { 1517 | if (s->result.is_null[i]) 1518 | rb_ary_push(ret, Qnil); 1519 | else { 1520 | VALUE v; 1521 | MYSQL_TIME *t; 1522 | switch (s->result.bind[i].buffer_type) { 1523 | case MYSQL_TYPE_TINY: 1524 | if (s->result.bind[i].is_unsigned) 1525 | v = UINT2NUM(*(unsigned char *)s->result.bind[i].buffer); 1526 | else 1527 | v = INT2NUM(*(signed char *)s->result.bind[i].buffer); 1528 | break; 1529 | case MYSQL_TYPE_SHORT: 1530 | case MYSQL_TYPE_YEAR: 1531 | if (s->result.bind[i].is_unsigned) 1532 | v = UINT2NUM(*(unsigned short *)s->result.bind[i].buffer); 1533 | else 1534 | v = INT2NUM(*(short *)s->result.bind[i].buffer); 1535 | break; 1536 | case MYSQL_TYPE_INT24: 1537 | case MYSQL_TYPE_LONG: 1538 | if (s->result.bind[i].is_unsigned) 1539 | v = UINT2NUM(*(unsigned int *)s->result.bind[i].buffer); 1540 | else 1541 | v = INT2NUM(*(int *)s->result.bind[i].buffer); 1542 | break; 1543 | case MYSQL_TYPE_LONGLONG: 1544 | if (s->result.bind[i].is_unsigned) 1545 | v = ULL2NUM(*(unsigned long long *)s->result.bind[i].buffer); 1546 | else 1547 | v = LL2NUM(*(long long *)s->result.bind[i].buffer); 1548 | break; 1549 | case MYSQL_TYPE_FLOAT: 1550 | v = rb_float_new((double)(*(float *)s->result.bind[i].buffer)); 1551 | break; 1552 | case MYSQL_TYPE_DOUBLE: 1553 | v = rb_float_new(*(double *)s->result.bind[i].buffer); 1554 | break; 1555 | case MYSQL_TYPE_TIME: 1556 | case MYSQL_TYPE_DATE: 1557 | case MYSQL_TYPE_DATETIME: 1558 | case MYSQL_TYPE_TIMESTAMP: 1559 | t = (MYSQL_TIME *)s->result.bind[i].buffer; 1560 | v = rb_obj_alloc(cMysqlTime); 1561 | rb_funcall(v, rb_intern("initialize"), 8, 1562 | INT2FIX(t->year), INT2FIX(t->month), 1563 | INT2FIX(t->day), INT2FIX(t->hour), 1564 | INT2FIX(t->minute), INT2FIX(t->second), 1565 | (t->neg ? Qtrue : Qfalse), 1566 | INT2FIX(t->second_part)); 1567 | break; 1568 | case MYSQL_TYPE_DECIMAL: 1569 | case MYSQL_TYPE_STRING: 1570 | case MYSQL_TYPE_VAR_STRING: 1571 | case MYSQL_TYPE_TINY_BLOB: 1572 | case MYSQL_TYPE_BLOB: 1573 | case MYSQL_TYPE_MEDIUM_BLOB: 1574 | case MYSQL_TYPE_LONG_BLOB: 1575 | #if MYSQL_VERSION_ID >= 50003 1576 | case MYSQL_TYPE_NEWDECIMAL: 1577 | case MYSQL_TYPE_BIT: 1578 | #endif 1579 | v = rb_tainted_str_new(s->result.bind[i].buffer, s->result.length[i]); 1580 | break; 1581 | default: 1582 | rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type); 1583 | } 1584 | rb_ary_push(ret, v); 1585 | } 1586 | } 1587 | return ret; 1588 | } 1589 | 1590 | /* each {...} */ 1591 | static VALUE stmt_each(VALUE obj) 1592 | { 1593 | VALUE row; 1594 | check_stmt_closed(obj); 1595 | while ((row = stmt_fetch(obj)) != Qnil) 1596 | rb_yield(row); 1597 | return obj; 1598 | } 1599 | 1600 | /* field_count() */ 1601 | static VALUE stmt_field_count(VALUE obj) 1602 | { 1603 | struct mysql_stmt* s = DATA_PTR(obj); 1604 | unsigned int n; 1605 | check_stmt_closed(obj); 1606 | n = mysql_stmt_field_count(s->stmt); 1607 | return INT2NUM(n); 1608 | } 1609 | 1610 | /* free_result() */ 1611 | static VALUE stmt_free_result(VALUE obj) 1612 | { 1613 | struct mysql_stmt* s = DATA_PTR(obj); 1614 | check_stmt_closed(obj); 1615 | if (mysql_stmt_free_result(s->stmt)) 1616 | mysql_stmt_raise(s->stmt); 1617 | return obj; 1618 | } 1619 | 1620 | /* insert_id() */ 1621 | static VALUE stmt_insert_id(VALUE obj) 1622 | { 1623 | struct mysql_stmt* s = DATA_PTR(obj); 1624 | my_ulonglong n; 1625 | check_stmt_closed(obj); 1626 | n = mysql_stmt_insert_id(s->stmt); 1627 | return ULL2NUM(n); 1628 | } 1629 | 1630 | /* num_rows() */ 1631 | static VALUE stmt_num_rows(VALUE obj) 1632 | { 1633 | struct mysql_stmt* s = DATA_PTR(obj); 1634 | my_ulonglong n; 1635 | check_stmt_closed(obj); 1636 | n = mysql_stmt_num_rows(s->stmt); 1637 | return INT2NUM(n); 1638 | } 1639 | 1640 | /* param_count() */ 1641 | static VALUE stmt_param_count(VALUE obj) 1642 | { 1643 | struct mysql_stmt* s = DATA_PTR(obj); 1644 | unsigned long n; 1645 | check_stmt_closed(obj); 1646 | n = mysql_stmt_param_count(s->stmt); 1647 | return INT2NUM(n); 1648 | } 1649 | 1650 | /* prepare(query) */ 1651 | static VALUE stmt_prepare(VALUE obj, VALUE query) 1652 | { 1653 | struct mysql_stmt* s = DATA_PTR(obj); 1654 | int n; 1655 | int i; 1656 | MYSQL_FIELD *field; 1657 | 1658 | free_mysqlstmt_memory(s); 1659 | check_stmt_closed(obj); 1660 | Check_Type(query, T_STRING); 1661 | if (mysql_stmt_prepare(s->stmt, RSTRING_PTR(query), RSTRING_LEN(query))) 1662 | mysql_stmt_raise(s->stmt); 1663 | 1664 | n = mysql_stmt_param_count(s->stmt); 1665 | s->param.n = n; 1666 | s->param.bind = xmalloc(sizeof(s->param.bind[0]) * n); 1667 | s->param.length = xmalloc(sizeof(s->param.length[0]) * n); 1668 | s->param.buffer = xmalloc(sizeof(s->param.buffer[0]) * n); 1669 | 1670 | s->res = mysql_stmt_result_metadata(s->stmt); 1671 | if (s->res) { 1672 | n = s->result.n = mysql_num_fields(s->res); 1673 | s->result.bind = xmalloc(sizeof(s->result.bind[0]) * n); 1674 | s->result.is_null = xmalloc(sizeof(s->result.is_null[0]) * n); 1675 | s->result.length = xmalloc(sizeof(s->result.length[0]) * n); 1676 | field = mysql_fetch_fields(s->res); 1677 | memset(s->result.bind, 0, sizeof(s->result.bind[0]) * n); 1678 | for (i = 0; i < n; i++) { 1679 | s->result.bind[i].buffer_type = field[i].type; 1680 | #if MYSQL_VERSION_ID < 50003 1681 | if (field[i].type == MYSQL_TYPE_DECIMAL) 1682 | s->result.bind[i].buffer_type = MYSQL_TYPE_STRING; 1683 | #endif 1684 | s->result.bind[i].is_null = &(s->result.is_null[i]); 1685 | s->result.bind[i].length = &(s->result.length[i]); 1686 | s->result.bind[i].is_unsigned = ((field[i].flags & UNSIGNED_FLAG) != 0); 1687 | } 1688 | } else { 1689 | if (mysql_stmt_errno(s->stmt)) 1690 | mysql_stmt_raise(s->stmt); 1691 | } 1692 | 1693 | return obj; 1694 | } 1695 | 1696 | #if 0 1697 | /* reset() */ 1698 | static VALUE stmt_reset(VALUE obj) 1699 | { 1700 | struct mysql_stmt* s = DATA_PTR(obj); 1701 | check_stmt_closed(obj); 1702 | if (mysql_stmt_reset(s->stmt)) 1703 | mysql_stmt_raise(s->stmt); 1704 | return obj; 1705 | } 1706 | #endif 1707 | 1708 | /* result_metadata() */ 1709 | static VALUE stmt_result_metadata(VALUE obj) 1710 | { 1711 | struct mysql_stmt* s = DATA_PTR(obj); 1712 | MYSQL_RES *res; 1713 | check_stmt_closed(obj); 1714 | res = mysql_stmt_result_metadata(s->stmt); 1715 | if (res == NULL) { 1716 | if (mysql_stmt_errno(s->stmt) != 0) 1717 | mysql_stmt_raise(s->stmt); 1718 | return Qnil; 1719 | } 1720 | return mysqlres2obj(res); 1721 | } 1722 | 1723 | /* row_seek(offset) */ 1724 | static VALUE stmt_row_seek(VALUE obj, VALUE offset) 1725 | { 1726 | struct mysql_stmt* s = DATA_PTR(obj); 1727 | MYSQL_ROW_OFFSET prev_offset; 1728 | if (CLASS_OF(offset) != cMysqlRowOffset) 1729 | rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset)); 1730 | check_stmt_closed(obj); 1731 | prev_offset = mysql_stmt_row_seek(s->stmt, DATA_PTR(offset)); 1732 | return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset); 1733 | } 1734 | 1735 | /* row_tell() */ 1736 | static VALUE stmt_row_tell(VALUE obj) 1737 | { 1738 | struct mysql_stmt* s = DATA_PTR(obj); 1739 | MYSQL_ROW_OFFSET offset; 1740 | check_stmt_closed(obj); 1741 | offset = mysql_stmt_row_tell(s->stmt); 1742 | return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset); 1743 | } 1744 | 1745 | #if 0 1746 | /* send_long_data(col, data) */ 1747 | static VALUE stmt_send_long_data(VALUE obj, VALUE col, VALUE data) 1748 | { 1749 | struct mysql_stmt* s = DATA_PTR(obj); 1750 | int c; 1751 | check_stmt_closed(obj); 1752 | c = NUM2INT(col); 1753 | if (0 <= c && c < s->param.n) { 1754 | s->param.bind[c].buffer_type = MYSQL_TYPE_STRING; 1755 | if (mysql_stmt_bind_param(s->stmt, s->param.bind)) 1756 | mysql_stmt_raise(s->stmt); 1757 | } 1758 | if (mysql_stmt_send_long_data(s->stmt, c, RSTRING_PTR(data), RSTRING_LEN(data))) 1759 | mysql_stmt_raise(s->stmt); 1760 | return obj; 1761 | } 1762 | #endif 1763 | 1764 | /* sqlstate() */ 1765 | static VALUE stmt_sqlstate(VALUE obj) 1766 | { 1767 | struct mysql_stmt* s = DATA_PTR(obj); 1768 | return rb_tainted_str_new2(mysql_stmt_sqlstate(s->stmt)); 1769 | } 1770 | 1771 | /*------------------------------- 1772 | * Mysql::Time object method 1773 | */ 1774 | 1775 | static VALUE time_initialize(int argc, VALUE* argv, VALUE obj) 1776 | { 1777 | VALUE year, month, day, hour, minute, second, neg, second_part; 1778 | rb_scan_args(argc, argv, "08", &year, &month, &day, &hour, &minute, &second, &neg, &second_part); 1779 | #define NILorFIXvalue(o) (NIL_P(o) ? INT2FIX(0) : (Check_Type(o, T_FIXNUM), o)) 1780 | rb_iv_set(obj, "year", NILorFIXvalue(year)); 1781 | rb_iv_set(obj, "month", NILorFIXvalue(month)); 1782 | rb_iv_set(obj, "day", NILorFIXvalue(day)); 1783 | rb_iv_set(obj, "hour", NILorFIXvalue(hour)); 1784 | rb_iv_set(obj, "minute", NILorFIXvalue(minute)); 1785 | rb_iv_set(obj, "second", NILorFIXvalue(second)); 1786 | rb_iv_set(obj, "neg", (neg == Qnil || neg == Qfalse) ? Qfalse : Qtrue); 1787 | rb_iv_set(obj, "second_part", NILorFIXvalue(second_part)); 1788 | return obj; 1789 | } 1790 | 1791 | static VALUE time_inspect(VALUE obj) 1792 | { 1793 | char buf[36]; 1794 | sprintf(buf, "#", 1795 | NUM2INT(rb_iv_get(obj, "year")), 1796 | NUM2INT(rb_iv_get(obj, "month")), 1797 | NUM2INT(rb_iv_get(obj, "day")), 1798 | NUM2INT(rb_iv_get(obj, "hour")), 1799 | NUM2INT(rb_iv_get(obj, "minute")), 1800 | NUM2INT(rb_iv_get(obj, "second"))); 1801 | return rb_str_new2(buf); 1802 | } 1803 | 1804 | static VALUE time_to_s(VALUE obj) 1805 | { 1806 | char buf[20]; 1807 | sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", 1808 | NUM2INT(rb_iv_get(obj, "year")), 1809 | NUM2INT(rb_iv_get(obj, "month")), 1810 | NUM2INT(rb_iv_get(obj, "day")), 1811 | NUM2INT(rb_iv_get(obj, "hour")), 1812 | NUM2INT(rb_iv_get(obj, "minute")), 1813 | NUM2INT(rb_iv_get(obj, "second"))); 1814 | return rb_str_new2(buf); 1815 | } 1816 | 1817 | #define DefineMysqlTimeGetMethod(m)\ 1818 | static VALUE time_get_##m(VALUE obj)\ 1819 | {return rb_iv_get(obj, #m);} 1820 | 1821 | DefineMysqlTimeGetMethod(year) 1822 | DefineMysqlTimeGetMethod(month) 1823 | DefineMysqlTimeGetMethod(day) 1824 | DefineMysqlTimeGetMethod(hour) 1825 | DefineMysqlTimeGetMethod(minute) 1826 | DefineMysqlTimeGetMethod(second) 1827 | DefineMysqlTimeGetMethod(neg) 1828 | DefineMysqlTimeGetMethod(second_part) 1829 | 1830 | #define DefineMysqlTimeSetMethod(m)\ 1831 | static VALUE time_set_##m(VALUE obj, VALUE v)\ 1832 | {rb_iv_set(obj, #m, NILorFIXvalue(v)); return v;} 1833 | 1834 | DefineMysqlTimeSetMethod(year) 1835 | DefineMysqlTimeSetMethod(month) 1836 | DefineMysqlTimeSetMethod(day) 1837 | DefineMysqlTimeSetMethod(hour) 1838 | DefineMysqlTimeSetMethod(minute) 1839 | DefineMysqlTimeSetMethod(second) 1840 | DefineMysqlTimeSetMethod(second_part) 1841 | 1842 | static VALUE time_set_neg(VALUE obj, VALUE v) 1843 | { 1844 | rb_iv_set(obj, "neg", (v == Qnil || v == Qfalse) ? Qfalse : Qtrue); 1845 | return v; 1846 | } 1847 | 1848 | static VALUE time_equal(VALUE obj, VALUE v) 1849 | { 1850 | if (CLASS_OF(v) == cMysqlTime && 1851 | NUM2INT(rb_iv_get(obj, "year")) == NUM2INT(rb_iv_get(v, "year")) && 1852 | NUM2INT(rb_iv_get(obj, "month")) == NUM2INT(rb_iv_get(v, "month")) && 1853 | NUM2INT(rb_iv_get(obj, "day")) == NUM2INT(rb_iv_get(v, "day")) && 1854 | NUM2INT(rb_iv_get(obj, "hour")) == NUM2INT(rb_iv_get(v, "hour")) && 1855 | NUM2INT(rb_iv_get(obj, "minute")) == NUM2INT(rb_iv_get(v, "minute")) && 1856 | NUM2INT(rb_iv_get(obj, "second")) == NUM2INT(rb_iv_get(v, "second")) && 1857 | rb_iv_get(obj, "neg") == rb_iv_get(v, "neg") && 1858 | NUM2INT(rb_iv_get(obj, "second_part")) == NUM2INT(rb_iv_get(v, "second_part"))) 1859 | return Qtrue; 1860 | return Qfalse; 1861 | } 1862 | 1863 | #endif 1864 | 1865 | /*------------------------------- 1866 | * Mysql::Error object method 1867 | */ 1868 | 1869 | static VALUE error_error(VALUE obj) 1870 | { 1871 | return rb_iv_get(obj, "mesg"); 1872 | } 1873 | 1874 | static VALUE error_errno(VALUE obj) 1875 | { 1876 | return rb_iv_get(obj, "errno"); 1877 | } 1878 | 1879 | static VALUE error_sqlstate(VALUE obj) 1880 | { 1881 | return rb_iv_get(obj, "sqlstate"); 1882 | } 1883 | 1884 | /*------------------------------- 1885 | * Initialize 1886 | */ 1887 | 1888 | void Init_mysql_api(void) 1889 | { 1890 | int i; 1891 | int dots = 0; 1892 | const char *lib = mysql_get_client_info(); 1893 | for (i = 0; lib[i] != 0 && MYSQL_SERVER_VERSION[i] != 0; i++) { 1894 | if (lib[i] == '.') { 1895 | dots++; 1896 | /* we only compare MAJOR and MINOR */ 1897 | if (dots == 2) break; 1898 | } 1899 | if (lib[i] != MYSQL_SERVER_VERSION[i]) { 1900 | rb_raise(rb_eRuntimeError, "Incorrect MySQL client library version! This gem was compiled for %s but the client library is %s.", MYSQL_SERVER_VERSION, lib); 1901 | return; 1902 | } 1903 | } 1904 | 1905 | cMysql = rb_define_class("Mysql", rb_cObject); 1906 | cMysqlRes = rb_define_class_under(cMysql, "Result", rb_cObject); 1907 | cMysqlField = rb_define_class_under(cMysql, "Field", rb_cObject); 1908 | #if MYSQL_VERSION_ID >= 40102 1909 | cMysqlStmt = rb_define_class_under(cMysql, "Stmt", rb_cObject); 1910 | cMysqlRowOffset = rb_define_class_under(cMysql, "RowOffset", rb_cObject); 1911 | cMysqlTime = rb_define_class_under(cMysql, "Time", rb_cObject); 1912 | #endif 1913 | eMysql = rb_define_class_under(cMysql, "Error", rb_eStandardError); 1914 | 1915 | rb_define_global_const("MysqlRes", cMysqlRes); 1916 | rb_define_global_const("MysqlField", cMysqlField); 1917 | rb_define_global_const("MysqlError", eMysql); 1918 | 1919 | /* Mysql class method */ 1920 | rb_define_singleton_method(cMysql, "init", init, 0); 1921 | rb_define_singleton_method(cMysql, "real_connect", real_connect, -1); 1922 | rb_define_singleton_method(cMysql, "connect", real_connect, -1); 1923 | rb_define_singleton_method(cMysql, "new", real_connect, -1); 1924 | rb_define_singleton_method(cMysql, "escape_string", escape_string, 1); 1925 | rb_define_singleton_method(cMysql, "quote", escape_string, 1); 1926 | rb_define_singleton_method(cMysql, "client_info", client_info, 0); 1927 | rb_define_singleton_method(cMysql, "get_client_info", client_info, 0); 1928 | #if MYSQL_VERSION_ID >= 32332 1929 | rb_define_singleton_method(cMysql, "debug", my_debug, 1); 1930 | #endif 1931 | #if MYSQL_VERSION_ID >= 40000 1932 | rb_define_singleton_method(cMysql, "get_client_version", client_version, 0); 1933 | rb_define_singleton_method(cMysql, "client_version", client_version, 0); 1934 | #endif 1935 | 1936 | /* Mysql object method */ 1937 | #if MYSQL_VERSION_ID >= 32200 1938 | rb_define_method(cMysql, "real_connect", real_connect2, -1); 1939 | rb_define_method(cMysql, "connect", real_connect2, -1); 1940 | rb_define_method(cMysql, "options", options, -1); 1941 | #endif 1942 | rb_define_method(cMysql, "initialize", initialize, -1); 1943 | #if MYSQL_VERSION_ID >= 32332 1944 | rb_define_method(cMysql, "escape_string", real_escape_string, 1); 1945 | rb_define_method(cMysql, "quote", real_escape_string, 1); 1946 | #else 1947 | rb_define_method(cMysql, "escape_string", escape_string, 1); 1948 | rb_define_method(cMysql, "quote", escape_string, 1); 1949 | #endif 1950 | rb_define_method(cMysql, "client_info", client_info, 0); 1951 | rb_define_method(cMysql, "get_client_info", client_info, 0); 1952 | rb_define_method(cMysql, "affected_rows", affected_rows, 0); 1953 | #if MYSQL_VERSION_ID >= 32303 1954 | rb_define_method(cMysql, "change_user", change_user, -1); 1955 | #endif 1956 | #if MYSQL_VERSION_ID >= 32321 1957 | rb_define_method(cMysql, "character_set_name", character_set_name, 0); 1958 | #endif 1959 | rb_define_method(cMysql, "close", my_close, 0); 1960 | #if MYSQL_VERSION_ID < 40000 1961 | rb_define_method(cMysql, "create_db", create_db, 1); 1962 | rb_define_method(cMysql, "drop_db", drop_db, 1); 1963 | #endif 1964 | #if MYSQL_VERSION_ID >= 32332 1965 | rb_define_method(cMysql, "dump_debug_info", dump_debug_info, 0); 1966 | #endif 1967 | rb_define_method(cMysql, "errno", my_errno, 0); 1968 | rb_define_method(cMysql, "error", my_error, 0); 1969 | rb_define_method(cMysql, "field_count", field_count, 0); 1970 | #if MYSQL_VERSION_ID >= 40000 1971 | rb_define_method(cMysql, "get_client_version", client_version, 0); 1972 | rb_define_method(cMysql, "client_version", client_version, 0); 1973 | #endif 1974 | rb_define_method(cMysql, "get_host_info", host_info, 0); 1975 | rb_define_method(cMysql, "host_info", host_info, 0); 1976 | rb_define_method(cMysql, "get_proto_info", proto_info, 0); 1977 | rb_define_method(cMysql, "proto_info", proto_info, 0); 1978 | rb_define_method(cMysql, "get_server_info", server_info, 0); 1979 | rb_define_method(cMysql, "server_info", server_info, 0); 1980 | rb_define_method(cMysql, "info", info, 0); 1981 | rb_define_method(cMysql, "insert_id", insert_id, 0); 1982 | rb_define_method(cMysql, "kill", my_kill, 1); 1983 | rb_define_method(cMysql, "list_dbs", list_dbs, -1); 1984 | rb_define_method(cMysql, "list_fields", list_fields, -1); 1985 | rb_define_method(cMysql, "list_processes", list_processes, 0); 1986 | rb_define_method(cMysql, "list_tables", list_tables, -1); 1987 | #if MYSQL_VERSION_ID >= 32200 1988 | rb_define_method(cMysql, "ping", ping, 0); 1989 | #endif 1990 | rb_define_method(cMysql, "query", query, 1); 1991 | rb_define_method(cMysql, "real_query", query, 1); 1992 | rb_define_method(cMysql, "refresh", refresh, 1); 1993 | rb_define_method(cMysql, "reload", reload, 0); 1994 | rb_define_method(cMysql, "select_db", select_db, 1); 1995 | rb_define_method(cMysql, "shutdown", my_shutdown, -1); 1996 | rb_define_method(cMysql, "stat", my_stat, 0); 1997 | rb_define_method(cMysql, "store_result", store_result, 0); 1998 | rb_define_method(cMysql, "thread_id", thread_id, 0); 1999 | rb_define_method(cMysql, "use_result", use_result, 0); 2000 | #if MYSQL_VERSION_ID >= 40100 2001 | rb_define_method(cMysql, "get_server_version", server_version, 0); 2002 | rb_define_method(cMysql, "server_version", server_version, 0); 2003 | rb_define_method(cMysql, "warning_count", warning_count, 0); 2004 | rb_define_method(cMysql, "commit", commit, 0); 2005 | rb_define_method(cMysql, "rollback", rollback, 0); 2006 | rb_define_method(cMysql, "autocommit", autocommit, 1); 2007 | #endif 2008 | #ifdef HAVE_MYSQL_SSL_SET 2009 | rb_define_method(cMysql, "ssl_set", ssl_set, -1); 2010 | #endif 2011 | #if MYSQL_VERSION_ID >= 40102 2012 | rb_define_method(cMysql, "stmt_init", stmt_init, 0); 2013 | rb_define_method(cMysql, "prepare", prepare, 1); 2014 | #endif 2015 | #if MYSQL_VERSION_ID >= 40100 2016 | rb_define_method(cMysql, "more_results", more_results, 0); 2017 | rb_define_method(cMysql, "more_results?", more_results, 0); 2018 | rb_define_method(cMysql, "next_result", next_result, 0); 2019 | #endif 2020 | #if MYSQL_VERSION_ID >= 40101 2021 | rb_define_method(cMysql, "set_server_option", set_server_option, 1); 2022 | rb_define_method(cMysql, "sqlstate", sqlstate, 0); 2023 | #endif 2024 | rb_define_method(cMysql, "query_with_result", query_with_result, 0); 2025 | rb_define_method(cMysql, "query_with_result=", query_with_result_set, 1); 2026 | 2027 | rb_define_method(cMysql, "reconnect", reconnect, 0); 2028 | rb_define_method(cMysql, "reconnect=", reconnect_set, 1); 2029 | 2030 | /* Mysql constant */ 2031 | rb_define_const(cMysql, "VERSION", INT2FIX(MYSQL_RUBY_VERSION)); 2032 | #if MYSQL_VERSION_ID >= 32200 2033 | rb_define_const(cMysql, "OPT_CONNECT_TIMEOUT", INT2NUM(MYSQL_OPT_CONNECT_TIMEOUT)); 2034 | rb_define_const(cMysql, "OPT_COMPRESS", INT2NUM(MYSQL_OPT_COMPRESS)); 2035 | rb_define_const(cMysql, "OPT_NAMED_PIPE", INT2NUM(MYSQL_OPT_NAMED_PIPE)); 2036 | rb_define_const(cMysql, "INIT_COMMAND", INT2NUM(MYSQL_INIT_COMMAND)); 2037 | rb_define_const(cMysql, "READ_DEFAULT_FILE", INT2NUM(MYSQL_READ_DEFAULT_FILE)); 2038 | rb_define_const(cMysql, "READ_DEFAULT_GROUP", INT2NUM(MYSQL_READ_DEFAULT_GROUP)); 2039 | #endif 2040 | #if MYSQL_VERSION_ID >= 32349 2041 | rb_define_const(cMysql, "SET_CHARSET_DIR", INT2NUM(MYSQL_SET_CHARSET_DIR)); 2042 | rb_define_const(cMysql, "SET_CHARSET_NAME", INT2NUM(MYSQL_SET_CHARSET_NAME)); 2043 | rb_define_const(cMysql, "OPT_LOCAL_INFILE", INT2NUM(MYSQL_OPT_LOCAL_INFILE)); 2044 | #endif 2045 | #if MYSQL_VERSION_ID >= 40100 2046 | rb_define_const(cMysql, "OPT_PROTOCOL", INT2NUM(MYSQL_OPT_PROTOCOL)); 2047 | rb_define_const(cMysql, "SHARED_MEMORY_BASE_NAME", INT2NUM(MYSQL_SHARED_MEMORY_BASE_NAME)); 2048 | #endif 2049 | #if MYSQL_VERSION_ID >= 40101 2050 | rb_define_const(cMysql, "OPT_READ_TIMEOUT", INT2NUM(MYSQL_OPT_READ_TIMEOUT)); 2051 | rb_define_const(cMysql, "OPT_WRITE_TIMEOUT", INT2NUM(MYSQL_OPT_WRITE_TIMEOUT)); 2052 | rb_define_const(cMysql, "SECURE_AUTH", INT2NUM(MYSQL_SECURE_AUTH)); 2053 | rb_define_const(cMysql, "OPT_GUESS_CONNECTION", INT2NUM(MYSQL_OPT_GUESS_CONNECTION)); 2054 | rb_define_const(cMysql, "OPT_USE_EMBEDDED_CONNECTION", INT2NUM(MYSQL_OPT_USE_EMBEDDED_CONNECTION)); 2055 | rb_define_const(cMysql, "OPT_USE_REMOTE_CONNECTION", INT2NUM(MYSQL_OPT_USE_REMOTE_CONNECTION)); 2056 | rb_define_const(cMysql, "SET_CLIENT_IP", INT2NUM(MYSQL_SET_CLIENT_IP)); 2057 | #endif 2058 | rb_define_const(cMysql, "REFRESH_GRANT", INT2NUM(REFRESH_GRANT)); 2059 | rb_define_const(cMysql, "REFRESH_LOG", INT2NUM(REFRESH_LOG)); 2060 | rb_define_const(cMysql, "REFRESH_TABLES", INT2NUM(REFRESH_TABLES)); 2061 | #ifdef REFRESH_HOSTS 2062 | rb_define_const(cMysql, "REFRESH_HOSTS", INT2NUM(REFRESH_HOSTS)); 2063 | #endif 2064 | #ifdef REFRESH_STATUS 2065 | rb_define_const(cMysql, "REFRESH_STATUS", INT2NUM(REFRESH_STATUS)); 2066 | #endif 2067 | #ifdef REFRESH_THREADS 2068 | rb_define_const(cMysql, "REFRESH_THREADS", INT2NUM(REFRESH_THREADS)); 2069 | #endif 2070 | #ifdef REFRESH_SLAVE 2071 | rb_define_const(cMysql, "REFRESH_SLAVE", INT2NUM(REFRESH_SLAVE)); 2072 | #endif 2073 | #ifdef REFRESH_MASTER 2074 | rb_define_const(cMysql, "REFRESH_MASTER", INT2NUM(REFRESH_MASTER)); 2075 | #endif 2076 | #ifdef CLIENT_LONG_PASSWORD 2077 | #endif 2078 | #ifdef CLIENT_FOUND_ROWS 2079 | rb_define_const(cMysql, "CLIENT_FOUND_ROWS", INT2NUM(CLIENT_FOUND_ROWS)); 2080 | #endif 2081 | #ifdef CLIENT_LONG_FLAG 2082 | #endif 2083 | #ifdef CLIENT_CONNECT_WITH_DB 2084 | #endif 2085 | #ifdef CLIENT_NO_SCHEMA 2086 | rb_define_const(cMysql, "CLIENT_NO_SCHEMA", INT2NUM(CLIENT_NO_SCHEMA)); 2087 | #endif 2088 | #ifdef CLIENT_COMPRESS 2089 | rb_define_const(cMysql, "CLIENT_COMPRESS", INT2NUM(CLIENT_COMPRESS)); 2090 | #endif 2091 | #ifdef CLIENT_ODBC 2092 | rb_define_const(cMysql, "CLIENT_ODBC", INT2NUM(CLIENT_ODBC)); 2093 | #endif 2094 | #ifdef CLIENT_LOCAL_FILES 2095 | rb_define_const(cMysql, "CLIENT_LOCAL_FILES", INT2NUM(CLIENT_LOCAL_FILES)); 2096 | #endif 2097 | #ifdef CLIENT_IGNORE_SPACE 2098 | rb_define_const(cMysql, "CLIENT_IGNORE_SPACE", INT2NUM(CLIENT_IGNORE_SPACE)); 2099 | #endif 2100 | #ifdef CLIENT_CHANGE_USER 2101 | rb_define_const(cMysql, "CLIENT_CHANGE_USER", INT2NUM(CLIENT_CHANGE_USER)); 2102 | #endif 2103 | #ifdef CLIENT_INTERACTIVE 2104 | rb_define_const(cMysql, "CLIENT_INTERACTIVE", INT2NUM(CLIENT_INTERACTIVE)); 2105 | #endif 2106 | #ifdef CLIENT_SSL 2107 | rb_define_const(cMysql, "CLIENT_SSL", INT2NUM(CLIENT_SSL)); 2108 | #endif 2109 | #ifdef CLIENT_IGNORE_SIGPIPE 2110 | rb_define_const(cMysql, "CLIENT_IGNORE_SIGPIPE", INT2NUM(CLIENT_IGNORE_SIGPIPE)); 2111 | #endif 2112 | #ifdef CLIENT_TRANSACTIONS 2113 | rb_define_const(cMysql, "CLIENT_TRANSACTIONS", INT2NUM(CLIENT_TRANSACTIONS)); 2114 | #endif 2115 | #ifdef CLIENT_MULTI_STATEMENTS 2116 | rb_define_const(cMysql, "CLIENT_MULTI_STATEMENTS", INT2NUM(CLIENT_MULTI_STATEMENTS)); 2117 | #endif 2118 | #ifdef CLIENT_MULTI_RESULTS 2119 | rb_define_const(cMysql, "CLIENT_MULTI_RESULTS", INT2NUM(CLIENT_MULTI_RESULTS)); 2120 | #endif 2121 | #if MYSQL_VERSION_ID >= 40101 2122 | rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_ON", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON)); 2123 | rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_OFF", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF)); 2124 | #endif 2125 | 2126 | /* Mysql::Result object method */ 2127 | rb_define_method(cMysqlRes, "data_seek", data_seek, 1); 2128 | rb_define_method(cMysqlRes, "fetch_field", fetch_field, 0); 2129 | rb_define_method(cMysqlRes, "fetch_fields", fetch_fields, 0); 2130 | rb_define_method(cMysqlRes, "fetch_field_direct", fetch_field_direct, 1); 2131 | rb_define_method(cMysqlRes, "fetch_lengths", fetch_lengths, 0); 2132 | rb_define_method(cMysqlRes, "fetch_row", fetch_row, 0); 2133 | rb_define_method(cMysqlRes, "fetch_hash", fetch_hash, -1); 2134 | rb_define_method(cMysqlRes, "field_seek", field_seek, 1); 2135 | rb_define_method(cMysqlRes, "field_tell", field_tell, 0); 2136 | rb_define_method(cMysqlRes, "free", res_free, 0); 2137 | rb_define_method(cMysqlRes, "num_fields", num_fields, 0); 2138 | rb_define_method(cMysqlRes, "num_rows", num_rows, 0); 2139 | rb_define_method(cMysqlRes, "row_seek", row_seek, 1); 2140 | rb_define_method(cMysqlRes, "row_tell", row_tell, 0); 2141 | rb_define_method(cMysqlRes, "each", each, 0); 2142 | rb_define_method(cMysqlRes, "each_hash", each_hash, -1); 2143 | 2144 | /* MysqlField object method */ 2145 | rb_define_method(cMysqlField, "name", field_name, 0); 2146 | rb_define_method(cMysqlField, "table", field_table, 0); 2147 | rb_define_method(cMysqlField, "def", field_def, 0); 2148 | rb_define_method(cMysqlField, "type", field_type, 0); 2149 | rb_define_method(cMysqlField, "length", field_length, 0); 2150 | rb_define_method(cMysqlField, "max_length", field_max_length, 0); 2151 | rb_define_method(cMysqlField, "flags", field_flags, 0); 2152 | rb_define_method(cMysqlField, "decimals", field_decimals, 0); 2153 | rb_define_method(cMysqlField, "hash", field_hash, 0); 2154 | rb_define_method(cMysqlField, "inspect", field_inspect, 0); 2155 | #ifdef IS_NUM 2156 | rb_define_method(cMysqlField, "is_num?", field_is_num, 0); 2157 | #endif 2158 | #ifdef IS_NOT_NULL 2159 | rb_define_method(cMysqlField, "is_not_null?", field_is_not_null, 0); 2160 | #endif 2161 | #ifdef IS_PRI_KEY 2162 | rb_define_method(cMysqlField, "is_pri_key?", field_is_pri_key, 0); 2163 | #endif 2164 | 2165 | /* Mysql::Field constant: TYPE */ 2166 | rb_define_const(cMysqlField, "TYPE_TINY", INT2NUM(FIELD_TYPE_TINY)); 2167 | #if MYSQL_VERSION_ID >= 32115 2168 | rb_define_const(cMysqlField, "TYPE_ENUM", INT2NUM(FIELD_TYPE_ENUM)); 2169 | #endif 2170 | rb_define_const(cMysqlField, "TYPE_DECIMAL", INT2NUM(FIELD_TYPE_DECIMAL)); 2171 | rb_define_const(cMysqlField, "TYPE_SHORT", INT2NUM(FIELD_TYPE_SHORT)); 2172 | rb_define_const(cMysqlField, "TYPE_LONG", INT2NUM(FIELD_TYPE_LONG)); 2173 | rb_define_const(cMysqlField, "TYPE_FLOAT", INT2NUM(FIELD_TYPE_FLOAT)); 2174 | rb_define_const(cMysqlField, "TYPE_DOUBLE", INT2NUM(FIELD_TYPE_DOUBLE)); 2175 | rb_define_const(cMysqlField, "TYPE_NULL", INT2NUM(FIELD_TYPE_NULL)); 2176 | rb_define_const(cMysqlField, "TYPE_TIMESTAMP", INT2NUM(FIELD_TYPE_TIMESTAMP)); 2177 | rb_define_const(cMysqlField, "TYPE_LONGLONG", INT2NUM(FIELD_TYPE_LONGLONG)); 2178 | rb_define_const(cMysqlField, "TYPE_INT24", INT2NUM(FIELD_TYPE_INT24)); 2179 | rb_define_const(cMysqlField, "TYPE_DATE", INT2NUM(FIELD_TYPE_DATE)); 2180 | rb_define_const(cMysqlField, "TYPE_TIME", INT2NUM(FIELD_TYPE_TIME)); 2181 | rb_define_const(cMysqlField, "TYPE_DATETIME", INT2NUM(FIELD_TYPE_DATETIME)); 2182 | #if MYSQL_VERSION_ID >= 32130 2183 | rb_define_const(cMysqlField, "TYPE_YEAR", INT2NUM(FIELD_TYPE_YEAR)); 2184 | #endif 2185 | #if MYSQL_VERSION_ID >= 50003 2186 | rb_define_const(cMysqlField, "TYPE_BIT", INT2NUM(FIELD_TYPE_BIT)); 2187 | rb_define_const(cMysqlField, "TYPE_NEWDECIMAL", INT2NUM(FIELD_TYPE_NEWDECIMAL)); 2188 | #endif 2189 | rb_define_const(cMysqlField, "TYPE_SET", INT2NUM(FIELD_TYPE_SET)); 2190 | rb_define_const(cMysqlField, "TYPE_BLOB", INT2NUM(FIELD_TYPE_BLOB)); 2191 | rb_define_const(cMysqlField, "TYPE_STRING", INT2NUM(FIELD_TYPE_STRING)); 2192 | #if MYSQL_VERSION_ID >= 40000 2193 | rb_define_const(cMysqlField, "TYPE_VAR_STRING", INT2NUM(FIELD_TYPE_VAR_STRING)); 2194 | #endif 2195 | rb_define_const(cMysqlField, "TYPE_CHAR", INT2NUM(FIELD_TYPE_CHAR)); 2196 | 2197 | /* Mysql::Field constant: FLAG */ 2198 | rb_define_const(cMysqlField, "NOT_NULL_FLAG", INT2NUM(NOT_NULL_FLAG)); 2199 | rb_define_const(cMysqlField, "PRI_KEY_FLAG", INT2NUM(PRI_KEY_FLAG)); 2200 | rb_define_const(cMysqlField, "UNIQUE_KEY_FLAG", INT2NUM(UNIQUE_KEY_FLAG)); 2201 | rb_define_const(cMysqlField, "MULTIPLE_KEY_FLAG", INT2NUM(MULTIPLE_KEY_FLAG)); 2202 | rb_define_const(cMysqlField, "BLOB_FLAG", INT2NUM(BLOB_FLAG)); 2203 | rb_define_const(cMysqlField, "UNSIGNED_FLAG", INT2NUM(UNSIGNED_FLAG)); 2204 | rb_define_const(cMysqlField, "ZEROFILL_FLAG", INT2NUM(ZEROFILL_FLAG)); 2205 | rb_define_const(cMysqlField, "BINARY_FLAG", INT2NUM(BINARY_FLAG)); 2206 | #ifdef ENUM_FLAG 2207 | rb_define_const(cMysqlField, "ENUM_FLAG", INT2NUM(ENUM_FLAG)); 2208 | #endif 2209 | #ifdef AUTO_INCREMENT_FLAG 2210 | rb_define_const(cMysqlField, "AUTO_INCREMENT_FLAG", INT2NUM(AUTO_INCREMENT_FLAG)); 2211 | #endif 2212 | #ifdef TIMESTAMP_FLAG 2213 | rb_define_const(cMysqlField, "TIMESTAMP_FLAG", INT2NUM(TIMESTAMP_FLAG)); 2214 | #endif 2215 | #ifdef SET_FLAG 2216 | rb_define_const(cMysqlField, "SET_FLAG", INT2NUM(SET_FLAG)); 2217 | #endif 2218 | #ifdef NUM_FLAG 2219 | rb_define_const(cMysqlField, "NUM_FLAG", INT2NUM(NUM_FLAG)); 2220 | #endif 2221 | #ifdef PART_KEY_FLAG 2222 | rb_define_const(cMysqlField, "PART_KEY_FLAG", INT2NUM(PART_KEY_FLAG)); 2223 | #endif 2224 | 2225 | #if MYSQL_VERSION_ID >= 40102 2226 | /* Mysql::Stmt object method */ 2227 | rb_define_method(cMysqlStmt, "affected_rows", stmt_affected_rows, 0); 2228 | #if 0 2229 | rb_define_method(cMysqlStmt, "attr_get", stmt_attr_get, 1); 2230 | rb_define_method(cMysqlStmt, "attr_set", stmt_attr_set, 2); 2231 | #endif 2232 | rb_define_method(cMysqlStmt, "bind_result", stmt_bind_result, -1); 2233 | rb_define_method(cMysqlStmt, "close", stmt_close, 0); 2234 | rb_define_method(cMysqlStmt, "data_seek", stmt_data_seek, 1); 2235 | rb_define_method(cMysqlStmt, "each", stmt_each, 0); 2236 | rb_define_method(cMysqlStmt, "execute", stmt_execute, -1); 2237 | rb_define_method(cMysqlStmt, "fetch", stmt_fetch, 0); 2238 | rb_define_method(cMysqlStmt, "field_count", stmt_field_count, 0); 2239 | rb_define_method(cMysqlStmt, "free_result", stmt_free_result, 0); 2240 | rb_define_method(cMysqlStmt, "insert_id", stmt_insert_id, 0); 2241 | rb_define_method(cMysqlStmt, "num_rows", stmt_num_rows, 0); 2242 | rb_define_method(cMysqlStmt, "param_count", stmt_param_count, 0); 2243 | rb_define_method(cMysqlStmt, "prepare", stmt_prepare, 1); 2244 | #if 0 2245 | rb_define_method(cMysqlStmt, "reset", stmt_reset, 0); 2246 | #endif 2247 | rb_define_method(cMysqlStmt, "result_metadata", stmt_result_metadata, 0); 2248 | rb_define_method(cMysqlStmt, "row_seek", stmt_row_seek, 1); 2249 | rb_define_method(cMysqlStmt, "row_tell", stmt_row_tell, 0); 2250 | #if 0 2251 | rb_define_method(cMysqlStmt, "send_long_data", stmt_send_long_data, 2); 2252 | #endif 2253 | rb_define_method(cMysqlStmt, "sqlstate", stmt_sqlstate, 0); 2254 | 2255 | #if 0 2256 | rb_define_const(cMysqlStmt, "ATTR_UPDATE_MAX_LENGTH", INT2NUM(STMT_ATTR_UPDATE_MAX_LENGTH)); 2257 | #endif 2258 | 2259 | /* Mysql::Time object method */ 2260 | rb_define_method(cMysqlTime, "initialize", time_initialize, -1); 2261 | rb_define_method(cMysqlTime, "inspect", time_inspect, 0); 2262 | rb_define_method(cMysqlTime, "to_s", time_to_s, 0); 2263 | rb_define_method(cMysqlTime, "year", time_get_year, 0); 2264 | rb_define_method(cMysqlTime, "month", time_get_month, 0); 2265 | rb_define_method(cMysqlTime, "day", time_get_day, 0); 2266 | rb_define_method(cMysqlTime, "hour", time_get_hour, 0); 2267 | rb_define_method(cMysqlTime, "minute", time_get_minute, 0); 2268 | rb_define_method(cMysqlTime, "second", time_get_second, 0); 2269 | rb_define_method(cMysqlTime, "neg", time_get_neg, 0); 2270 | rb_define_method(cMysqlTime, "second_part", time_get_second_part, 0); 2271 | rb_define_method(cMysqlTime, "year=", time_set_year, 1); 2272 | rb_define_method(cMysqlTime, "month=", time_set_month, 1); 2273 | rb_define_method(cMysqlTime, "day=", time_set_day, 1); 2274 | rb_define_method(cMysqlTime, "hour=", time_set_hour, 1); 2275 | rb_define_method(cMysqlTime, "minute=", time_set_minute, 1); 2276 | rb_define_method(cMysqlTime, "second=", time_set_second, 1); 2277 | rb_define_method(cMysqlTime, "neg=", time_set_neg, 1); 2278 | rb_define_method(cMysqlTime, "second_part=", time_set_second_part, 1); 2279 | rb_define_method(cMysqlTime, "==", time_equal, 1); 2280 | 2281 | #endif 2282 | 2283 | /* Mysql::Error object method */ 2284 | rb_define_method(eMysql, "error", error_error, 0); 2285 | rb_define_method(eMysql, "errno", error_errno, 0); 2286 | rb_define_method(eMysql, "sqlstate", error_sqlstate, 0); 2287 | 2288 | /* Mysql::Error constant */ 2289 | #define rb_define_mysql_const(s) rb_define_const(eMysql, #s, INT2NUM(s)) 2290 | #include "error_const.h" 2291 | } 2292 | --------------------------------------------------------------------------------