knjrbfw 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. data/VERSION +1 -1
  2. data/knjrbfw.gemspec +29 -8
  3. data/lib/knj/arrayext.rb +206 -153
  4. data/lib/knj/autoload/backups/ping.rb +2 -2
  5. data/lib/knj/autoload/erubis.rb +3 -3
  6. data/lib/knj/autoload/facets_dictionary.rb +2 -2
  7. data/lib/knj/autoload/gettext.rb +3 -3
  8. data/lib/knj/autoload/gtk2.rb +1 -1
  9. data/lib/knj/autoload/json.rb +14 -0
  10. data/lib/knj/autoload/magick.rb +3 -3
  11. data/lib/knj/autoload/mysql.rb +3 -3
  12. data/lib/knj/autoload/parsedate.rb +1 -1
  13. data/lib/knj/autoload/ping.rb +2 -2
  14. data/lib/knj/autoload/rexml.rb +5 -5
  15. data/lib/knj/autoload/soap.rb +1 -1
  16. data/lib/knj/autoload/sqlite3.rb +3 -3
  17. data/lib/knj/autoload/tmail.rb +3 -3
  18. data/lib/knj/autoload/xmlsimple.rb +3 -3
  19. data/lib/knj/autoload/zip.rb +3 -3
  20. data/lib/knj/autoload.rb +87 -81
  21. data/lib/knj/cmd_gen.rb +19 -19
  22. data/lib/knj/cmd_parser.rb +59 -0
  23. data/lib/knj/compiler.rb +34 -34
  24. data/lib/knj/cpufreq.rb +37 -37
  25. data/lib/knj/csv.rb +20 -0
  26. data/lib/knj/datarow.rb +406 -239
  27. data/lib/knj/datarow_custom.rb +124 -0
  28. data/lib/knj/datestamp.rb +89 -89
  29. data/lib/knj/datet.rb +550 -454
  30. data/lib/knj/db.rb +1 -0
  31. data/lib/knj/degulesider.rb +42 -44
  32. data/lib/knj/erb/erb.rb +5 -5
  33. data/lib/knj/erb/erb_cache_clean.rb +10 -10
  34. data/lib/knj/erb/erb_fcgi.rb +32 -32
  35. data/lib/knj/erb/erb_fcgi_1.9.rb +32 -32
  36. data/lib/knj/erb/erb_fcgi_jruby.rb +2 -2
  37. data/lib/knj/erb/erb_jruby.rb +5 -5
  38. data/lib/knj/erb/include.rb +243 -243
  39. data/lib/knj/errors.rb +19 -18
  40. data/lib/knj/eruby.rb +12 -10
  41. data/lib/knj/event_filemod.rb +31 -31
  42. data/lib/knj/event_handler.rb +73 -67
  43. data/lib/knj/exchangerates.rb +37 -37
  44. data/lib/knj/facebook_connect.rb +95 -18
  45. data/lib/knj/filesystem.rb +6 -6
  46. data/lib/knj/fs/drivers/filesystem.rb +12 -12
  47. data/lib/knj/fs/drivers/ftp.rb +31 -31
  48. data/lib/knj/fs/drivers/ssh.rb +26 -26
  49. data/lib/knj/fs/fs.rb +31 -31
  50. data/lib/knj/gettext_fallback.rb +15 -15
  51. data/lib/knj/gettext_threadded.rb +75 -75
  52. data/lib/knj/google_sitemap.rb +53 -53
  53. data/lib/knj/gtk2.rb +272 -272
  54. data/lib/knj/gtk2_cb.rb +80 -80
  55. data/lib/knj/gtk2_menu.rb +55 -55
  56. data/lib/knj/gtk2_statuswindow.rb +62 -62
  57. data/lib/knj/gtk2_tv.rb +58 -58
  58. data/lib/knj/hash_methods.rb +27 -36
  59. data/lib/knj/http.rb +189 -167
  60. data/lib/knj/http2.rb +259 -53
  61. data/lib/knj/image.rb +2 -2
  62. data/lib/knj/includes/appserver_cli.rb +18 -18
  63. data/lib/knj/includes/require_info.rb +15 -0
  64. data/lib/knj/ip2location.rb +20 -20
  65. data/lib/knj/ironruby-gtk2/button.rb +14 -14
  66. data/lib/knj/ironruby-gtk2/dialog.rb +42 -42
  67. data/lib/knj/ironruby-gtk2/entry.rb +4 -4
  68. data/lib/knj/ironruby-gtk2/gdk_event.rb +1 -1
  69. data/lib/knj/ironruby-gtk2/gdk_eventbutton.rb +11 -11
  70. data/lib/knj/ironruby-gtk2/gdk_pixbuf.rb +9 -9
  71. data/lib/knj/ironruby-gtk2/gladexml.rb +102 -102
  72. data/lib/knj/ironruby-gtk2/glib.rb +13 -13
  73. data/lib/knj/ironruby-gtk2/gtk2.rb +121 -121
  74. data/lib/knj/ironruby-gtk2/gtk_builder.rb +29 -29
  75. data/lib/knj/ironruby-gtk2/gtk_cellrenderertext.rb +3 -3
  76. data/lib/knj/ironruby-gtk2/gtk_combobox.rb +17 -17
  77. data/lib/knj/ironruby-gtk2/gtk_filechooserbutton.rb +3 -3
  78. data/lib/knj/ironruby-gtk2/gtk_liststore.rb +16 -16
  79. data/lib/knj/ironruby-gtk2/gtk_menu.rb +3 -3
  80. data/lib/knj/ironruby-gtk2/gtk_menuitem.rb +2 -2
  81. data/lib/knj/ironruby-gtk2/gtk_statusicon.rb +3 -3
  82. data/lib/knj/ironruby-gtk2/gtk_treeiter.rb +22 -22
  83. data/lib/knj/ironruby-gtk2/gtk_treeselection.rb +11 -11
  84. data/lib/knj/ironruby-gtk2/gtk_treeview.rb +17 -17
  85. data/lib/knj/ironruby-gtk2/gtk_treeviewcolumn.rb +30 -30
  86. data/lib/knj/ironruby-gtk2/iconsize.rb +1 -1
  87. data/lib/knj/ironruby-gtk2/image.rb +13 -13
  88. data/lib/knj/ironruby-gtk2/label.rb +17 -17
  89. data/lib/knj/ironruby-gtk2/stock.rb +2 -2
  90. data/lib/knj/ironruby-gtk2/tests/test_2.rb +14 -14
  91. data/lib/knj/ironruby-gtk2/tests/test_ironruby_window.rb +37 -37
  92. data/lib/knj/ironruby-gtk2/vbox.rb +3 -3
  93. data/lib/knj/ironruby-gtk2/window.rb +18 -18
  94. data/lib/knj/jruby-gtk2/builder/test_builder.rb +11 -11
  95. data/lib/knj/jruby-gtk2/builder.rb +25 -25
  96. data/lib/knj/jruby-gtk2/cellrenderertext.rb +10 -10
  97. data/lib/knj/jruby-gtk2/checkbutton.rb +1 -1
  98. data/lib/knj/jruby-gtk2/combobox.rb +27 -27
  99. data/lib/knj/jruby-gtk2/dialog.rb +40 -40
  100. data/lib/knj/jruby-gtk2/eventbutton.rb +19 -19
  101. data/lib/knj/jruby-gtk2/gladexml.rb +97 -97
  102. data/lib/knj/jruby-gtk2/gtk2.rb +203 -203
  103. data/lib/knj/jruby-gtk2/hbox.rb +8 -8
  104. data/lib/knj/jruby-gtk2/iconsize.rb +3 -3
  105. data/lib/knj/jruby-gtk2/image.rb +8 -8
  106. data/lib/knj/jruby-gtk2/liststore.rb +54 -54
  107. data/lib/knj/jruby-gtk2/menu.rb +35 -35
  108. data/lib/knj/jruby-gtk2/progressbar.rb +10 -10
  109. data/lib/knj/jruby-gtk2/statusicon.rb +3 -3
  110. data/lib/knj/jruby-gtk2/stock.rb +6 -6
  111. data/lib/knj/jruby-gtk2/tests/test_glade_window.rb +36 -36
  112. data/lib/knj/jruby-gtk2/tests/test_normal_window.rb +3 -3
  113. data/lib/knj/jruby-gtk2/tests/test_trayicon.rb +2 -2
  114. data/lib/knj/jruby-gtk2/treeview.rb +88 -88
  115. data/lib/knj/jruby-gtk2/vbox.rb +10 -10
  116. data/lib/knj/jruby-gtk2/window.rb +7 -7
  117. data/lib/knj/jruby_compiler.rb +12 -12
  118. data/lib/knj/knj.rb +12 -11
  119. data/lib/knj/knj_controller.rb +13 -8
  120. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql.rb +499 -316
  121. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_columns.rb +127 -125
  122. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_indexes.rb +43 -25
  123. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_tables.rb +316 -241
  124. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3.rb +12 -0
  125. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_columns.rb +146 -146
  126. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_indexes.rb +24 -24
  127. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_tables.rb +283 -283
  128. data/lib/knj/knjdb/libknjdb.rb +96 -52
  129. data/lib/knj/knjdb/libknjdb_java_sqlite3.rb +78 -78
  130. data/lib/knj/knjdb/libknjdb_row.rb +147 -147
  131. data/lib/knj/knjdb/libknjdb_sqlite3_ironruby.rb +61 -61
  132. data/lib/knj/knjdb/revision.rb +262 -0
  133. data/lib/knj/libqt.rb +69 -69
  134. data/lib/knj/libqt_window.rb +8 -8
  135. data/lib/knj/locales.rb +62 -52
  136. data/lib/knj/maemo/fremantle-calendar/fremantle-calendar.rb +54 -54
  137. data/lib/knj/mail.rb +73 -73
  138. data/lib/knj/mailobj.rb +82 -80
  139. data/lib/knj/mount.rb +113 -113
  140. data/lib/knj/notify.rb +11 -11
  141. data/lib/knj/nvidia_settings.rb +43 -43
  142. data/lib/knj/objects/objects_sqlhelper.rb +474 -0
  143. data/lib/knj/objects.rb +569 -793
  144. data/lib/knj/opts.rb +38 -38
  145. data/lib/knj/os.rb +176 -158
  146. data/lib/knj/php.rb +853 -683
  147. data/lib/knj/php_parser/arguments.rb +3 -3
  148. data/lib/knj/php_parser/functions.rb +95 -95
  149. data/lib/knj/php_parser/php_parser.rb +16 -16
  150. data/lib/knj/php_parser/tests/test.rb +6 -6
  151. data/lib/knj/php_parser/tests/test_function_run.rb +6 -6
  152. data/lib/knj/power_manager.rb +29 -29
  153. data/lib/knj/process.rb +457 -0
  154. data/lib/knj/process_meta.rb +400 -0
  155. data/lib/knj/rand.rb +8 -8
  156. data/lib/knj/retry.rb +69 -69
  157. data/lib/knj/rhodes/delegate.rb +414 -0
  158. data/lib/knj/rhodes/rhodes.rb +114 -40
  159. data/lib/knj/rhodes/weakref.rb +80 -0
  160. data/lib/knj/rsvgbin.rb +18 -18
  161. data/lib/knj/scripts/degulesider.rb +2 -2
  162. data/lib/knj/scripts/filesearch.rb +35 -35
  163. data/lib/knj/scripts/ip2location.rb +2 -2
  164. data/lib/knj/scripts/keepalive.rb +2 -2
  165. data/lib/knj/scripts/php_to_rb_helper.rb +376 -0
  166. data/lib/knj/scripts/process_meta_exec.rb +104 -0
  167. data/lib/knj/scripts/svn_merge.rb +21 -21
  168. data/lib/knj/scripts/upgrade_knjrbfw_checker.rb +26 -26
  169. data/lib/knj/sms.rb +52 -52
  170. data/lib/knj/sshrobot/sshrobot.rb +90 -88
  171. data/lib/knj/sshrobot.rb +1 -0
  172. data/lib/knj/strings.rb +186 -74
  173. data/lib/knj/sysuser.rb +25 -25
  174. data/lib/knj/table_writer.rb +97 -0
  175. data/lib/knj/tests/compiler/compiler_test.rb +2 -2
  176. data/lib/knj/tests/test_degulesider.rb +1 -1
  177. data/lib/knj/tests/test_http2_proxy.rb +26 -0
  178. data/lib/knj/tests/test_mount.rb +9 -9
  179. data/lib/knj/tests/test_retry.rb +17 -17
  180. data/lib/knj/thread.rb +23 -24
  181. data/lib/knj/thread2.rb +45 -45
  182. data/lib/knj/threadhandler.rb +135 -102
  183. data/lib/knj/threadpool.rb +195 -145
  184. data/lib/knj/translations.rb +128 -119
  185. data/lib/knj/unix_proc.rb +80 -80
  186. data/lib/knj/web.rb +947 -881
  187. data/lib/knj/webscripts/image.rhtml +142 -67
  188. data/lib/knj/win.rb +2 -2
  189. data/lib/knj/win_registry.rb +58 -58
  190. data/lib/knj/win_tightvnc.rb +125 -125
  191. data/lib/knj/wref.rb +104 -0
  192. data/lib/knj/x11vnc.rb +46 -46
  193. data/lib/knj/youtube.rb +33 -36
  194. data/lib/knjrbfw.rb +1 -0
  195. data/spec/cmd_parser_spec.rb +25 -0
  196. data/spec/db_spec.rb +40 -0
  197. data/spec/db_spec_encoding_test_file.txt +1 -0
  198. data/spec/http2_spec.rb +37 -0
  199. data/spec/knjrbfw_spec.rb +17 -15
  200. data/spec/php_spec.rb +69 -0
  201. data/spec/process_meta_spec.rb +150 -0
  202. data/spec/process_spec.rb +107 -0
  203. data/spec/strings_spec.rb +21 -0
  204. data/spec/web_spec.rb +16 -0
  205. metadata +42 -21
  206. data/lib/knj/autoload/json_autoload.rb +0 -7
  207. data/lib/knj/autoload/twitter.rb +0 -2
  208. data/lib/knj/ext/webrick.rb +0 -31
  209. data/lib/knj/jruby-gtk2/gtk-4.0.jar +0 -0
  210. data/lib/knj/knjdb/mysql-connector-java-5.1.13-bin.jar +0 -0
  211. data/lib/knj/knjdb/sqlitejdbc-v056.jar +0 -0
