Skip to content

Commit

Permalink
a better (default) table_exists? (aligned with columns_internal) for all
Browse files Browse the repository at this point in the history
  • Loading branch information
kares committed Feb 20, 2013
1 parent 3d9938a commit 5f2deb4
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 45 deletions.
2 changes: 1 addition & 1 deletion lib/arjdbc/jdbc/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def tables(name = nil)
end

def table_exists?(name)
jdbc_columns(name) rescue nil
@connection.table_exists?(name) # schema_name = nil
end

def indexes(table_name, name = nil, schema_name = nil)
Expand Down
Binary file modified lib/arjdbc/jdbc/adapter_java.jar
Binary file not shown.
4 changes: 0 additions & 4 deletions lib/arjdbc/mssql/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,6 @@ def remove_check_constraints(table_name, column_name)
def remove_index(table_name, options = {})
execute "DROP INDEX #{table_name}.#{index_name(table_name, options)}"
end

def table_exists?(name)
!! ( jdbc_columns(name) rescue nil )
end

SKIP_COLUMNS_TABLE_NAMES_RE = /^information_schema\./i # :nodoc:

Expand Down
66 changes: 46 additions & 20 deletions src/java/arjdbc/jdbc/RubyJdbcConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBignum;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
import org.jruby.RubyHash;
import org.jruby.RubyModule;
Expand Down Expand Up @@ -182,7 +183,7 @@ public IRubyObject execute(final ThreadContext context, final IRubyObject sql) {
return (IRubyObject) withConnectionAndRetry(context, new SQLBlock() {
public Object call(Connection c) throws SQLException {
Statement stmt = null;
String query = rubyApi.convertToRubyString(sql).getUnicodeValue();
String query = sql.convertToString().getUnicodeValue();
try {
stmt = c.createStatement();
if (genericExecute(stmt, query)) {
Expand Down Expand Up @@ -223,7 +224,7 @@ public IRubyObject execute_id_insert(final ThreadContext context, final IRubyObj
final IRubyObject id) throws SQLException {
return (IRubyObject) withConnectionAndRetry(context, new SQLBlock() {
public Object call(Connection c) throws SQLException {
String insert = rubyApi.convertToRubyString(sql).getUnicodeValue();
String insert = sql.convertToString().getUnicodeValue();
PreparedStatement ps = c.prepareStatement(insert);
try {
ps.setLong(1, RubyNumeric.fix2long(id));
Expand Down Expand Up @@ -265,20 +266,18 @@ public Object call(Connection c) throws SQLException {
}

@JRubyMethod(name = "execute_query", required = 1)
public IRubyObject execute_query(final ThreadContext context, IRubyObject _sql)
public IRubyObject execute_query(final ThreadContext context, IRubyObject sql)
throws SQLException, IOException {
String sql = rubyApi.convertToRubyString(_sql).getUnicodeValue();

return executeQuery(context, sql, 0);
String query = sql.convertToString().getUnicodeValue();
return executeQuery(context, query, 0);
}

@JRubyMethod(name = "execute_query", required = 2)
public IRubyObject execute_query(final ThreadContext context, IRubyObject _sql,
IRubyObject _maxRows) throws SQLException, IOException {
String sql = rubyApi.convertToRubyString(_sql).getUnicodeValue();
int maxrows = RubyNumeric.fix2int(_maxRows);

return executeQuery(context, sql, maxrows);
public IRubyObject execute_query(final ThreadContext context, IRubyObject sql,
IRubyObject max_rows) throws SQLException, IOException {
String query = sql.convertToString().getUnicodeValue();
final int maxRows = RubyNumeric.fix2int(max_rows);
return executeQuery(context, query, maxRows);
}

protected IRubyObject executeQuery(final ThreadContext context, final String query, final int maxRows) {
Expand Down Expand Up @@ -308,7 +307,7 @@ public IRubyObject execute_update(final ThreadContext context, final IRubyObject
return (IRubyObject) withConnectionAndRetry(context, new SQLBlock() {
public Object call(Connection c) throws SQLException {
Statement stmt = null;
String update = rubyApi.convertToRubyString(sql).getUnicodeValue();
String update = sql.convertToString().getUnicodeValue();
try {
stmt = c.createStatement();
return context.getRuntime().newFixnum((long)stmt.executeUpdate(update));
Expand Down Expand Up @@ -411,11 +410,14 @@ public Object call(Connection c) throws SQLException {
}

@JRubyMethod(name = "select?", required = 1, meta = true, frame = false)
public static IRubyObject select_p(ThreadContext context, IRubyObject recv, IRubyObject _sql) {
ByteList sql = rubyApi.convertToRubyString(_sql).getByteList();

return context.getRuntime().newBoolean(startsWithNoCaseCmp(sql, SELECT) || startsWithNoCaseCmp(sql, WITH) ||
startsWithNoCaseCmp(sql, SHOW) || startsWithNoCaseCmp(sql, CALL));
public static IRubyObject select_p(ThreadContext context, IRubyObject self, IRubyObject sql) {
final ByteList sqlBytes = sql.convertToString().getByteList();
return context.getRuntime().newBoolean(
startsWithNoCaseCmp(sqlBytes, SELECT) ||
startsWithNoCaseCmp(sqlBytes, WITH) ||
startsWithNoCaseCmp(sqlBytes, SHOW) ||
startsWithNoCaseCmp(sqlBytes, CALL)
);
}

@JRubyMethod(name = "set_native_database_types")
Expand Down Expand Up @@ -463,6 +465,30 @@ protected String[] getTableTypes() {
return TABLE_TYPES;
}

@JRubyMethod(name = "table_exists?", required = 1, optional = 1)
public IRubyObject table_exists_p(final ThreadContext context, final IRubyObject[] args) {
IRubyObject name = args[0], schema_name = args.length > 1 ? args[1] : null;
if ( ! ( name instanceof RubyString ) ) {
name = name.callMethod(context, "to_s");
}
final String tableName = ((RubyString) name).getUnicodeValue();
final String tableSchema = schema_name == null ? null : schema_name.convertToString().getUnicodeValue();
final Ruby runtime = context.getRuntime();

return (RubyBoolean) withConnectionAndRetry(context, new SQLBlock() {
public Object call(final Connection connection) throws SQLException {
final TableNameComponents components =
extractTableNameComponents(connection, tableSchema, tableName);

final Collection matchingTables = (Collection) tableLookupBlock(
runtime, components.catalog, components.schema, components.table, getTableTypes()
).call(connection);

return runtime.newBoolean( ! matchingTables.isEmpty() );
}
});
}

@JRubyMethod(name = {"columns", "columns_internal"}, required = 1, optional = 2)
public IRubyObject columns_internal(final ThreadContext context, final IRubyObject[] args)
throws SQLException, IOException {
Expand All @@ -474,10 +500,10 @@ public Object call(final Connection connection) throws SQLException {
String tableName = rubyApi.convertToRubyString(args[0]).getUnicodeValue();
TableNameComponents components = extractTableNameComponents(connection, defaultSchema, tableName);

RubyArray matchingTables = (RubyArray) tableLookupBlock(context.getRuntime(),
Collection matchingTables = (Collection) tableLookupBlock(context.getRuntime(),
components.catalog, components.schema, components.table, getTableTypes()).call(connection);
if (matchingTables.isEmpty()) {
throw new SQLException("Table " + tableName + " does not exist");
throw new SQLException("table: " + tableName + " does not exist");
}

final DatabaseMetaData metaData = connection.getMetaData();
Expand Down
5 changes: 5 additions & 0 deletions test/db/oracle/simple_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ class OracleSimpleTest < Test::Unit::TestCase
include ActiveRecord3TestMethods
include DirtyAttributeTests

# #override
def test_insert_returns_id
# TODO not supported/implemented
end

def test_default_id_type_is_integer
assert Integer === Entry.first.id
end
Expand Down
42 changes: 22 additions & 20 deletions test/simple.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,16 @@ def with_partial_updates(klass, on = true)
module SimpleTestMethods
include FixtureSetup

def test_entries_created
assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^entries$/i}, "entries not created"
def test_tables
assert_not_empty ActiveRecord::Base.connection.tables
tables = ActiveRecord::Base.connection.tables
assert tables.find { |t| t =~ /^entries$/i }, "entries not created: #{tables.inspect}"
assert tables.map(&:downcase).include?('users'), "users table not found: #{tables.inspect}"
end

def test_users_created
assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^users$/i}, "users not created"
def test_table_exists?
assert_true ActiveRecord::Base.connection.table_exists? 'entries'
assert_false ActiveRecord::Base.connection.table_exists? 'blahbls'
end

def test_entries_empty
Expand All @@ -182,23 +186,21 @@ def test_find_with_string_slug
end

def test_insert_returns_id
unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
value = ActiveRecord::Base.connection.insert("INSERT INTO entries (title, content, rating) VALUES('insert_title', 'some content', 1)")
value = ActiveRecord::Base.connection.insert("INSERT INTO entries (title, content, rating) VALUES('insert_title', 'some content', 1)")
assert !value.nil?
entry = Entry.find_by_title('insert_title')
assert_equal entry.id, value

# Ensure we get the id even if the PK column is not named 'id'
1.upto(4) do |i|
cpn_name = "return id test#{i}"
cpn = CustomPkName.new
cpn.name = cpn_name
cpn.save
value = cpn.custom_id
assert !value.nil?
entry = Entry.find_by_title('insert_title')
assert_equal entry.id, value

# Ensure we get the id even if the PK column is not named 'id'
1.upto(4) do |i|
cpn_name = "return id test#{i}"
cpn = CustomPkName.new
cpn.name = cpn_name
cpn.save
value = cpn.custom_id
assert !value.nil?
cpn = CustomPkName.find_by_name(cpn_name)
assert_equal cpn.custom_id, value
end
cpn = CustomPkName.find_by_name(cpn_name)
assert_equal cpn.custom_id, value
end
end

Expand Down

0 comments on commit 5f2deb4

Please sign in to comment.