lib/rubyrep/connection_extenders/postgresql_extender.rb in rubyrep-1.0.4 vs lib/rubyrep/connection_extenders/postgresql_extender.rb in rubyrep-1.0.5

- old
+ new

@@ -82,94 +82,130 @@ module ConnectionExtenders # Provides various PostgreSQL specific functionality required by Rubyrep. module PostgreSQLExtender RR::ConnectionExtenders.register :postgresql => self + + # Returns an array of schemas in the current search path. + def schemas + unless @schemas + search_path = select_one("show search_path")['search_path'] + @schemas = search_path.split(/,/).map { |p| quote(p.strip) }.join(',') + end + @schemas + end + # *** Monkey patch*** + # Returns the list of all tables in the schema search path or a specified schema. + # This overwrites the according ActiveRecord::PostgreSQLAdapter method + # to make sure that also search paths with spaces work + # (E. g. 'public, rr' instead of only 'public,rr') + def tables(name = nil) + select_all(<<-SQL, name).map { |row| row['tablename'] } + SELECT tablename + FROM pg_tables + WHERE schemaname IN (#{schemas}) + SQL + end + # Returns an ordered list of primary key column names of the given table def primary_key_names(table) row = self.select_one(<<-end_sql) SELECT relname FROM pg_class - WHERE relname = '#{table}' + WHERE relname = '#{table}' and relnamespace IN + (SELECT oid FROM pg_namespace WHERE nspname in (#{schemas})) end_sql - if row.nil? - raise "table '#{table}' does not exist" - end + raise "table '#{table}' does not exist" if row.nil? - row = self.select_one(<<-end_sql) + row = self.select_one(<<-end_sql) SELECT cons.conkey FROM pg_class rel JOIN pg_constraint cons ON (rel.oid = cons.conrelid) - WHERE cons.contype = 'p' AND rel.relname = '#{table}' - end_sql - if row.nil? - return [] - end - column_parray = row['conkey'] + WHERE cons.contype = 'p' AND rel.relname = '#{table}' AND rel.relnamespace IN + (SELECT oid FROM pg_namespace WHERE nspname in (#{schemas})) + end_sql + return [] if row.nil? + column_parray = row['conkey'] - # Change a Postgres Array of attribute numbers - # (returned in String form, e. g.: "{1,2}") into an array of Integers - column_ids = column_parray.sub(/^\{(.*)\}$/,'\1').split(',').map {|a| a.to_i} + # Change a Postgres Array of attribute numbers + # (returned in String form, e. g.: "{1,2}") into an array of Integers + column_ids = column_parray.sub(/^\{(.*)\}$/,'\1').split(',').map {|a| a.to_i} - columns = {} - rows = self.select_all(<<-end_sql) + columns = {} + rows = self.select_all(<<-end_sql) SELECT attnum, attname FROM pg_class rel JOIN pg_constraint cons ON (rel.oid = cons.conrelid) JOIN pg_attribute attr ON (rel.oid = attr.attrelid and attr.attnum = any (cons.conkey)) - WHERE cons.contype = 'p' AND rel.relname = '#{table}' - end_sql - sorted_columns = [] - if not rows.nil? - rows.each() {|r| columns[r['attnum'].to_i] = r['attname']} - sorted_columns = column_ids.map {|column_id| columns[column_id]} - end - sorted_columns - end + WHERE cons.contype = 'p' AND rel.relname = '#{table}' AND rel.relnamespace IN + (SELECT oid FROM pg_namespace WHERE nspname in (#{schemas})) + end_sql + sorted_columns = [] + if not rows.nil? + rows.each() {|r| columns[r['attnum'].to_i] = r['attname']} + sorted_columns = column_ids.map {|column_id| columns[column_id]} + end + sorted_columns + end - # Returns for each given table, which other tables it references via - # foreign key constraints. - # * tables: an array of table names - # Returns: a hash with - # * key: name of the referencing table - # * value: an array of names of referenced tables - def referenced_tables(tables) - rows = self.select_all(<<-end_sql) + # Returns for each given table, which other tables it references via + # foreign key constraints. + # * tables: an array of table names + # Returns: a hash with + # * key: name of the referencing table + # * value: an array of names of referenced tables + def referenced_tables(tables) + rows = self.select_all(<<-end_sql) select distinct referencing.relname as referencing_table, referenced.relname as referenced_table from pg_class referencing left join pg_constraint on referencing.oid = pg_constraint.conrelid left join pg_class referenced on pg_constraint.confrelid = referenced.oid where referencing.relkind='r' and referencing.relname in ('#{tables.join("', '")}') - end_sql - result = {} - rows.each do |row| - unless result.include? row['referencing_table'] - result[row['referencing_table']] = [] + and referencing.relnamespace IN + (SELECT oid FROM pg_namespace WHERE nspname in (#{schemas})) + end_sql + result = {} + rows.each do |row| + unless result.include? row['referencing_table'] + result[row['referencing_table']] = [] + end + if row['referenced_table'] != nil + result[row['referencing_table']] << row['referenced_table'] + end + end + result end - if row['referenced_table'] != nil - result[row['referencing_table']] << row['referenced_table'] + + # *** Monkey patch*** + # Returns the list of a table's column names, data types, and default values. + # This overwrites the according ActiveRecord::PostgreSQLAdapter method + # to + # * work with tables containing a dot (".") and + # * only look for tables in the current schema search path. + def column_definitions(table_name) #:nodoc: + rows = self.select_all <<-end_sql + SELECT + a.attname as name, + format_type(a.atttypid, a.atttypmod) as type, + d.adsrc as source, + a.attnotnull as notnull + FROM pg_attribute a LEFT JOIN pg_attrdef d + ON a.attrelid = d.adrelid AND a.attnum = d.adnum + WHERE a.attrelid = ( + SELECT oid FROM pg_class + WHERE relname = '#{table_name}' AND relnamespace IN + (SELECT oid FROM pg_namespace WHERE nspname in (#{schemas})) + LIMIT 1 + ) + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum + end_sql + + rows.map {|row| [row['name'], row['type'], row['source'], row['notnull']]} end + end - result end - - # *** Monkey patch*** - # Returns the list of a table's column names, data types, and default values. - # This overwrites the according ActiveRecord::PostgreSQLAdapter method - # to work with tables containing a dot ("."). - def column_definitions(table_name) #:nodoc: - query <<-end_sql - SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull - FROM pg_attribute a LEFT JOIN pg_attrdef d - ON a.attrelid = d.adrelid AND a.attnum = d.adnum - WHERE a.attrelid = (SELECT oid FROM pg_class WHERE relname = '#{table_name}') - AND a.attnum > 0 AND NOT a.attisdropped - ORDER BY a.attnum - end_sql - end - -end -end end