activerecord-jdbc-adapter-onsite 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +14 -0
  3. data/Appraisals +16 -0
  4. data/Gemfile +11 -0
  5. data/Gemfile.lock +45 -0
  6. data/History.txt +488 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.rdoc +214 -0
  9. data/Rakefile +62 -0
  10. data/activerecord-jdbc-adapter.gemspec +23 -0
  11. data/bench/bench_attributes.rb +13 -0
  12. data/bench/bench_attributes_new.rb +14 -0
  13. data/bench/bench_create.rb +12 -0
  14. data/bench/bench_find_all.rb +12 -0
  15. data/bench/bench_find_all_mt.rb +25 -0
  16. data/bench/bench_model.rb +85 -0
  17. data/bench/bench_new.rb +12 -0
  18. data/bench/bench_new_valid.rb +12 -0
  19. data/bench/bench_valid.rb +13 -0
  20. data/gemfiles/rails23.gemfile +10 -0
  21. data/gemfiles/rails23.gemfile.lock +38 -0
  22. data/gemfiles/rails30.gemfile +9 -0
  23. data/gemfiles/rails30.gemfile.lock +33 -0
  24. data/gemfiles/rails31.gemfile +9 -0
  25. data/gemfiles/rails31.gemfile.lock +35 -0
  26. data/gemfiles/rails32.gemfile +9 -0
  27. data/gemfiles/rails32.gemfile.lock +35 -0
  28. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  31. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  32. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  33. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  34. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  35. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  36. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  37. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  39. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  40. data/lib/activerecord-jdbc-adapter.rb +8 -0
  41. data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
  42. data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
  43. data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
  44. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
  45. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
  46. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
  47. data/lib/arel/visitors/compat.rb +13 -0
  48. data/lib/arel/visitors/db2.rb +17 -0
  49. data/lib/arel/visitors/derby.rb +32 -0
  50. data/lib/arel/visitors/firebird.rb +24 -0
  51. data/lib/arel/visitors/hsqldb.rb +26 -0
  52. data/lib/arel/visitors/sql_server.rb +46 -0
  53. data/lib/arjdbc.rb +24 -0
  54. data/lib/arjdbc/db2.rb +2 -0
  55. data/lib/arjdbc/db2/adapter.rb +541 -0
  56. data/lib/arjdbc/derby.rb +7 -0
  57. data/lib/arjdbc/derby/adapter.rb +358 -0
  58. data/lib/arjdbc/derby/connection_methods.rb +19 -0
  59. data/lib/arjdbc/discover.rb +92 -0
  60. data/lib/arjdbc/firebird.rb +2 -0
  61. data/lib/arjdbc/firebird/adapter.rb +140 -0
  62. data/lib/arjdbc/h2.rb +4 -0
  63. data/lib/arjdbc/h2/adapter.rb +54 -0
  64. data/lib/arjdbc/h2/connection_methods.rb +13 -0
  65. data/lib/arjdbc/hsqldb.rb +4 -0
  66. data/lib/arjdbc/hsqldb/adapter.rb +184 -0
  67. data/lib/arjdbc/hsqldb/connection_methods.rb +15 -0
  68. data/lib/arjdbc/informix.rb +3 -0
  69. data/lib/arjdbc/informix/adapter.rb +142 -0
  70. data/lib/arjdbc/informix/connection_methods.rb +11 -0
  71. data/lib/arjdbc/jdbc.rb +2 -0
  72. data/lib/arjdbc/jdbc/adapter.rb +356 -0
  73. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  74. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  75. data/lib/arjdbc/jdbc/callbacks.rb +44 -0
  76. data/lib/arjdbc/jdbc/column.rb +47 -0
  77. data/lib/arjdbc/jdbc/compatibility.rb +51 -0
  78. data/lib/arjdbc/jdbc/connection.rb +134 -0
  79. data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
  80. data/lib/arjdbc/jdbc/core_ext.rb +24 -0
  81. data/lib/arjdbc/jdbc/discover.rb +18 -0
  82. data/lib/arjdbc/jdbc/driver.rb +35 -0
  83. data/lib/arjdbc/jdbc/extension.rb +47 -0
  84. data/lib/arjdbc/jdbc/java.rb +14 -0
  85. data/lib/arjdbc/jdbc/jdbc.rake +131 -0
  86. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +88 -0
  87. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  88. data/lib/arjdbc/jdbc/railtie.rb +9 -0
  89. data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
  90. data/lib/arjdbc/jdbc/require_driver.rb +16 -0
  91. data/lib/arjdbc/jdbc/type_converter.rb +126 -0
  92. data/lib/arjdbc/mimer.rb +2 -0
  93. data/lib/arjdbc/mimer/adapter.rb +142 -0
  94. data/lib/arjdbc/mssql.rb +4 -0
  95. data/lib/arjdbc/mssql/adapter.rb +477 -0
  96. data/lib/arjdbc/mssql/connection_methods.rb +31 -0
  97. data/lib/arjdbc/mssql/limit_helpers.rb +101 -0
  98. data/lib/arjdbc/mssql/lock_helpers.rb +72 -0
  99. data/lib/arjdbc/mssql/tsql_helper.rb +61 -0
  100. data/lib/arjdbc/mysql.rb +4 -0
  101. data/lib/arjdbc/mysql/adapter.rb +505 -0
  102. data/lib/arjdbc/mysql/connection_methods.rb +28 -0
  103. data/lib/arjdbc/oracle.rb +3 -0
  104. data/lib/arjdbc/oracle/adapter.rb +432 -0
  105. data/lib/arjdbc/oracle/connection_methods.rb +12 -0
  106. data/lib/arjdbc/postgresql.rb +4 -0
  107. data/lib/arjdbc/postgresql/adapter.rb +861 -0
  108. data/lib/arjdbc/postgresql/connection_methods.rb +23 -0
  109. data/lib/arjdbc/sqlite3.rb +4 -0
  110. data/lib/arjdbc/sqlite3/adapter.rb +389 -0
  111. data/lib/arjdbc/sqlite3/connection_methods.rb +35 -0
  112. data/lib/arjdbc/sybase.rb +2 -0
  113. data/lib/arjdbc/sybase/adapter.rb +46 -0
  114. data/lib/arjdbc/version.rb +8 -0
  115. data/lib/generators/jdbc/USAGE +10 -0
  116. data/lib/generators/jdbc/jdbc_generator.rb +9 -0
  117. data/lib/jdbc_adapter.rb +2 -0
  118. data/lib/jdbc_adapter/rake_tasks.rb +3 -0
  119. data/lib/jdbc_adapter/version.rb +3 -0
  120. data/lib/pg.rb +26 -0
  121. data/pom.xml +57 -0
  122. data/rails_generators/jdbc_generator.rb +15 -0
  123. data/rails_generators/templates/config/initializers/jdbc.rb +7 -0
  124. data/rails_generators/templates/lib/tasks/jdbc.rake +8 -0
  125. data/rakelib/bundler_ext.rb +11 -0
  126. data/rakelib/compile.rake +23 -0
  127. data/rakelib/db.rake +39 -0
  128. data/rakelib/rails.rake +41 -0
  129. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +69 -0
  130. data/src/java/arjdbc/derby/DerbyModule.java +324 -0
  131. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
  132. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
  133. data/src/java/arjdbc/jdbc/AdapterJavaService.java +68 -0
  134. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +36 -0
  135. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1346 -0
  136. data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
  137. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
  138. data/src/java/arjdbc/mysql/MySQLModule.java +134 -0
  139. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +161 -0
  140. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
  141. data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +82 -0
  142. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +126 -0
  143. data/test/abstract_db_create.rb +135 -0
  144. data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
  145. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
  146. data/test/activerecord/jall.sh +7 -0
  147. data/test/activerecord/jtest.sh +3 -0
  148. data/test/db/db2.rb +11 -0
  149. data/test/db/derby.rb +12 -0
  150. data/test/db/h2.rb +11 -0
  151. data/test/db/hsqldb.rb +13 -0
  152. data/test/db/informix.rb +11 -0
  153. data/test/db/jdbc.rb +12 -0
  154. data/test/db/jndi_config.rb +40 -0
  155. data/test/db/logger.rb +3 -0
  156. data/test/db/mssql.rb +9 -0
  157. data/test/db/mysql.rb +10 -0
  158. data/test/db/oracle.rb +34 -0
  159. data/test/db/postgres.rb +18 -0
  160. data/test/db/sqlite3.rb +11 -0
  161. data/test/db2_reset_column_information_test.rb +8 -0
  162. data/test/db2_simple_test.rb +66 -0
  163. data/test/derby_migration_test.rb +68 -0
  164. data/test/derby_multibyte_test.rb +12 -0
  165. data/test/derby_reset_column_information_test.rb +8 -0
  166. data/test/derby_row_locking_test.rb +9 -0
  167. data/test/derby_simple_test.rb +139 -0
  168. data/test/generic_jdbc_connection_test.rb +29 -0
  169. data/test/h2_change_column_test.rb +68 -0
  170. data/test/h2_simple_test.rb +41 -0
  171. data/test/has_many_through.rb +79 -0
  172. data/test/helper.rb +108 -0
  173. data/test/hsqldb_simple_test.rb +6 -0
  174. data/test/informix_simple_test.rb +48 -0
  175. data/test/jdbc_common.rb +28 -0
  176. data/test/jndi_callbacks_test.rb +36 -0
  177. data/test/jndi_test.rb +25 -0
  178. data/test/manualTestDatabase.rb +191 -0
  179. data/test/models/add_not_null_column_to_table.rb +9 -0
  180. data/test/models/auto_id.rb +15 -0
  181. data/test/models/custom_pk_name.rb +14 -0
  182. data/test/models/data_types.rb +30 -0
  183. data/test/models/entry.rb +40 -0
  184. data/test/models/mixed_case.rb +22 -0
  185. data/test/models/reserved_word.rb +15 -0
  186. data/test/models/string_id.rb +17 -0
  187. data/test/models/thing.rb +16 -0
  188. data/test/models/validates_uniqueness_of_string.rb +19 -0
  189. data/test/mssql_db_create_test.rb +26 -0
  190. data/test/mssql_identity_insert_test.rb +19 -0
  191. data/test/mssql_ignore_system_views_test.rb +27 -0
  192. data/test/mssql_legacy_types_test.rb +58 -0
  193. data/test/mssql_limit_offset_test.rb +136 -0
  194. data/test/mssql_multibyte_test.rb +18 -0
  195. data/test/mssql_null_test.rb +14 -0
  196. data/test/mssql_reset_column_information_test.rb +8 -0
  197. data/test/mssql_row_locking_sql_test.rb +159 -0
  198. data/test/mssql_row_locking_test.rb +9 -0
  199. data/test/mssql_simple_test.rb +55 -0
  200. data/test/mysql_db_create_test.rb +27 -0
  201. data/test/mysql_index_length_test.rb +58 -0
  202. data/test/mysql_info_test.rb +123 -0
  203. data/test/mysql_multibyte_test.rb +10 -0
  204. data/test/mysql_nonstandard_primary_key_test.rb +42 -0
  205. data/test/mysql_reset_column_information_test.rb +8 -0
  206. data/test/mysql_simple_test.rb +125 -0
  207. data/test/oracle_reset_column_information_test.rb +8 -0
  208. data/test/oracle_simple_test.rb +18 -0
  209. data/test/oracle_specific_test.rb +83 -0
  210. data/test/postgres_db_create_test.rb +32 -0
  211. data/test/postgres_drop_db_test.rb +16 -0
  212. data/test/postgres_information_schema_leak_test.rb +29 -0
  213. data/test/postgres_mixed_case_test.rb +29 -0
  214. data/test/postgres_native_type_mapping_test.rb +93 -0
  215. data/test/postgres_nonseq_pkey_test.rb +38 -0
  216. data/test/postgres_reserved_test.rb +22 -0
  217. data/test/postgres_reset_column_information_test.rb +8 -0
  218. data/test/postgres_schema_search_path_test.rb +48 -0
  219. data/test/postgres_simple_test.rb +168 -0
  220. data/test/postgres_table_alias_length_test.rb +15 -0
  221. data/test/postgres_type_conversion_test.rb +34 -0
  222. data/test/row_locking.rb +90 -0
  223. data/test/simple.rb +731 -0
  224. data/test/sqlite3_reset_column_information_test.rb +8 -0
  225. data/test/sqlite3_simple_test.rb +316 -0
  226. data/test/sybase_jtds_simple_test.rb +28 -0
  227. data/test/sybase_reset_column_information_test.rb +8 -0
  228. metadata +288 -0
