activerecord-jdbc-adapter 1.0.0.beta1-java → 1.0.0.beta2-java
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.
- data/History.txt +37 -0
- data/Manifest.txt +8 -0
- data/README.txt +41 -88
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +9 -0
- data/lib/arel/engines/sql/compilers/mssql_compiler.rb +34 -0
- data/lib/arjdbc/db2/adapter.rb +232 -52
- data/lib/arjdbc/derby/adapter.rb +28 -1
- data/lib/arjdbc/derby/connection_methods.rb +1 -1
- data/lib/arjdbc/discover.rb +1 -1
- data/lib/arjdbc/firebird/adapter.rb +26 -0
- data/lib/arjdbc/h2/adapter.rb +13 -0
- data/lib/arjdbc/hsqldb/adapter.rb +8 -6
- data/lib/arjdbc/informix/adapter.rb +4 -0
- data/lib/arjdbc/jdbc/adapter.rb +27 -5
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +76 -45
- data/lib/arjdbc/jdbc/jdbc.rake +22 -20
- data/lib/arjdbc/jdbc/type_converter.rb +9 -2
- data/lib/arjdbc/mssql/adapter.rb +102 -24
- data/lib/arjdbc/mssql/connection_methods.rb +19 -2
- data/lib/arjdbc/mssql/tsql_helper.rb +1 -0
- data/lib/arjdbc/mysql/adapter.rb +6 -0
- data/lib/arjdbc/mysql/connection_methods.rb +8 -7
- data/lib/arjdbc/oracle/adapter.rb +8 -6
- data/lib/arjdbc/postgresql/adapter.rb +51 -19
- data/lib/arjdbc/version.rb +1 -1
- data/lib/jdbc_adapter/rake_tasks.rb +3 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +2 -2
- data/rakelib/package.rake +2 -0
- data/rakelib/test.rake +6 -3
- data/src/java/arjdbc/derby/DerbyModule.java +30 -1
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +7 -3
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +45 -30
- data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +54 -1
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
- data/test/abstract_db_create.rb +6 -1
- data/test/db/jndi_config.rb +20 -10
- data/test/db2_simple_test.rb +34 -1
- data/test/derby_simple_test.rb +78 -0
- data/test/generic_jdbc_connection_test.rb +21 -1
- data/test/jndi_callbacks_test.rb +2 -1
- data/test/jndi_test.rb +1 -11
- data/test/models/entry.rb +20 -0
- data/test/mssql_limit_offset_test.rb +28 -0
- data/test/mssql_simple_test.rb +7 -1
- data/test/mysql_info_test.rb +49 -6
- data/test/mysql_simple_test.rb +4 -0
- data/test/oracle_simple_test.rb +3 -47
- data/test/oracle_specific_test.rb +83 -0
- data/test/postgres_db_create_test.rb +6 -0
- data/test/postgres_drop_db_test.rb +16 -0
- data/test/postgres_simple_test.rb +17 -0
- data/test/postgres_table_alias_length_test.rb +15 -0
- data/test/simple.rb +17 -4
- metadata +33 -7
    
        data/lib/arjdbc/version.rb
    CHANGED
    
    
    
        data/rakelib/package.rake
    CHANGED
    
    | @@ -24,6 +24,8 @@ begin | |
| 24 24 | 
             
                p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
         | 
| 25 25 | 
             
                p.description = p.paragraphs_of('README.txt', 0...1).join("\n\n")
         | 
| 26 26 | 
             
              end
         | 
| 27 | 
            +
              hoe.spec.rdoc_options += ["-SHN", "-f", "darkfish"]
         | 
| 28 | 
            +
             | 
| 27 29 | 
             
              task :gemspec do
         | 
| 28 30 | 
             
                File.open("#{hoe.name}.gemspec", "w") {|f| f << hoe.spec.to_ruby }
         | 
| 29 31 | 
             
              end
         | 
    
        data/rakelib/test.rake
    CHANGED
    
    | @@ -4,6 +4,9 @@ if defined?(JRUBY_VERSION) | |
| 4 4 | 
             
              if find_executable?("psql") && `psql -c '\\l'` && $?.exitstatus == 0
         | 
| 5 5 | 
             
                databases << :test_postgres
         | 
| 6 6 | 
             
              end
         | 
| 7 | 
            +
              if File.exist?('test/fscontext.jar')
         | 
| 8 | 
            +
                databases << :test_jndi
         | 
| 9 | 
            +
              end
         | 