@@ -1,327 +1,510 @@
1
1
  class KnjDB_mysql
2
- attr_reader :knjdb, :conn, :escape_table, :escape_col, :escape_val, :esc_table
3
- attr_accessor :tables, :cols, :indexes
4
-
5
- def initialize(knjdb_ob)
6
- @knjdb = knjdb_ob
7
- @encoding = @knjdb.opts[:encoding]
8
- @escape_table = "`"
9
- @escape_col = "`"
10
- @escape_val = "'"
11
- @esc_table = "`"
12
- @esc_col = "`"
13
- @mutex = Mutex.new
14
-
15
- if @knjdb.opts.key?(:port)
16
- @port = @knjdb.opts[:port].to_i
17
- else
18
- @port = 3306
19
- end
20
-
21
- @subtype = @knjdb.opts[:subtype]
22
- reconnect
23
- end
24
-
25
- def reconnect
26
- if !@subtype or @subtype == "mysql"
27
- @conn = Mysql.real_connect(@knjdb.opts[:host], @knjdb.opts[:user], @knjdb.opts[:pass], @knjdb.opts[:db], @port)
28
- elsif @subtype == "mysql2"
29
- require "rubygems"
30
- require "mysql2"
31
-
32
- args = {
33
- :host => @knjdb.opts[:host],
34
- :username => @knjdb.opts[:user],
35
- :password => @knjdb.opts[:pass],
36
- :database => @knjdb.opts[:db],
37
- :port => @port,
38
- :symbolize_keys => true
39
- }
40
-
41
- @query_args = @knjdb.opts[:query_args]
42
- @query_args = {} if !@query_args
43
-
44
- pos_args = [:as, :async, :cast_booleans, :database_timezone, :application_timezone, :cache_rows, :connect_flags, :cast]
45
- pos_args.each do |key|
46
- args[key] = @knjdb.opts[key] if @knjdb.opts.key?(key)
47
- end
48
-
49
- @conn = Mysql2::Client.new(args)
50
- elsif @subtype == "java"
51
- if !@jdbc_loaded
52
- require "java"
53
-
54
- if File.exists?("/usr/share/java/mysql-connector-java.jar")
55
- require "/usr/share/java/mysql-connector-java.jar"
56
- else
57
- require File.dirname(__FILE__) + "/mysql-connector-java-5.1.13-bin.jar"
58
- end
59
-
60
- import "com.mysql.jdbc.Driver"
61
- @jdbc_loaded = true
62
- end
63
-
64
- @conn = java.sql::DriverManager.getConnection("jdbc:mysql://#{@knjdb.opts[:host]}:#{@port}/#{@knjdb.opts[:db]}?user=#{@knjdb.opts[:user]}&password=#{@knjdb.opts[:pass]}&populateInsertRowWithDefaultValues=true&zeroDateTimeBehavior=round")
65
- query("SET SQL_MODE = ''")
66
- else
67
- raise "Unknown subtype: #{@subtype}"
68
- end
69
-
70
- query_conn(@conn, "SET NAMES '#{esc(@encoding)}'") if @encoding
71
- end
72
-
73
- def query_conn(conn, str)
74
- if @subtype == "java"
75
- stmt = conn.createStatement
76
-
77
- if str.match(/insert\s+into\s+/i) or str.match(/update\s+/i) or str.match(/^\s*delete\s+/i) or str.match(/^\s*create\s*/i)
78
- return stmt.execute(str)
79
- else
80
- return stmt.executeQuery(str)
81
- end
82
- elsif conn.respond_to?(:query)
83
- return conn.query(str)
84
- else
85
- raise "Could not figure out the way to execute the query on #{conn.class.name}."
86
- end
87
- end
88
-
89
- def query(string)
90
- string = string.to_s
91
- string = string.force_encoding("UTF-8") if @encoding == "utf8" and string.respond_to?(:force_encoding)
92
-
93
- @mutex.synchronize do
94
- if !@subtype or @subtype == "mysql"
95
- begin
96
- return KnjDB_mysql_result.new(self, @conn.query(string))
97
- rescue Mysql::Error => e
98
- if e.message == "MySQL server has gone away"
99
- reconnect
100
- retry
101
- else
102
- raise e
103
- end
104
- end
105
- elsif @subtype == "mysql2"
106
- begin
107
- return KnjDB_mysql2_result.new(@conn.query(string, @query_args))
108
- rescue Mysql2::Error => e
109
- if e.message == "MySQL server has gone away" or e.message == "closed MySQL connection"
110
- reconnect
111
- retry
112
- elsif e.message == "This connection is still waiting for a result, try again once you have the result"
113
- sleep 0.1
114
- retry
115
- else
116
- print string
117
- raise e
118
- end
119
- end
120
- elsif @subtype == "java"
121
- begin
122
- return KnjDB_java_mysql_result.new(@knjdb, query_conn(@conn, string))
123
- rescue => e
124
- if e.to_s.index("No operations allowed after connection closed") != nil
125
- reconnect
126
- retry
127
- end
128
-
129
- raise e
130
- end
131
- else
132
- raise "Unknown subtype: '#{@subtype}'."
133
- end
134
- end
135
- end
136
-
137
- def escape(string)
138
- if !@subtype or @subtype == "mysql"
139
- return @conn.escape_string(string.to_s)
140
- elsif @subtype == "mysql2"
141
- return @conn.escape(string.to_s)
142
- elsif @subtype == "java"
143
- #This is copied from the Ruby/MySQL framework at: http://www.tmtm.org/en/ruby/mysql/
144
- return string.to_s.gsub(/([\0\n\r\032\'\"\\])/) do
145
- case $1
146
- when "\0" then "\\0"
147
- when "\n" then "\\n"
148
- when "\r" then "\\r"
149
- when "\032" then "\\Z"
150
- else "\\" + $1
151
- end
152
- end
153
- else
154
- raise "Unknown subtype: '#{@subtype}'."
155
- end
156
- end
157
-
158
- def esc_col(string)
159
- string = string.to_s
160
- raise "Invalid column-string: #{string}" if string.index(@escape_col) != nil
161
- return string
162
- end
163
-
164
- alias :esc_table :esc_col
165
- alias :esc :escape
166
-
167
- def lastID
168
- if !@subtype or @subtype == "mysql"
169
- @mutex.synchronize do
170
- return @conn.insert_id
171
- end
172
- elsif @subtype == "mysql2"
173
- @mutex.synchronize do
174
- return @conn.last_id
175
- end
176
- else
177
- data = self.query("SELECT LAST_INSERT_ID() AS id").fetch
178
- return data[:id] if data.key?(:id)
179
- raise "Could not figure out last inserted ID."
180
- end
181
- end
182
-
183
- def close
184
- @mutex.synchronize do
185
- @conn.close
186
- end
187
- end
188
-
189
- def destroy
190
- @conn = nil
191
- @knjdb = nil
192
- @mutex = nil
193
- @subtype = nil
194
- @encoding = nil
195
- @query_args = nil
196
- @port = nil
197
- end
198
-
199
- def insert_multi(tablename, arr_hashes)
200
- sql = "INSERT INTO `#{esc_table(tablename)}` ("
201
-
202
- first = true
203
- arr_hashes[0].keys.each do |col_name|
204
- sql += "," if !first
205
- first = false if first
206
- sql += "`#{esc_col(col_name)}`"
207
- end
208
-
209
- sql += ") VALUES ("
210
-
211
- first = true
212
- arr_hashes.each do |hash|
213
- sql += "),(" if !first
214
- first = false if first
215
-
216
- first_key = true
217
- hash.each do |key, val|
218
- sql += "," if !first_key
219
- first_key = false if first_key
220
- sql += "'#{esc(val)}'"
221
- end
222
- end
223
-
224
- sql += ")"
225
-
226
- query(sql)
227
- end
2
+ attr_reader :knjdb, :conn, :conns, :escape_table, :escape_col, :escape_val, :esc_table
3
+ attr_accessor :tables, :cols, :indexes
4
+
5
+ def initialize(knjdb_ob)
6
+ @knjdb = knjdb_ob
7
+ @opts = @knjdb.opts
8
+ @encoding = @opts[:encoding]
9
+ @escape_table = "`"
10
+ @escape_col = "`"
11
+ @escape_val = "'"
12
+ @esc_table = "`"
13
+ @esc_col = "`"
14
+ @mutex = Mutex.new
15
+
16
+ if @knjdb.opts.key?(:port)
17
+ @port = @knjdb.opts[:port].to_i
18
+ else
19
+ @port = 3306
20
+ end
21
+
22
+ @java_rs_data = {}
23
+ @subtype = @knjdb.opts[:subtype]
24
+ @subtype = "mysql" if @subtype.to_s.length <= 0
25
+ self.reconnect
26
+ end
27
+
28
+ #This method handels the closing of statements and results for the Java MySQL-mode.
29
+ def java_mysql_resultset_killer(id)
30
+ data = @java_rs_data[id]
31
+ return nil if !data
32
+
33
+ data[:res].close
34
+ data[:stmt].close
35
+ @java_rs_data.delete(id)
36
+ end
37
+
38
+ def reconnect
39
+ case @subtype
40
+ when "mysql"
41
+ @conn = Mysql.real_connect(@knjdb.opts[:host], @knjdb.opts[:user], @knjdb.opts[:pass], @knjdb.opts[:db], @port)
42
+ when "mysql2"
43
+ require "rubygems"
44
+ require "mysql2"
45
+
46
+ args = {
47
+ :host => @knjdb.opts[:host],
48
+ :username => @knjdb.opts[:user],
49
+ :password => @knjdb.opts[:pass],
50
+ :database => @knjdb.opts[:db],
51
+ :port => @port,
52
+ :symbolize_keys => true,
53
+ :cache_rows => false
54
+ }
55
+
56
+ #Symbolize keys should also be given here, else table-data wont be symbolized for some reason - knj.
57
+ @query_args = {:symbolize_keys => true}
58
+ @query_args.merge!(@knjdb.opts[:query_args]) if @knjdb.opts[:query_args]
59
+
60
+ pos_args = [:as, :async, :cast_booleans, :database_timezone, :application_timezone, :cache_rows, :connect_flags, :cast]
61
+ pos_args.each do |key|
62
+ args[key] = @knjdb.opts[key] if @knjdb.opts.key?(key)
63
+ end
64
+
65
+ tries = 0
66
+ begin
67
+ tries += 1
68
+ @conn = Mysql2::Client.new(args)
69
+ rescue => e
70
+ if tries <= 3
71
+ if e.message == "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)"
72
+ sleep 1
73
+ retry
74
+ end
75
+ end
76
+
77
+ raise e
78
+ end
79
+ when "java"
80
+ if !@jdbc_loaded
81
+ require "java"
82
+ require "/usr/share/java/mysql-connector-java.jar" if File.exists?("/usr/share/java/mysql-connector-java.jar")
83
+ import "com.mysql.jdbc.Driver"
84
+ @jdbc_loaded = true
85
+ end
86
+
87
+ @conn = java.sql::DriverManager.getConnection("jdbc:mysql://#{@knjdb.opts[:host]}:#{@port}/#{@knjdb.opts[:db]}?user=#{@knjdb.opts[:user]}&password=#{@knjdb.opts[:pass]}&populateInsertRowWithDefaultValues=true&zeroDateTimeBehavior=round")
88
+ query("SET SQL_MODE = ''")
89
+ else
90
+ raise "Unknown subtype: #{@subtype}"
91
+ end
92
+
93
+ self.query("SET NAMES '#{self.esc(@encoding)}'") if @encoding
94
+ end
95
+
96
+ #Executes a query and returns the result.
97
+ def query(str)
98
+ str = str.to_s
99
+ str = str.force_encoding("UTF-8") if @encoding == "utf8" and str.respond_to?(:force_encoding)
100
+ tries = 0
101
+
102
+ begin
103
+ tries += 1
104
+ @mutex.synchronize do
105
+ case @subtype
106
+ when "mysql"
107
+ return KnjDB_mysql_result.new(self, @conn.query(str))
108
+ when "mysql2"
109
+ return KnjDB_mysql2_result.new(@conn.query(str, @query_args))
110
+ when "java"
111
+ stmt = conn.createStatement
112
+
113
+ if str.match(/^\s*(delete|update|create|drop|insert\s+into)\s+/i)
114
+ begin
115
+ stmt.execute(str)
116
+ ensure
117
+ stmt.close
118
+ end
119
+
120
+ return nil
121
+ else
122
+ begin
123
+ res = stmt.executeQuery(str)
124
+ ret = KnjDB_java_mysql_result.new(@knjdb, @opts, res)
125
+
126
+ #Save reference to result and statement, so we can close them when they are garbage collected.
127
+ @java_rs_data[ret.__id__] = {:res => res, :stmt => stmt}
128
+ ObjectSpace.define_finalizer(ret, self.method("java_mysql_resultset_killer"))
129
+
130
+ return ret
131
+ rescue => e
132
+ res.close if res
133
+ stmt.close
134
+ raise e
135
+ end
136
+ end
137
+ else
138
+ raise "Unknown subtype: '#{@subtype}'."
139
+ end
140
+ end
141
+ rescue => e
142
+ if tries < 3
143
+ if e.message == "MySQL server has gone away" or e.message == "closed MySQL connection" or e.message == "Can't connect to local MySQL server through socket"
144
+ sleep 0.5
145
+ self.reconnect
146
+ retry
147
+ elsif e.message == "This connection is still waiting for a result, try again once you have the result"
148
+ sleep 0.1
149
+ retry
150
+ elsif e.to_s.index("No operations allowed after connection closed") != nil
151
+ self.reconnect
152
+ retry
153
+ end
154
+ end
155
+
156
+ print str
157
+ raise e
158
+ end
159
+ end
160
+
161
+ #Executes an unbuffered query and returns the result that can be used to access the data.
162
+ def query_ubuf(str)
163
+ @mutex.synchronize do
164
+ case @subtype
165
+ when "mysql"
166
+ conn.query_with_result = false
167
+ return KnjDB_mysql_unbuffered_result.new(@conn, @opts, @conn.query(str))
168
+ when "mysql2"
169
+ raise "MySQL2 does not support unbuffered queries yet! Waiting for :stream..."
170
+ when "java"
171
+ stmt = conn.createStatement
172
+
173
+ if str.match(/^\s*(delete|update|create|drop|insert\s+into)\s+/i)
174
+ begin
175
+ stmt.execute(str)
176
+ ensure
177
+ stmt.close
178
+ end
179
+
180
+ return nil
181
+ else
182
+ stmt.setFetchSize(500)
183
+
184
+ begin
185
+ res = stmt.executeQuery(str)
186
+ ret = KnjDB_java_mysql_result.new(@knjdb, @opts, res)
187
+
188
+ #Save reference to result and statement, so we can close them when they are garbage collected.
189
+ @java_rs_data[ret.__id__] = {:res => res, :stmt => stmt}
190
+ ObjectSpace.define_finalizer(ret, self.method("java_mysql_resultset_killer"))
191
+
192
+ return ret
193
+ rescue => e
194
+ res.close if res
195
+ stmt.close
196
+ raise e
197
+ end
198
+ end
199
+ raise "Not implemented yet."
200
+ else
201
+ raise "Unknown subtype: '#{@subtype}'"
202
+ end
203
+ end
204
+ end
205
+
206
+ #Escapes a string to be safe to use in a query.
207
+ def escape_alternative(string)
208
+ case @subtype
209
+ when "mysql"
210
+ return @conn.escape_string(string.to_s)
211
+ when "mysql2"
212
+ return @conn.escape(string.to_s)
213
+ when "java"
214
+ return self.escape(string)
215
+ else
216
+ raise "Unknown subtype: '#{@subtype}'."
217
+ end
218
+ end
219
+
220
+ #An alternative to the MySQL framework's escape. This is copied from the Ruby/MySQL framework at: http://www.tmtm.org/en/ruby/mysql/
221
+ def escape(string)
222
+ return string.to_s.gsub(/([\0\n\r\032\'\"\\])/) do
223
+ case $1
224
+ when "\0" then "\\0"
225
+ when "\n" then "\\n"
226
+ when "\r" then "\\r"
227
+ when "\032" then "\\Z"
228
+ else "\\" + $1
229
+ end
230
+ end
231
+ end
232
+
233
+ #Escapes a string to be safe to use as a column in a query.
234
+ def esc_col(string)
235
+ string = string.to_s
236
+ raise "Invalid column-string: #{string}" if string.index(@escape_col) != nil
237
+ return string
238
+ end
239
+
240
+ alias :esc_table :esc_col
241
+ alias :esc :escape
242
+
243
+ #Returns the last inserted ID for the connection.
244
+ def lastID
245
+ case @subtype
246
+ when "mysql"
247
+ @mutex.synchronize do
248
+ return @conn.insert_id
249
+ end
250
+ when "mysql2"
251
+ @mutex.synchronize do
252
+ return @conn.last_id
253
+ end
254
+ when "java"
255
+ data = self.query("SELECT LAST_INSERT_ID() AS id").fetch
256
+ return data[:id] if data.key?(:id)
257
+ raise "Could not figure out last inserted ID."
258
+ end
259
+ end
260
+
261
+ #Closes the connection threadsafe.
262
+ def close
263
+ @mutex.synchronize do
264
+ @conn.close
265
+ end
266
+ end
267
+
268
+ #Destroyes the connection.
269
+ def destroy
270
+ @conn = nil
271
+ @knjdb = nil
272
+ @mutex = nil
273
+ @subtype = nil
274
+ @encoding = nil
275
+ @query_args = nil
276
+ @port = nil
277
+ end
278
+
279
+ def insert_multi(tablename, arr_hashes)
280
+ sql = "INSERT INTO `#{self.esc_table(tablename)}` ("
281
+
282
+ first = true
283
+ arr_hashes.first.keys.each do |col_name|
284
+ sql << "," if !first
285
+ first = false if first
286
+ sql << "`#{self.esc_col(col_name)}`"
287
+ end
288
+
289
+ sql << ") VALUES ("
290
+
291
+ first = true
292
+ arr_hashes.each do |hash|
293
+ if first
294
+ first = false
295
+ else
296
+ sql << "),("
297
+ end
298
+
299
+ first_key = true
300
+ hash.each do |key, val|
301
+ if first_key
302
+ first_key = false
303
+ else
304
+ sql << ","
305
+ end
306
+
307
+ sql << "'#{self.escape(val)}'"
308
+ end
309
+ end
310
+
311
+ sql << ")"
312
+
313
+ self.query(sql)
314
+ end
228
315
  end
229
316
 
230
317
  class KnjDB_mysql_result
231
- def initialize(driver, result)
232
- @driver = driver
233
- @result = result
234
- @mutex = Mutex.new
235
-
236
- if @result
237
- @keys = []
238
- keys = @result.fetch_fields
239
- keys.each do |key|
240
- @keys << key.name.to_sym
241
- end
242
- end
243
- end
244
-
245
- def fetch
246
- return fetch_hash_symbols if @driver.knjdb.opts[:return_keys] == "symbols"
247
- return fetch_hash_strings
248
- end
249
-
250
- def fetch_hash_strings
251
- @mutex.synchronize do
252
- return @result.fetch_hash
253
- end
254
- end
255
-
256
- def fetch_hash_symbols
257
- @mutex.synchronize do
258
- fetched = @result.fetch_row
259
- return false if !fetched
260
-
261
- ret = {}
262
- count = 0
263
- @keys.each do |key|
264
- ret[key] = fetched[count]
265
- count += 1
266
- end
267
-
268
- return ret
269
- end
270
- end
318
+ def initialize(driver, result)
319
+ @driver = driver
320
+ @result = result
321
+ @mutex = Mutex.new
322
+
323
+ if @result
324
+ @keys = []
325
+ keys = @result.fetch_fields
326
+ keys.each do |key|
327
+ @keys << key.name.to_sym
328
+ end
329
+ end
330
+ end
331
+
332
+ def fetch
333
+ return self.fetch_hash_symbols if @driver.knjdb.opts[:return_keys] == "symbols"
334
+ return self.fetch_hash_strings
335
+ end
336
+
337
+ def fetch_hash_strings
338
+ @mutex.synchronize do
339
+ return @result.fetch_hash
340
+ end
341
+ end
342
+
343
+ def fetch_hash_symbols
344
+ fetched = nil
345
+ @mutex.synchronize do
346
+ fetched = @result.fetch_row
347
+ end
348
+
349
+ return false if !fetched
350
+
351
+ ret = {}
352
+ count = 0
353
+ @keys.each do |key|
354
+ ret[key] = fetched[count]
355
+ count += 1
356
+ end
357
+
358
+ return ret
359
+ end
360
+
361
+ def each
362
+ while data = self.fetch_hash_symbols
363
+ yield(data)
364
+ end
365
+ end
366
+ end
367
+
368
+ class KnjDB_mysql_unbuffered_result
369
+ def initialize(conn, opts, result)
370
+ @conn = conn
371
+ @result = result
372
+
373
+ if !opts.key?(:result) or opts[:result] == "hash"
374
+ @as_hash = true
375
+ elsif opts[:result] == "array"
376
+ @as_hash = false
377
+ else
378
+ raise "Unknown type of result: '#{opts[:result]}'."
379
+ end
380
+ end
381
+
382
+ def load_keys
383
+ @keys = []
384
+ keys = @res.fetch_fields
385
+ keys.each do |key|
386
+ @keys << key.name.to_sym
387
+ end
388
+ end
389
+
390
+ def fetch
391
+ if @enum
392
+ begin
393
+ ret = @enum.next
394
+ rescue StopIteration
395
+ @enum = nil
396
+ @res = nil
397
+ end
398
+ end
399
+
400
+ if !ret and !@res and !@enum
401
+ begin
402
+ @res = @conn.use_result
403
+ @enum = @res.to_enum
404
+ ret = @enum.next
405
+ rescue Mysql::Error
406
+ #Reset it to run non-unbuffered again and then return false.
407
+ @conn.query_with_result = true
408
+ return false
409
+ rescue StopIteration
410
+ sleep 0.1
411
+ retry
412
+ end
413
+ end
414
+
415
+ if !@as_hash
416
+ return ret
417
+ else
418
+ self.load_keys if !@keys
419
+
420
+ ret_h = {}
421
+ @keys.each_index do |key_no|
422
+ ret_h[@keys[key_no]] = ret[key_no]
423
+ end
424
+
425
+ return ret_h
426
+ end
427
+ end
428
+
429
+ def each
430
+ while data = self.fetch
431
+ yield(data)
432
+ end
433
+ end
271
434
  end
272
435
 
273
436
  class KnjDB_mysql2_result
274
- def initialize(result)
275
- @result = result.to_a
276
- @count = 0
277
- @mutex = Mutex.new
278
- end
279
-
280
- def fetch
281
- @mutex.synchronize do
282
- ret = @result[@count]
283
- return false if !ret
284
-
285
- realret = {}
286
- ret.each do |key, val|
287
- realret[key.to_sym] = val
288
- end
289
-
290
- @count += 1
291
- return realret
292
- end
293
- end
437
+ def initialize(result)
438
+ @result = result
439
+ end
440
+
441
+ def fetch
442
+ @enum = @result.to_enum if !@enum
443
+
444
+ begin
445
+ return @enum.next
446
+ rescue StopIteration
447
+ return false
448
+ end
449
+ end
450
+
451
+ def each(&block)
452
+ @result.each(&block)
453
+ end
294
454
  end
295
455
 
296
456
  class KnjDB_java_mysql_result
297
- def initialize(knjdb, result)
298
- @knjdb = knjdb
299
- @result = result
300
- @mutex = Mutex.new
301
- end
302
-
303
- def read_meta
304
- @result.before_first
305
- meta = @result.meta_data
306
-
307
- @keys = []
308
- 0.upto(meta.column_count - 1) do |count|
309
- @keys << meta.column_name(count + 1).to_sym
310
- end
311
- end
312
-
313
- def fetch
314
- @mutex.synchronize do
315
- read_meta if !@keys
316
- status = @result.next
317
- return false if !status
318
-
319
- ret = {}
320
- 0.upto(@keys.length - 1) do |count|
321
- ret[@keys[count].to_sym] = @result.string(count + 1)
322
- end
323
-
324
- return ret
325
- end
326
- end
457
+ def initialize(knjdb, opts, result)
458
+ @knjdb = knjdb
459
+ @result = result
460
+
461
+ if !opts.key?(:result) or opts[:result] == "hash"
462
+ @as_hash = true
463
+ elsif opts[:result] == "array"
464
+ @as_hash = false
465
+ else
466
+ raise "Unknown type of result: '#{opts[:result]}'."
467
+ end
468
+ end
469
+
470
+ #Reads meta-data about the query like keys and count.
471
+ def read_meta
472
+ @result.before_first
473
+ meta = @result.meta_data
474
+ @count = meta.column_count
475
+
476
+ @keys = []
477
+ 1.upto(@count) do |count|
478
+ @keys << meta.column_name(count).to_sym
479
+ end
480
+ end
481
+
482
+ def fetch
483
+ return false if !@result
484
+
485
+ self.read_meta if !@keys
486
+ status = @result.next
487
+
488
+ return false if !status
489
+
490
+ if @as_hash
491
+ ret = {}
492
+ 1.upto(@keys.length) do |count|
493
+ ret[@keys[count - 1]] = @result.string(count).to_s.encode("utf-8")
494
+ end
495
+ else
496
+ ret = []
497
+ 1.upto(@count) do |count|
498
+ ret << @result.string(count).to_s.encode("utf-8")
499
+ end
500
+ end
501
+
502
+ return ret
503
+ end
504
+
505
+ def each
506
+ while data = self.fetch
507
+ yield(data)
508
+ end
509
+ end
327
510
  end