@@ -0,0 +1,2 @@
1
+ require 'arjdbc/jdbc'
2
+ require 'arjdbc/sybase/adapter.rb'
@@ -0,0 +1,46 @@
1
+ module ArJdbc
2
+ module Sybase
3
+ def add_limit_offset!(sql, options) # :nodoc:
4
+ @limit = options[:limit]
5
+ @offset = options[:offset]
6
+ if use_temp_table?
7
+ # Use temp table to hack offset with Sybase
8
+ sql.sub!(/ FROM /i, ' INTO #artemp FROM ')
9
+ elsif zero_limit?
10
+ # "SET ROWCOUNT 0" turns off limits, so we havesy
11
+ # to use a cheap trick.
12
+ if sql =~ /WHERE/i
13
+ sql.sub!(/WHERE/i, 'WHERE 1 = 2 AND ')
14
+ elsif sql =~ /ORDER\s+BY/i
15
+ sql.sub!(/ORDER\s+BY/i, 'WHERE 1 = 2 ORDER BY')
16
+ else
17
+ sql << 'WHERE 1 = 2'
18
+ end
19
+ end
20
+ end
21
+
22
+ # If limit is not set at all, we can ignore offset;
23
+ # if limit *is* set but offset is zero, use normal select
24
+ # with simple SET ROWCOUNT. Thus, only use the temp table
25
+ # if limit is set and offset > 0.
26
+ def use_temp_table?
27
+ !@limit.nil? && !@offset.nil? && @offset > 0
28
+ end
29
+
30
+ def zero_limit?
31
+ !@limit.nil? && @limit == 0
32
+ end
33
+
34
+ def modify_types(tp) #:nodoc:
35
+ tp[:primary_key] = "NUMERIC(22,0) IDENTITY PRIMARY KEY"
36
+ tp[:integer][:limit] = nil
37
+ tp[:boolean] = {:name => "bit"}
38
+ tp[:binary] = {:name => "image"}
39
+ tp
40
+ end
41
+
42
+ def remove_index(table_name, options = {})
43
+ execute "DROP INDEX #{table_name}.#{index_name(table_name, options)}"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ module ArJdbc
2
+ module Version
3
+ VERSION = "1.2.2"
4
+ end
5
+ end
6
+ # Compatibility with older versions of ar-jdbc for other extensions out there
7
+ JdbcAdapter = ArJdbc
8
+ JdbcSpec = ArJdbc
@@ -0,0 +1,10 @@
1
+ Description:
2
+ Creates stubs that ensure activerecord-jdbc is bootstrapped in
3
+ your Rails application.
4
+
5
+ Example:
6
+ ./script/generate jdbc
7
+
8
+ This will create:
9
+ config/initializers/jdbc.rb
10
+ lib/tasks/jdbc.rake
@@ -0,0 +1,9 @@
1
+ class JdbcGenerator < Rails::Generators::Base
2
+ def self.source_root
3
+ @source_root ||= File.expand_path('../../../../rails_generators/templates', __FILE__)
4
+ end
5
+
6
+ def create_jdbc_files
7
+ directory '.', '.'
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ warn "DEPRECATED: require 'arjdbc' instead of 'jdbc_adapter'."
2
+ require 'arjdbc'
@@ -0,0 +1,3 @@
1
+ warn "DEPRECATED: require 'arjdbc/rake_tasks' instead of 'jdbc_adapter/rake_tasks'."
2
+ require 'arjdbc/jdbc/rake_tasks'
3
+
@@ -0,0 +1,3 @@
1
+ warn "DEPRECATED: require 'arjdbc/version' instead of 'jdbc_adapter/version'."
2
+ require 'arjdbc/version'
3
+
@@ -0,0 +1,26 @@
1
+ # Stub library for postgresql -- allows Rails to load
2
+ # postgresql_adapter without error. Other than postgres-pr, there's no
3
+ # other way to use PostgreSQL on JRuby anyway, right? If you've
4
+ # installed ar-jdbc you probably want to use that to connect to pg.
5
+ #
6
+ # If by chance this library is installed in another Ruby and this file
7
+ # got required then we'll just continue to try to load the next pg.rb
8
+ # in the $LOAD_PATH.
9
+
10
+ unless defined?(JRUBY_VERSION)
11
+ gem 'pg' if respond_to?(:gem) # make sure pg gem is activated
12
+ after_current_file = false
13
+ $LOAD_PATH.each do |p|
14
+ require_file = File.join(p, 'pg.rb')
15
+
16
+ if File.expand_path(require_file) == File.expand_path(__FILE__)
17
+ after_current_file = true
18
+ next
19
+ end
20
+
21
+ if after_current_file && File.exist?(require_file)
22
+ load require_file
23
+ break
24
+ end
25
+ end
26
+ end
data/pom.xml ADDED
@@ -0,0 +1,57 @@
1
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3
+ <modelVersion>4.0.0</modelVersion>
4
+ <groupId>org.jruby.activerecord-jdbc</groupId>
5
+ <artifactId>activerecord-jdbc</artifactId>
6
+ <packaging>jar</packaging>
7
+ <version>1.0.0</version>
8
+ <name>activerecord-jdbc</name>
9
+ <description>
10
+ This POM for activerecord-jdbc is just for bootstrapping IDEs. You
11
+ can't use it to build the project at the moment.
12
+ </description>
13
+ <url>http://activerecord-jdbc.kenai.com/</url>
14
+
15
+ <issueManagement>
16
+ <system>JIRA</system>
17
+ <url>http://kenai.com/jira/browse/ACTIVERECORD_JDBC</url>
18
+ </issueManagement>
19
+
20
+ <scm>
21
+ <connection>scm:git:git://github.com/nicksieger/activerecord-jdbc-adapter.git</connection>
22
+ <developerConnection>scm:git:git@github.com:nicksieger/activerecord-jdbc-adapter.git</developerConnection>
23
+ <url>http://github.com/nicksieger/activerecord-jdbc-adapter</url>
24
+ </scm>
25
+
26
+ <licenses>
27
+ <license>
28
+ <name>BSD</name>
29
+ <url>http://www.opensource.org/licenses/bsd-license.php</url>
30
+ <distribution>repo</distribution>
31
+ </license>
32
+ </licenses>
33
+
34
+ <dependencies>
35
+ <dependency>
36
+ <groupId>org.jruby</groupId>
37
+ <artifactId>jruby-complete</artifactId>
38
+ <version>1.5.3</version>
39
+ </dependency>
40
+ </dependencies>
41
+
42
+ <build>
43
+ <outputDirectory>pkg/classes</outputDirectory>
44
+ <sourceDirectory>src/java</sourceDirectory>
45
+ <plugins>
46
+ <plugin>
47
+ <groupId>org.apache.maven.plugins</groupId>
48
+ <artifactId>maven-compiler-plugin</artifactId>
49
+ <configuration>
50
+ <source>1.5</source>
51
+ <target>1.5</target>
52
+ </configuration>
53
+ </plugin>
54
+ </plugins>
55
+ </build>
56
+
57
+ </project>
@@ -0,0 +1,15 @@
1
+ class JdbcGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.directory 'config/initializers'
5
+ m.template 'config/initializers/jdbc.rb', File.join('config', 'initializers', 'jdbc.rb')
6
+ m.directory 'lib/tasks'
7
+ m.template 'lib/tasks/jdbc.rake', File.join('lib', 'tasks', 'jdbc.rake')
8
+ end
9
+ end
10
+
11
+ protected
12
+ def banner
13
+ "Usage: #{$0} jdbc\nGenerate JDBC bootstrapping files for your Rails application."
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ # This file was generated by the "jdbc" generator, which is provided
2
+ # by the activerecord-jdbc-adapter gem.
3
+ #
4
+ # This file allows the JDBC drivers to be hooked into ActiveRecord
5
+ # such that you don't have to change anything else in your Rails
6
+ # application.
7
+ require 'arjdbc' if defined?(JRUBY_VERSION)
@@ -0,0 +1,8 @@
1
+ # This file was generated by the "jdbc" generator, which is provided
2
+ # by the activerecord-jdbc-adapter gem.
3
+ #
4
+ # This file allows you to use Rails' various db:* tasks with JDBC.
5
+ if defined?(JRUBY_VERSION)
6
+ require 'arjdbc'
7
+ require 'arjdbc/jdbc/rake_tasks'
8
+ end
@@ -0,0 +1,11 @@
1
+ module Bundler
2
+ class GemHelper
3
+ def guard_already_tagged
4
+ # parent project performs the tag
5
+ end
6
+ def tag_version
7
+ Bundler.ui.confirm "Parent project tagged #{version_tag}"
8
+ yield if block_given?
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ jar_file = File.join(*%w(lib arjdbc jdbc adapter_java.jar))
2
+ begin
3
+ require 'ant'
4
+ directory "pkg/classes"
5
+ CLEAN << "pkg"
6
+
7
+ file jar_file => FileList['src/java/**/*.java', 'pkg/classes'] do
8
+ rm_rf FileList['pkg/classes/**/*']
9
+ ant.javac :srcdir => "src/java", :destdir => "pkg/classes",
10
+ :source => "1.5", :target => "1.5", :debug => true,
11
+ :classpath => "${java.class.path}:${sun.boot.class.path}",
12
+ :includeantRuntime => false
13
+
14
+ ant.jar :basedir => "pkg/classes", :destfile => jar_file, :includes => "**/*.class"
15
+ end
16
+
17
+ desc "Compile the native Java code."
18
+ task :jar => jar_file
19
+ rescue LoadError
20
+ task :jar do
21
+ puts "Run 'jar' with JRuby to re-compile the agent extension class"
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ namespace :db do
2
+ desc "Creates the test database for MySQL."
3
+ task :mysql do
4
+ load 'test/db/mysql.rb' rescue nil
5
+ t = Tempfile.new("mysql")
6
+ t.puts <<-SQL
7
+ DROP DATABASE IF EXISTS `#{MYSQL_CONFIG[:database]}`;
8
+ CREATE DATABASE `#{MYSQL_CONFIG[:database]}` DEFAULT CHARACTER SET `utf8`;
9
+ GRANT ALL PRIVILEGES ON `#{MYSQL_CONFIG[:database]}`.* TO #{MYSQL_CONFIG[:username]}@localhost;
10
+ GRANT ALL PRIVILEGES ON `test\_%`.* TO #{MYSQL_CONFIG[:username]}@localhost;
11
+ SET PASSWORD FOR #{MYSQL_CONFIG[:username]}@localhost = PASSWORD('#{MYSQL_CONFIG[:password]}');
12
+ SQL
13
+ t.close
14
+ at_exit { t.unlink }
15
+ password = ""
16
+ if ENV['DATABASE_YML']
17
+ require 'yaml'
18
+ password = YAML.load(File.new(ENV['DATABASE_YML']))["production"]["password"]
19
+ password_arg = " --password=#{password}"
20
+ end
21
+ sh "cat #{t.path} | mysql -u root#{password_arg}", :verbose => false # so password is not echoed
22
+ end
23
+
24
+ desc "Creates the test database for PostgreSQL."
25
+ task :postgres do
26
+ fail unless have_postgres?
27
+ load 'test/db/postgres.rb' rescue nil
28
+ t = Tempfile.new("psql")
29
+ t.puts <<-SQL
30
+ DROP DATABASE IF EXISTS #{POSTGRES_CONFIG[:database]};
31
+ DROP USER IF EXISTS #{POSTGRES_CONFIG[:username]};
32
+ CREATE USER #{POSTGRES_CONFIG[:username]} CREATEDB SUPERUSER LOGIN PASSWORD '#{POSTGRES_CONFIG[:password]}';
33
+ CREATE DATABASE #{POSTGRES_CONFIG[:database]} OWNER #{POSTGRES_CONFIG[:username]};
34
+ SQL
35
+ t.close
36
+ at_exit { t.unlink }
37
+ sh "cat #{t.path} | psql -U postgres"
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ namespace :rails do
2
+ def _adapter(n)
3
+ case n
4
+ when /postgres/
5
+ 'postgresql'
6
+ else
7
+ n
8
+ end
9
+ end
10
+
11
+ def _driver(n)
12
+ case n
13
+ when /postgres/
14
+ 'postgres'
15
+ else
16
+ n
17
+ end
18
+ end
19
+
20
+ def _target(n)
21
+ case n
22
+ when /postgres/
23
+ 'test_jdbcpostgresql'
24
+ else
25
+ "test_jdbc#{n}"
26
+ end
27
+ end
28
+
29
+ task :test => :jar do
30
+ driver = ENV['DRIVER']
31
+ raise "need a DRIVER" unless driver
32
+ activerecord = ENV['RAILS']
33
+ raise "need location of RAILS source code" unless activerecord
34
+ activerecord = File.join(activerecord, 'activerecord') unless activerecord =~ /activerecord$/
35
+ ar_jdbc = File.expand_path(File.dirname(__FILE__) + '/..')
36
+ rubylib = "#{ar_jdbc}/lib:#{ar_jdbc}/jdbc-#{_driver(driver)}/lib:#{ar_jdbc}/activerecord-jdbc#{_adapter(driver)}-adapter/lib"
37
+ Dir.chdir(activerecord) do
38
+ rake "RUBYLIB=#{rubylib}", "#{_target(driver)}"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,69 @@
1
+ /*
2
+ **** BEGIN LICENSE BLOCK *****
3
+ * Copyright (c) 2006-2010 Nick Sieger <nick@nicksieger.com>
4
+ * Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
5
+ * Copyright (c) 2008-2009 Thomas E Enebo <enebo@acm.org>
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining
8
+ * a copy of this software and associated documentation files (the
9
+ * "Software"), to deal in the Software without restriction, including
10
+ * without limitation the rights to use, copy, modify, merge, publish,
11
+ * distribute, sublicense, and/or sell copies of the Software, and to
12
+ * permit persons to whom the Software is furnished to do so, subject to
13
+ * the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ ***** END LICENSE BLOCK *****/
26
+ package arjdbc.db2;
27
+
28
+ import org.jruby.Ruby;
29
+ import org.jruby.RubyClass;
30
+ import org.jruby.runtime.ObjectAllocator;
31
+ import org.jruby.runtime.builtin.IRubyObject;
32
+
33
+ import arjdbc.jdbc.RubyJdbcConnection;
34
+
35
+ /**
36
+ *
37
+ * @author mikestone
38
+ */
39
+ public class DB2RubyJdbcConnection extends RubyJdbcConnection {
40
+ private static final String[] TABLE_TYPES = new String[]{"TABLE", "VIEW", "SYNONYM", "MATERIALIZED QUERY TABLE", "ALIAS"};
41
+
42
+ protected DB2RubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
43
+ super(runtime, metaClass);
44
+ }
45
+
46
+ @Override
47
+ protected String[] getTableTypes() {
48
+ return TABLE_TYPES;
49
+ }
50
+
51
+ @Override
52
+ protected boolean databaseSupportsSchemas() {
53
+ return true;
54
+ }
55
+
56
+ public static RubyClass createDB2JdbcConnectionClass(Ruby runtime, RubyClass jdbcConnection) {
57
+ RubyClass clazz = RubyJdbcConnection.getConnectionAdapters(runtime).defineClassUnder("DB2JdbcConnection",
58
+ jdbcConnection, DB2_JDBCCONNECTION_ALLOCATOR);
59
+ clazz.defineAnnotatedMethods(DB2RubyJdbcConnection.class);
60
+
61
+ return clazz;
62
+ }
63
+
64
+ private static ObjectAllocator DB2_JDBCCONNECTION_ALLOCATOR = new ObjectAllocator() {
65
+ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
66
+ return new DB2RubyJdbcConnection(runtime, klass);
67
+ }
68
+ };
69
+ }
@@ -0,0 +1,324 @@
1
+ /***** BEGIN LICENSE BLOCK *****
2
+ * Copyright (c) 2006-2011 Nick Sieger <nick@nicksieger.com>
3
+ * Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ ***** END LICENSE BLOCK *****/
24
+
25
+ package arjdbc.derby;
26
+
27
+ import java.sql.SQLException;
28
+
29
+ import arjdbc.jdbc.RubyJdbcConnection;
30
+
31
+ import org.jruby.Ruby;
32
+ import org.jruby.RubyBoolean;
33
+ import org.jruby.RubyModule;
34
+ import org.jruby.RubyObjectAdapter;
35
+ import org.jruby.RubyRange;
36
+ import org.jruby.RubyString;
37
+ import org.jruby.anno.JRubyMethod;
38
+ import org.jruby.runtime.ThreadContext;
39
+ import org.jruby.runtime.builtin.IRubyObject;
40
+ import org.jruby.util.ByteList;
41
+
42
+ public class DerbyModule {
43
+ private static RubyObjectAdapter rubyApi;
44
+ public static void load(RubyModule arJdbc, RubyObjectAdapter adapter) {
45
+ RubyModule derby = arJdbc.defineModuleUnder("Derby");
46
+ derby.defineAnnotatedMethods(DerbyModule.class);
47
+ RubyModule column = derby.defineModuleUnder("Column");
48
+ column.defineAnnotatedMethods(Column.class);
49
+ rubyApi = adapter;
50
+ }
51
+
52
+ public static class Column {
53
+ @JRubyMethod(name = "type_cast", required = 1)
54
+ public static IRubyObject type_cast(IRubyObject recv, IRubyObject value) {
55
+ Ruby runtime = recv.getRuntime();
56
+
57
+ if (value.isNil() || ((value instanceof RubyString) && value.toString().trim().equalsIgnoreCase("null"))) {
58
+ return runtime.getNil();
59
+ }
60
+
61
+ String type = rubyApi.getInstanceVariable(recv, "@type").toString();
62
+
63
+ switch (type.charAt(0)) {
64
+ case 's': //string
65
+ return value;
66
+ case 't': //text, timestamp, time
67
+ if (type.equals("text")) {
68
+ return value;
69
+ } else if (type.equals("timestamp")) {
70
+ return rubyApi.callMethod(recv.getMetaClass(), "string_to_time", value);
71
+ } else { //time
72
+ return rubyApi.callMethod(recv.getMetaClass(), "string_to_dummy_time", value);
73
+ }
74
+ case 'i': //integer
75
+ case 'p': //primary key
76
+ if (value.respondsTo("to_i")) {
77
+ return rubyApi.callMethod(value, "to_i");
78
+ } else {
79
+ return runtime.newFixnum(value.isTrue() ? 1 : 0);
80
+ }
81
+ case 'd': //decimal, datetime, date
82
+ if (type.equals("datetime")) {
83
+ return rubyApi.callMethod(recv.getMetaClass(), "string_to_time", value);
84
+ } else if (type.equals("date")) {
85
+ return rubyApi.callMethod(recv.getMetaClass(), "string_to_date", value);
86
+ } else {
87
+ return rubyApi.callMethod(recv.getMetaClass(), "value_to_decimal", value);
88
+ }
89
+ case 'f': //float
90
+ return rubyApi.callMethod(value, "to_f");
91
+ case 'b': //binary, boolean
92
+ if (type.equals("binary")) {
93
+ return rubyApi.callMethod(recv.getMetaClass(), "binary_to_string", value);
94
+ } else {
95
+ return rubyApi.callMethod(recv.getMetaClass(), "value_to_boolean", value);
96
+ }
97
+ }
98
+ return value;
99
+ }
100
+ }
101
+
102
+ @JRubyMethod(name = "quote", required = 1, optional = 1)
103
+ public static IRubyObject quote(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
104
+ Ruby runtime = recv.getRuntime();
105
+ IRubyObject value = args[0];
106
+ if (args.length > 1) {
107
+ IRubyObject col = args[1];
108
+ String type = rubyApi.callMethod(col, "type").toString();
109
+ // intercept and change value, maybe, if the column type is :text or :string
110
+ if (type.equals("text") || type.equals("string")) {
111
+ value = make_ruby_string_for_text_column(context, recv, runtime, value);
112
+ }
113
+ String metaClass = value.getMetaClass().getName();
114
+
115
+ if (value instanceof RubyString) {
116
+ if (type.equals("string")) {
117
+ return quote_string_with_surround(runtime, "'", (RubyString)value, "'");
118
+ } else if (type.equals("text")) {
119
+ return quote_string_with_surround(runtime, "CAST('", (RubyString)value, "' AS CLOB)");
120
+ } else if (type.equals("binary")) {
121
+ return hexquote_string_with_surround(runtime, "CAST(X'", (RubyString)value, "' AS BLOB)");
122
+ } else {
123
+ // column type :integer or other numeric or date version
124
+ if (only_digits((RubyString)value)) {
125
+ return value;
126
+ } else {
127
+ return super_quote(context, recv, runtime, value, col);
128
+ }
129
+ }
130
+ } else if (metaClass.equals("Float") || metaClass.equals("Fixnum") || metaClass.equals("Bignum")) {
131
+ if (type.equals("string")) {
132
+ return quote_string_with_surround(runtime, "'", RubyString.objAsString(context, value), "'");
133
+ }
134
+ }
135
+ }
136
+ return super_quote(context, recv, runtime, value, runtime.getNil());
137
+ }
138
+
139
+ /*
140
+ * Derby is not permissive like MySql. Try and send an Integer to a CLOB or VARCHAR column and Derby will vomit.
141
+ * This method turns non stringy things into strings.
142
+ */
143
+ private static IRubyObject make_ruby_string_for_text_column(ThreadContext context, IRubyObject recv, Ruby runtime, IRubyObject value) {
144
+ RubyModule multibyteChars = (RubyModule)
145
+ ((RubyModule) ((RubyModule) runtime.getModule("ActiveSupport")).getConstant("Multibyte")).getConstantAt("Chars");
146
+ if (value instanceof RubyString || rubyApi.isKindOf(value, multibyteChars) || value.isNil()) {
147
+ return value;
148
+ }
149
+
150
+ String metaClass = value.getMetaClass().getName();
151
+
152
+ if (value instanceof RubyBoolean) {
153
+ return value.isTrue() ? runtime.newString("1") : runtime.newString("0");
154
+ } else if (metaClass.equals("Float") || metaClass.equals("Fixnum") || metaClass.equals("Bignum")) {
155
+ return RubyString.objAsString(context, value);
156
+ } else if (metaClass.equals("BigDecimal")) {
157
+ return rubyApi.callMethod(value, "to_s", runtime.newString("F"));
158
+ } else {
159
+ if (rubyApi.callMethod(value, "acts_like?", runtime.newString("date")).isTrue() || rubyApi.callMethod(value, "acts_like?", runtime.newString("time")).isTrue()) {
160
+ return (RubyString)rubyApi.callMethod(recv, "quoted_date", value);
161
+ } else {
162
+ return (RubyString)rubyApi.callMethod(value, "to_yaml");
163
+ }
164
+ }
165
+ }
166
+
167
+ private final static ByteList NULL = new ByteList("NULL".getBytes());
168
+
169
+ private static IRubyObject super_quote(ThreadContext context, IRubyObject recv, Ruby runtime, IRubyObject value, IRubyObject col) {
170
+ if (value.respondsTo("quoted_id")) {
171
+ return rubyApi.callMethod(value, "quoted_id");
172
+ }
173
+
174
+ String metaClass = value.getMetaClass().getName();
175
+
176
+ IRubyObject type = (col.isNil()) ? col : rubyApi.callMethod(col, "type");
177
+ RubyModule multibyteChars = (RubyModule)
178
+ ((RubyModule) ((RubyModule) runtime.getModule("ActiveSupport")).getConstant("Multibyte")).getConstantAt("Chars");
179
+ if (value instanceof RubyString || rubyApi.isKindOf(value, multibyteChars)) {
180
+ RubyString svalue = RubyString.objAsString(context, value);
181
+ if (type == runtime.newSymbol("binary") && col.getType().respondsTo("string_to_binary")) {
182
+ return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(col.getType(), "string_to_binary", svalue)), "'");
183
+ } else if (type == runtime.newSymbol("integer") || type == runtime.newSymbol("float")) {
184
+ return RubyString.objAsString(context, ((type == runtime.newSymbol("integer")) ?
185
+ rubyApi.callMethod(svalue, "to_i") :
186
+ rubyApi.callMethod(svalue, "to_f")));
187
+ } else {
188
+ return quote_string_with_surround(runtime, "'", svalue, "'");
189
+ }
190
+ } else if (value.isNil()) {
191
+ return runtime.newString(NULL);
192
+ } else if (value instanceof RubyBoolean) {
193
+ return (value.isTrue() ?
194
+ (type == runtime.newSymbol(":integer")) ? runtime.newString("1") : rubyApi.callMethod(recv, "quoted_true") :
195
+ (type == runtime.newSymbol(":integer")) ? runtime.newString("0") : rubyApi.callMethod(recv, "quoted_false"));
196
+ } else if (metaClass.equals("Float") || metaClass.equals("Fixnum") || metaClass.equals("Bignum")) {
197
+ return RubyString.objAsString(context, value);
198
+ } else if (metaClass.equals("BigDecimal")) {
199
+ return rubyApi.callMethod(value, "to_s", runtime.newString("F"));
200
+ } else if (rubyApi.callMethod(value, "acts_like?", runtime.newString("date")).isTrue() || rubyApi.callMethod(value, "acts_like?", runtime.newString("time")).isTrue()) {
201
+ return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(recv, "quoted_date", value)), "'");
202
+ } else {
203
+ return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(value, "to_yaml")), "'");
204
+ }
205
+ }
206
+
207
+ private final static ByteList TWO_SINGLE = new ByteList(new byte[]{'\'','\''});
208
+
209
+ private static IRubyObject quote_string_with_surround(Ruby runtime, String before, RubyString string, String after) {
210
+ ByteList input = string.getByteList();
211
+ ByteList output = new ByteList(before.getBytes());
212
+ for(int i = input.begin; i< input.begin + input.realSize; i++) {
213
+ switch(input.bytes[i]) {
214
+ case '\'':
215
+ output.append(input.bytes[i]);
216
+ //FALLTHROUGH
217
+ default:
218
+ output.append(input.bytes[i]);
219
+ }
220
+
221
+ }
222
+
223
+ output.append(after.getBytes());
224
+
225
+ return runtime.newString(output);
226
+ }
227
+
228
+ private final static byte[] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
229
+
230
+ private static IRubyObject hexquote_string_with_surround(Ruby runtime, String before, RubyString string, String after) {
231
+ ByteList input = string.getByteList();
232
+ ByteList output = new ByteList(before.getBytes());
233
+ int written = 0;
234
+ for(int i = input.begin; i< input.begin + input.realSize; i++) {
235
+ byte b1 = input.bytes[i];
236
+ byte higher = HEX[(((char)b1)>>4)%16];
237
+ byte lower = HEX[((char)b1)%16];
238
+ output.append(higher);
239
+ output.append(lower);
240
+ written += 2;
241
+ if(written >= 16334) { // max hex length = 16334
242
+ output.append("'||X'".getBytes());
243
+ written = 0;
244
+ }
245
+ }
246
+
247
+ output.append(after.getBytes());
248
+ return runtime.newStringShared(output);
249
+ }
250
+
251
+ private static boolean only_digits(RubyString inp) {
252
+ ByteList input = inp.getByteList();
253
+ for(int i = input.begin; i< input.begin + input.realSize; i++) {
254
+ if(input.bytes[i] < '0' || input.bytes[i] > '9') {
255
+ return false;
256
+ }
257
+ }
258
+ return true;
259
+ }
260
+
261
+ @JRubyMethod(name = "quote_string", required = 1)
262
+ public static IRubyObject quote_string(IRubyObject recv, IRubyObject string) {
263
+ boolean replacementFound = false;
264
+ ByteList bl = ((RubyString) string).getByteList();
265
+
266
+ for(int i = bl.begin; i < bl.begin + bl.realSize; i++) {
267
+ switch (bl.bytes[i]) {
268
+ case '\'': break;
269
+ default: continue;
270
+ }
271
+
272
+ // On first replacement allocate a different bytelist so we don't manip original
273
+ if(!replacementFound) {
274
+ i-= bl.begin;
275
+ bl = new ByteList(bl);
276
+ replacementFound = true;
277
+ }
278
+
279
+ bl.replace(i, 1, TWO_SINGLE);
280
+ i+=1;
281
+ }
282
+ if(replacementFound) {
283
+ return recv.getRuntime().newStringShared(bl);
284
+ } else {
285
+ return string;
286
+ }
287
+ }
288
+
289
+ @JRubyMethod(name = "select_all", rest = true)
290
+ public static IRubyObject select_all(IRubyObject recv, IRubyObject[] args) {
291
+ return rubyApi.callMethod(recv, "execute", args);
292
+ }
293
+
294
+ @JRubyMethod(name = "select_one", rest = true)
295
+ public static IRubyObject select_one(IRubyObject recv, IRubyObject[] args) {
296
+ IRubyObject limit = rubyApi.getInstanceVariable(recv, "@limit");
297
+ if (limit == null || limit.isNil()) {
298
+ rubyApi.setInstanceVariable(recv, "@limit", recv.getRuntime().newFixnum(1));
299
+ }
300
+ try {
301
+ IRubyObject result = rubyApi.callMethod(recv, "execute", args);
302
+ return rubyApi.callMethod(result, "first");
303
+ } finally {
304
+ rubyApi.setInstanceVariable(recv, "@limit", recv.getRuntime().getNil());
305
+ }
306
+ }
307
+
308
+ @JRubyMethod(name = "_execute", required = 1, optional = 1)
309
+ public static IRubyObject _execute(ThreadContext context, IRubyObject recv, IRubyObject[] args) throws SQLException, java.io.IOException {
310
+ Ruby runtime = recv.getRuntime();
311
+ RubyJdbcConnection conn = (RubyJdbcConnection) rubyApi.getInstanceVariable(recv, "@connection");
312
+ String sql = args[0].toString().trim().toLowerCase();
313
+ if (sql.charAt(0) == '(') {
314
+ sql = sql.substring(1).trim();
315
+ }
316
+ if (sql.startsWith("insert")) {
317
+ return conn.execute_insert(context, args[0]);
318
+ } else if (sql.startsWith("select") || sql.startsWith("show") || sql.startsWith("values")) {
319
+ return conn.execute_query(context, args[0]);
320
+ } else {
321
+ return conn.execute_update(context, args[0]);
322
+ }
323
+ }
324
+ }