| 7 10 | 
             
              task :test => databases
         | 
| 8 11 | 
             
            else
         | 
| 9 12 | 
             
              task :test => [:test_mysql]
         | 
| @@ -37,12 +40,12 @@ declare_test_task_for :postgres | |
| 37 40 | 
             
            declare_test_task_for :sqlite3
         | 
| 38 41 |  | 
| 39 42 | 
             
            Rake::TestTask.new(:test_jdbc) do |t|
         | 
| 40 | 
            -
              t.test_files = FileList['test/generic_jdbc_connection_test.rb' | 
| 43 | 
            +
              t.test_files = FileList['test/generic_jdbc_connection_test.rb']
         | 
| 41 44 | 
             
              t.libs << 'test' << 'drivers/mysql/lib'
         | 
| 42 45 | 
             
            end
         | 
| 43 46 |  | 
| 44 47 | 
             
            Rake::TestTask.new(:test_jndi) do |t|
         | 
| 45 | 
            -
              t.test_files = FileList['test/ | 
| 48 | 
            +
              t.test_files = FileList['test/jndi*_test.rb']
         | 
| 46 49 | 
             
              t.libs << 'test' << 'drivers/derby/lib'
         | 
| 47 50 | 
             
            end
         | 
| 48 51 |  | 
| @@ -52,7 +55,7 @@ task :test_pgsql => [:test_postgres] | |
| 52 55 | 
             
            # Ensure driver for these DBs is on your classpath
         | 
| 53 56 | 
             
            %w(oracle db2 cachedb informix).each do |d|
         | 
| 54 57 | 
             
              Rake::TestTask.new("test_#{d}") do |t|
         | 
| 55 | 
            -
                t.test_files = FileList["test/#{d} | 
| 58 | 
            +
                t.test_files = FileList["test/#{d}*_test.rb"]
         | 
| 56 59 | 
             
                t.libs = []
         | 
| 57 60 | 
             
                t.libs << 'lib' if defined?(JRUBY_VERSION)
         | 
| 58 61 | 
             
                t.libs << 'test'
         | 
| @@ -111,6 +111,10 @@ public class DerbyModule { | |
| 111 111 | 
             
                    if (args.length > 1) {
         | 
| 112 112 | 
             
                        IRubyObject col = args[1];
         | 
| 113 113 | 
             
                        String type = rubyApi.callMethod(col, "type").toString();
         | 
| 114 | 
            +
                        // intercept and change value, maybe, if the column type is :text or :string
         | 
| 115 | 
            +
                        if (type.equals("text") || type.equals("string")) {
         | 
| 116 | 
            +
                        	value = make_ruby_string_for_text_column(context, recv, runtime, value);
         | 
| 117 | 
            +
                        }
         | 
| 114 118 | 
             
                        if (value instanceof RubyString) {
         | 
| 115 119 | 
             
                            if (type.equals("string")) {
         | 
| 116 120 | 
             
                                return quote_string_with_surround(runtime, "'", (RubyString)value, "'");
         | 
| @@ -135,7 +139,32 @@ public class DerbyModule { | |
| 135 139 | 
             
                    return super_quote(context, recv, runtime, value, runtime.getNil());
         | 
| 136 140 | 
             
                }
         | 
| 137 141 |  | 
| 138 | 
            -
                 | 
| 142 | 
            +
                /* 
         | 
| 143 | 
            +
                 * Derby is not permissive like MySql. Try and send an Integer to a CLOB or VARCHAR column and Derby will vomit.
         | 
| 144 | 
            +
                 * This method turns non stringy things into strings.
         | 
| 145 | 
            +
                 */
         | 
| 146 | 
            +
                private static IRubyObject make_ruby_string_for_text_column(ThreadContext context, IRubyObject recv, Ruby runtime, IRubyObject value) {
         | 
| 147 | 
            +
                	RubyModule multibyteChars = (RubyModule) 
         | 
| 148 | 
            +
                    ((RubyModule) ((RubyModule) runtime.getModule("ActiveSupport")).getConstant("Multibyte")).getConstantAt("Chars");
         | 
| 149 | 
            +
            		if (value instanceof RubyString || rubyApi.isKindOf(value, multibyteChars) || value.isNil()) {
         | 
| 150 | 
            +
            			return value;
         | 
| 151 | 
            +
            		}
         | 
| 152 | 
            +
            		if (value instanceof RubyBoolean) {
         | 
| 153 | 
            +
                        return value.isTrue() ? runtime.newString("1") : runtime.newString("0");
         | 
| 154 | 
            +
            		} else if (value instanceof RubyFloat || value instanceof RubyFixnum || value instanceof RubyBignum) {
         | 
| 155 | 
            +
            			return RubyString.objAsString(context, value);
         | 
| 156 | 
            +
            		} else if ( value instanceof RubyBigDecimal) {
         | 
| 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());
         | 
| 139 168 |  | 
| 140 169 | 
             
                private static IRubyObject super_quote(ThreadContext context, IRubyObject recv, Ruby runtime, IRubyObject value, IRubyObject col) {
         | 
| 141 170 | 
             
                    if (value.respondsTo("quoted_id")) {
         | 
| @@ -0,0 +1,74 @@ | |
| 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 | 
            +
             | 
| 27 | 
            +
            package arjdbc.informix;
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            import java.sql.ResultSet;
         | 
| 30 | 
            +
            import java.sql.SQLException;
         | 
| 31 | 
            +
            import java.sql.Types;
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            import arjdbc.jdbc.RubyJdbcConnection;
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            import org.jruby.Ruby;
         | 
| 36 | 
            +
            import org.jruby.RubyClass;
         | 
| 37 | 
            +
            import org.jruby.runtime.ObjectAllocator;
         | 
| 38 | 
            +
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            /**
         | 
| 41 | 
            +
             *
         | 
| 42 | 
            +
             * @author nicksieger
         | 
| 43 | 
            +
             */
         | 
| 44 | 
            +
            public class InformixRubyJdbcConnection extends RubyJdbcConnection {
         | 
| 45 | 
            +
                protected InformixRubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
         | 
| 46 | 
            +
                    super(runtime, metaClass);
         | 
| 47 | 
            +
                }
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                public static RubyClass createInformixJdbcConnectionClass(Ruby runtime, RubyClass jdbcConnection) {
         | 
| 50 | 
            +
                    RubyClass clazz = RubyJdbcConnection.getConnectionAdapters(runtime).defineClassUnder("InformixJdbcConnection",
         | 
| 51 | 
            +
                            jdbcConnection, INFORMIX_JDBCCONNECTION_ALLOCATOR);
         | 
| 52 | 
            +
                    clazz.defineAnnotatedMethods(InformixRubyJdbcConnection.class);
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    return clazz;
         | 
| 55 | 
            +
                }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                private static ObjectAllocator INFORMIX_JDBCCONNECTION_ALLOCATOR = new ObjectAllocator() {
         | 
| 58 | 
            +
                    public IRubyObject allocate(Ruby runtime, RubyClass klass) {
         | 
| 59 | 
            +
                        return new InformixRubyJdbcConnection(runtime, klass);
         | 
| 60 | 
            +
                    }
         | 
| 61 | 
            +
                };
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                /**
         | 
| 64 | 
            +
                 * Treat LONGVARCHAR as CLOB on Informix for purposes of converting a JDBC value to Ruby.
         | 
| 65 | 
            +
                 */
         | 
| 66 | 
            +
                @Override
         | 
| 67 | 
            +
                protected IRubyObject jdbcToRuby(Ruby runtime, int column, int type, ResultSet resultSet)
         | 
| 68 | 
            +
                        throws SQLException {
         | 
| 69 | 
            +
                    if (type == Types.LONGVARCHAR) {
         | 
| 70 | 
            +
                        type = Types.CLOB;
         | 
| 71 | 
            +
                    }
         | 
| 72 | 
            +
                    return super.jdbcToRuby(runtime, column, type, resultSet);
         | 
| 73 | 
            +
                }
         | 
| 74 | 
            +
            }
         | 
| @@ -28,11 +28,13 @@ package arjdbc.jdbc; | |
| 28 28 |  | 
| 29 29 | 
             
            import java.io.IOException;
         | 
| 30 30 |  | 
| 31 | 
            -
            import arjdbc. | 
| 31 | 
            +
            import arjdbc.derby.DerbyModule;
         | 
| 32 | 
            +
            import arjdbc.informix.InformixRubyJdbcConnection;
         | 
| 32 33 | 
             
            import arjdbc.mssql.MssqlRubyJdbcConnection;
         | 
| 33 | 
            -
            import arjdbc.sqlite3.Sqlite3RubyJdbcConnection;
         | 
| 34 34 | 
             
            import arjdbc.mysql.MySQLModule;
         | 
| 35 | 
            -
            import arjdbc. | 
| 35 | 
            +
            import arjdbc.oracle.OracleRubyJdbcConnection;
         | 
| 36 | 
            +
            import arjdbc.postgresql.PostgresqlRubyJdbcConnection;
         | 
| 37 | 
            +
            import arjdbc.sqlite3.Sqlite3RubyJdbcConnection;
         | 
| 36 38 |  | 
| 37 39 | 
             
            import org.jruby.Ruby;
         | 
| 38 40 | 
             
            import org.jruby.RubyClass;
         | 
| @@ -48,6 +50,8 @@ public class AdapterJavaService implements BasicLibraryService { | |
| 48 50 | 
             
                    RubyClass jdbcConnection = RubyJdbcConnection.createJdbcConnectionClass(runtime);
         | 
| 49 51 | 
             
                    PostgresqlRubyJdbcConnection.createPostgresqlJdbcConnectionClass(runtime, jdbcConnection);
         | 
| 50 52 | 
             
                    MssqlRubyJdbcConnection.createMssqlJdbcConnectionClass(runtime, jdbcConnection);
         | 
| 53 | 
            +
                    InformixRubyJdbcConnection.createInformixJdbcConnectionClass(runtime, jdbcConnection);
         | 
| 54 | 
            +
                    OracleRubyJdbcConnection.createOracleJdbcConnectionClass(runtime, jdbcConnection);
         | 
| 51 55 | 
             
                    Sqlite3RubyJdbcConnection.createSqlite3JdbcConnectionClass(runtime, jdbcConnection);
         | 
| 52 56 | 
             
                    RubyModule arJdbc = runtime.getOrCreateModule("ArJdbc");
         | 
| 53 57 |  | 
| @@ -123,21 +123,32 @@ public class RubyJdbcConnection extends RubyObject { | |
| 123 123 | 
             
                                String table_name = rubyApi.convertToRubyString(args[0]).getUnicodeValue();
         | 
| 124 124 | 
             
                                String schemaName = null;
         | 
| 125 125 |  | 
| 126 | 
            -
                                 | 
| 127 | 
            -
                                if( | 
| 128 | 
            -
                                     | 
| 129 | 
            -
                                    table_name = table_name.substring(index + 1);
         | 
| 126 | 
            +
                                final String[] name_parts = table_name.split( "\\." );
         | 
| 127 | 
            +
                                if ( name_parts.length > 3 ) {
         | 
| 128 | 
            +
                                    throw new SQLException("Table name '" + table_name + "' should not contain more than 2 '.'");
         | 
| 130 129 | 
             
                                }
         | 
| 131 130 |  | 
| 132 131 | 
             
                                DatabaseMetaData metadata = c.getMetaData();
         | 
| 132 | 
            +
                                String clzName = metadata.getClass().getName().toLowerCase();
         | 
| 133 | 
            +
                                boolean isDB2 = clzName.indexOf("db2") != -1 || clzName.indexOf("as400") != -1;
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                                String catalog = c.getCatalog();
         | 
| 136 | 
            +
                                if( name_parts.length == 2 ) {
         | 
| 137 | 
            +
                                    schemaName = name_parts[0];
         | 
| 138 | 
            +
                                    table_name = name_parts[1];
         | 
| 139 | 
            +
                                }
         | 
| 140 | 
            +
                                else if ( name_parts.length == 3 ) {
         | 
| 141 | 
            +
                                    catalog = name_parts[0];
         | 
| 142 | 
            +
                                    schemaName = name_parts[1];
         | 
| 143 | 
            +
                                    table_name = name_parts[2];
         | 
| 144 | 
            +
                                }
         | 
| 133 145 |  | 
| 134 146 | 
             
                                if(args.length > 2 && schemaName == null) schemaName = toStringOrNull(args[2]);
         | 
| 135 147 |  | 
| 136 148 | 
             
                                if (schemaName != null) schemaName = caseConvertIdentifierForJdbc(metadata, schemaName);
         | 
| 137 149 | 
             
                                table_name = caseConvertIdentifierForJdbc(metadata, table_name);
         | 
| 138 150 |  | 
| 139 | 
            -
                                 | 
| 140 | 
            -
                                if (schemaName != null) { catalog = schemaName; }
         | 
| 151 | 
            +
                                if (schemaName != null && !isDB2 && !databaseSupportsSchemas()) { catalog = schemaName; }
         | 
| 141 152 |  | 
| 142 153 | 
             
                                String[] tableTypes = new String[]{"TABLE","VIEW","SYNONYM"};
         | 
| 143 154 | 
             
                                RubyArray matchingTables = (RubyArray) tableLookupBlock(context.getRuntime(),
         | 
| @@ -645,10 +656,11 @@ public class RubyJdbcConnection extends RubyObject { | |
| 645 656 | 
             
                public static String caseConvertIdentifierForJdbc(DatabaseMetaData metadata, String value)
         | 
| 646 657 | 
             
                        throws SQLException {
         | 
| 647 658 | 
             
                    if (value == null) return null;
         | 
| 659 | 
            +
                    boolean isPostgres = metadata.getDatabaseProductName().equals("PostgreSQL");
         | 
| 648 660 |  | 
| 649 661 | 
             
                    if (metadata.storesUpperCaseIdentifiers()) {
         | 
| 650 662 | 
             
                        return value.toUpperCase();
         | 
| 651 | 
            -
                    } else if (metadata.storesLowerCaseIdentifiers()) {
         | 
| 663 | 
            +
                    } else if (metadata.storesLowerCaseIdentifiers() && ! isPostgres) {
         | 
| 652 664 | 
             
                        return value.toLowerCase();
         | 
| 653 665 | 
             
                    }
         | 
| 654 666 |  | 
| @@ -839,8 +851,9 @@ public class RubyJdbcConnection extends RubyObject { | |
| 839 851 | 
             
                        RubyHash row = RubyHash.newHash(runtime);
         | 
| 840 852 |  | 
| 841 853 | 
             
                        for (int i = 0; i < columnCount; i++) {
         | 
| 842 | 
            -
                            row.op_aset(context, columns[i].name, jdbcToRuby(runtime, i | 
| 854 | 
            +
                            row.op_aset(context, columns[i].name, jdbcToRuby(runtime, columns[i].index, columns[i].type, resultSet));
         | 
| 843 855 | 
             
                        }
         | 
| 856 | 
            +
             | 
| 844 857 | 
             
                        results.add(row);
         | 
| 845 858 | 
             
                    }
         | 
| 846 859 | 
             
                }
         | 
| @@ -970,10 +983,12 @@ public class RubyJdbcConnection extends RubyObject { | |
| 970 983 | 
             
                                DatabaseMetaData metadata = c.getMetaData();
         | 
| 971 984 | 
             
                                String clzName = metadata.getClass().getName().toLowerCase();
         | 
| 972 985 | 
             
                                boolean isOracle = clzName.indexOf("oracle") != -1 || clzName.indexOf("oci") != -1;
         | 
| 986 | 
            +
                                boolean isDerby = clzName.indexOf("derby") != 1;
         | 
| 973 987 |  | 
| 974 988 | 
             
                                String realschema = schemapat;
         | 
| 975 989 | 
             
                                String realtablepat = tablepat;
         | 
| 976 990 |  | 
| 991 | 
            +
                                if (isDerby && realschema != null && realschema.equals("")) realschema = null;  // Derby doesn't like empty-string schema name
         | 
| 977 992 | 
             
                                if (realtablepat != null) realtablepat = caseConvertIdentifierForJdbc(metadata, realtablepat);
         | 
| 978 993 | 
             
                                if (realschema != null) realschema = caseConvertIdentifierForJdbc(metadata, realschema);
         | 
| 979 994 |  | 
| @@ -1015,15 +1030,15 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1015 1030 | 
             
                    return RubyString.newUnicodeString(runtime, str);
         | 
| 1016 1031 | 
             
                }
         | 
| 1017 1032 |  | 
| 1018 | 
            -
                 | 
| 1019 | 
            -
                 | 
| 1020 | 
            -
                 | 
| 1021 | 
            -
                 | 
| 1022 | 
            -
                 | 
| 1023 | 
            -
                 | 
| 1024 | 
            -
                 | 
| 1033 | 
            +
                protected static final int COLUMN_NAME = 4;
         | 
| 1034 | 
            +
                protected static final int DATA_TYPE = 5;
         | 
| 1035 | 
            +
                protected static final int TYPE_NAME = 6;
         | 
| 1036 | 
            +
                protected static final int COLUMN_SIZE = 7;
         | 
| 1037 | 
            +
                protected static final int DECIMAL_DIGITS = 9;
         | 
| 1038 | 
            +
                protected static final int COLUMN_DEF = 13;
         | 
| 1039 | 
            +
                protected static final int IS_NULLABLE = 18;
         | 
| 1025 1040 |  | 
| 1026 | 
            -
                 | 
| 1041 | 
            +
                protected int intFromResultSet(ResultSet resultSet, int column) throws SQLException {
         | 
| 1027 1042 | 
             
                    int precision = resultSet.getInt(column);
         | 
| 1028 1043 |  | 
| 1029 1044 | 
             
                    return precision == 0 && resultSet.wasNull() ? -1 : precision;
         | 
| @@ -1032,20 +1047,11 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1032 1047 | 
             
                /**
         | 
| 1033 1048 | 
             
                 * Create a string which represents a sql type usable by Rails from the resultSet column
         | 
| 1034 1049 | 
             
                 * metadata object.
         | 
| 1035 | 
            -
                 *
         | 
| 1036 | 
            -
                 * @param numberAsBoolean the database uses decimal as a boolean data type
         | 
| 1037 | 
            -
                 * because it does not support optional SQL92 type or mandatory SQL99
         | 
| 1038 | 
            -
                 * booleans.
         | 
| 1039 1050 | 
             
                 */
         | 
| 1040 | 
            -
                 | 
| 1051 | 
            +
                protected String typeFromResultSet(ResultSet resultSet) throws SQLException {
         | 
| 1041 1052 | 
             
                    int precision = intFromResultSet(resultSet, COLUMN_SIZE);
         | 
| 1042 1053 | 
             
                    int scale = intFromResultSet(resultSet, DECIMAL_DIGITS);
         | 
| 1043 1054 |  | 
| 1044 | 
            -
                    // Assume db's which use decimal for boolean will not also specify a
         | 
| 1045 | 
            -
                    // valid precision 1 decimal also.  Seems sketchy to me...
         | 
| 1046 | 
            -
                    if (numberAsBoolean && precision != 1 &&
         | 
| 1047 | 
            -
                        resultSet.getInt(DATA_TYPE) == java.sql.Types.DECIMAL) precision = -1;
         | 
| 1048 | 
            -
             | 
| 1049 1055 | 
             
                    String type = resultSet.getString(TYPE_NAME);
         | 
| 1050 1056 | 
             
                    if (precision > 0) {
         | 
| 1051 1057 | 
             
                        type += "(" + precision;
         | 
| @@ -1070,7 +1076,6 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1070 1076 | 
             
                        List columns = new ArrayList();
         | 
| 1071 1077 | 
             
                        List pkeyNames = new ArrayList();
         | 
| 1072 1078 | 
             
                        String clzName = metadata.getClass().getName().toLowerCase();
         | 
| 1073 | 
            -
                        boolean isOracle = clzName.indexOf("oracle") != -1 || clzName.indexOf("oci") != -1;
         | 
| 1074 1079 |  | 
| 1075 1080 | 
             
                        RubyHash types = (RubyHash) native_database_types();
         | 
| 1076 1081 | 
             
                        IRubyObject jdbcCol = getJdbcColumnClass(context);
         | 
| @@ -1087,7 +1092,7 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1087 1092 | 
             
                                        RubyString.newUnicodeString(runtime,
         | 
| 1088 1093 | 
             
                                                caseConvertIdentifierForRails(metadata, colName)),
         | 
| 1089 1094 | 
             
                                        defaultValueFromResultSet(runtime, rs),
         | 
| 1090 | 
            -
                                        RubyString.newUnicodeString(runtime, typeFromResultSet(rs | 
| 1095 | 
            +
                                        RubyString.newUnicodeString(runtime, typeFromResultSet(rs)),
         | 
| 1091 1096 | 
             
                                        runtime.newBoolean(!rs.getString(IS_NULLABLE).trim().equals("NO"))
         | 
| 1092 1097 | 
             
                                    });
         | 
| 1093 1098 | 
             
                            columns.add(column);
         | 
| @@ -1192,6 +1197,14 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1192 1197 | 
             
                    return Java.java_to_ruby(this, JavaObject.wrap(getRuntime(), c), Block.NULL_BLOCK);
         | 
| 1193 1198 | 
             
                }
         | 
| 1194 1199 |  | 
| 1200 | 
            +
                /**
         | 
| 1201 | 
            +
                 * Some databases support schemas and others do not.
         | 
| 1202 | 
            +
                 * For ones which do this method should return true, aiding in decisions regarding schema vs database determination.
         | 
| 1203 | 
            +
                 */
         | 
| 1204 | 
            +
                protected boolean databaseSupportsSchemas() {
         | 
| 1205 | 
            +
                    return false;
         | 
| 1206 | 
            +
                }
         | 
| 1207 | 
            +
             | 
| 1195 1208 | 
             
                private static int whitespace(int start, ByteList bl) {
         | 
| 1196 1209 | 
             
                    int end = bl.begin + bl.realSize;
         | 
| 1197 1210 |  | 
| @@ -1222,11 +1235,13 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1222 1235 |  | 
| 1223 1236 | 
             
                public static class ColumnData {
         | 
| 1224 1237 | 
             
                    public IRubyObject name;
         | 
| 1238 | 
            +
                    public int index;
         | 
| 1225 1239 | 
             
                    public int type;
         | 
| 1226 1240 |  | 
| 1227 | 
            -
                    public ColumnData(IRubyObject name, int type) {
         | 
| 1241 | 
            +
                    public ColumnData(IRubyObject name, int type, int idx) {
         | 
| 1228 1242 | 
             
                        this.name = name;
         | 
| 1229 1243 | 
             
                        this.type = type;
         | 
| 1244 | 
            +
                        this.index = idx;
         | 
| 1230 1245 | 
             
                    }
         | 
| 1231 1246 |  | 
| 1232 1247 | 
             
                    public static ColumnData[] setup(Ruby runtime, DatabaseMetaData databaseMetadata,
         | 
| @@ -1242,7 +1257,7 @@ public class RubyJdbcConnection extends RubyObject { | |
| 1242 1257 | 
             
                                name = RubyJdbcConnection.caseConvertIdentifierForRails(databaseMetadata, metadata.getColumnLabel(i));
         | 
| 1243 1258 | 
             
                            }
         | 
| 1244 1259 |  | 
| 1245 | 
            -
                            columns[i - 1] = new ColumnData(RubyString.newUnicodeString(runtime, name), metadata.getColumnType(i));
         | 
| 1260 | 
            +
                            columns[i - 1] = new ColumnData(RubyString.newUnicodeString(runtime, name), metadata.getColumnType(i), i);
         | 
| 1246 1261 | 
             
                        }
         | 
| 1247 1262 |  | 
| 1248 1263 | 
             
                        return columns;
         | 
| @@ -28,12 +28,16 @@ package arjdbc.mssql; | |
| 28 28 | 
             
            import java.sql.ResultSet;
         | 
| 29 29 | 
             
            import java.sql.SQLException;
         | 
| 30 30 | 
             
            import java.sql.Types;
         | 
| 31 | 
            +
            import java.util.List;
         | 
| 31 32 |  | 
| 32 33 | 
             
            import arjdbc.jdbc.RubyJdbcConnection;
         | 
| 34 | 
            +
            import static arjdbc.jdbc.RubyJdbcConnection.ColumnData;
         | 
| 33 35 |  | 
| 34 36 | 
             
            import org.jruby.Ruby;
         | 
| 35 37 | 
             
            import org.jruby.RubyClass;
         | 
| 38 | 
            +
            import org.jruby.RubyString;
         | 
| 36 39 | 
             
            import org.jruby.runtime.ObjectAllocator;
         | 
| 40 | 
            +
            import org.jruby.runtime.ThreadContext;
         | 
| 37 41 | 
             
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 38 42 |  | 
| 39 43 | 
             
            /**
         | 
| @@ -42,8 +46,11 @@ import org.jruby.runtime.builtin.IRubyObject; | |
| 42 46 | 
             
             */
         | 
| 43 47 | 
             
            public class MssqlRubyJdbcConnection extends RubyJdbcConnection {
         | 
| 44 48 |  | 
| 49 | 
            +
                private RubyString _row_num;
         | 
| 50 | 
            +
             | 
| 45 51 | 
             
                protected MssqlRubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
         | 
| 46 52 | 
             
                    super(runtime, metaClass);
         | 
| 53 | 
            +
                    _row_num = runtime.newString("_row_num");
         | 
| 47 54 | 
             
                }
         | 
| 48 55 |  | 
| 49 56 | 
             
                public static RubyClass createMssqlJdbcConnectionClass(Ruby runtime, RubyClass jdbcConnection) {
         | 
| @@ -53,22 +60,68 @@ public class MssqlRubyJdbcConnection extends RubyJdbcConnection { | |
| 53 60 |  | 
| 54 61 | 
             
                    return clazz;
         | 
| 55 62 | 
             
                }
         | 
| 56 | 
            -
                private static ObjectAllocator MSSQL_JDBCCONNECTION_ALLOCATOR = new ObjectAllocator() {
         | 
| 57 63 |  | 
| 64 | 
            +
                private static ObjectAllocator MSSQL_JDBCCONNECTION_ALLOCATOR = new ObjectAllocator() {
         | 
| 58 65 | 
             
                    public IRubyObject allocate(Ruby runtime, RubyClass klass) {
         | 
| 59 66 | 
             
                        return new MssqlRubyJdbcConnection(runtime, klass);
         | 
| 60 67 | 
             
                    }
         | 
| 61 68 | 
             
                };
         | 
| 62 69 |  | 
| 70 | 
            +
                protected static IRubyObject booleanToRuby(Ruby runtime, ResultSet resultSet, boolean booleanValue)
         | 
| 71 | 
            +
                        throws SQLException {
         | 
| 72 | 
            +
                    if (booleanValue == false && resultSet.wasNull()) return runtime.getNil();
         | 
| 73 | 
            +
                    return runtime.newBoolean(booleanValue);
         | 
| 74 | 
            +
                }
         | 
| 75 | 
            +
             | 
| 63 76 | 
             
                /**
         | 
| 64 77 | 
             
                 * Treat LONGVARCHAR as CLOB on Mssql for purposes of converting a JDBC value to Ruby.
         | 
| 78 | 
            +
                 * Treat BOOLEAN/BIT as Boolean, rather than the default behaviour of conversion to string
         | 
| 65 79 | 
             
                 */
         | 
| 66 80 | 
             
                @Override
         | 
| 67 81 | 
             
                protected IRubyObject jdbcToRuby(Ruby runtime, int column, int type, ResultSet resultSet)
         | 
| 68 82 | 
             
                        throws SQLException {
         | 
| 83 | 
            +
                    if ( Types.BOOLEAN == type || Types.BIT == type ) {
         | 
| 84 | 
            +
                      return booleanToRuby(runtime, resultSet, resultSet.getBoolean(column));
         | 
| 85 | 
            +
                    }
         | 
| 69 86 | 
             
                    if (type == Types.LONGVARCHAR) {
         | 
| 70 87 | 
             
                        type = Types.CLOB;
         | 
| 71 88 | 
             
                    }
         | 
| 72 89 | 
             
                    return super.jdbcToRuby(runtime, column, type, resultSet);
         | 
| 73 90 | 
             
                }
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                /**
         | 
| 93 | 
            +
                 * Microsoft SQL 2000+ support schemas
         | 
| 94 | 
            +
                 */
         | 
| 95 | 
            +
                @Override
         | 
| 96 | 
            +
                protected boolean databaseSupportsSchemas() {
         | 
| 97 | 
            +
                    return true;
         | 
| 98 | 
            +
                }
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                @Override
         | 
| 101 | 
            +
                protected void populateFromResultSet(ThreadContext context, Ruby runtime, List results,
         | 
| 102 | 
            +
                                                     ResultSet resultSet, ColumnData[] columns) throws SQLException {
         | 
| 103 | 
            +
                    super.populateFromResultSet(context, runtime, results, resultSet, filterRowNumFromColumns(columns));
         | 
| 104 | 
            +
                }
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                /**
         | 
| 107 | 
            +
                 * Filter out the <tt>_row_num</tt> column from results.
         | 
| 108 | 
            +
                 */
         | 
| 109 | 
            +
                private ColumnData[] filterRowNumFromColumns(ColumnData[] columns) {
         | 
| 110 | 
            +
                    for (int i = 0; i < columns.length; i++) {
         | 
| 111 | 
            +
                        if (columns[i].name.equals(_row_num)) {
         | 
| 112 | 
            +
                            ColumnData[] filtered = new ColumnData[columns.length - 1];
         | 
| 113 | 
            +
                            if (i > 0) {
         | 
| 114 | 
            +
                                System.arraycopy(columns, 0, filtered, 0, i);
         | 
| 115 | 
            +
                            }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                            if (i + 1 < columns.length) {
         | 
| 118 | 
            +
                                System.arraycopy(columns, i + 1, filtered, i, columns.length - (i + 1));
         | 
| 119 | 
            +
                            }
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                            return filtered;
         | 
| 122 | 
            +
                        }
         | 
| 123 | 
            +
                    }
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                    return columns;
         | 
| 126 | 
            +
                }
         | 
| 74 127 | 
             
            }
         |