Schema F

Peter Schrammel, 11. Juni 2009 09:00

PostgreSQL bietet, wie einige andere Datenbanken auch, die Möglichkeit Schemata zu definieren um Namensräume für Tabellen und andere Datenbankobjekte anzulegen. Rails’ Postgres Adapter kann mit Schemata umgehen und mit ein paar Tricks hat man eine Menge interessanter Anwendungsmöglichkeiten.

Am Anfang war die Konfiguration. Diese erfolgt wie üblich in der config/database.yml. Der Postgres Adapter kennt das Schlüsselwort schema_search_path. Wenn man z.B.

schema_search_path:  myschema,otherschema,public

angibt, werden Datebankobjekte zunächst in myschema, dann in otherschema und schließlich in public gesucht.

Ein Anwendungsbeispiel wären z.B. temporäre Tabellen, die man während der Laufzeit erzeugen und mit einem ‘DROP SCHEMA xyz’ wieder löschen kann.

Will man hingegen eine ganze Railsanwendung in einem Schema laufen lassen, stößt man unweigerlich auf ein Problem mit den Tests. Bei Tests wird ein “DROP testdatenbank” durchgeführt und das nimmt natürlich nicht nur das verwendete Schema mit ins Datennirvana.

Deshalb muß der Task ‘create_database’ und die Methode ‘drop_database’ ein wenig gepatcht werden. Man erstellt also in ‘/lib/tasks/core.rake’ (oder wie man es auch immer nennen mag) eine Date folgenden Inhalts:

namespace :db do
  namespace :create do
    def create_database(config)
      #ensure the database exists:
      begin
        ccopy=config.dup.merge('schema_search_path' => 'public')
        ActiveRecord::Base.establish_connection(ccopy)
        ActiveRecord::Base.connection
      rescue
        @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
        begin
          ccopy=config.dup.merge('database' => 'postgres',
                       'schema_search_path' => 'public')
          ActiveRecord::Base.establish_connection(ccopy)
         ActiveRecord::Base.connection.create_database(config['database'],
           config.merge('encoding' => @encoding))
        rescue
          $stderr.puts $!, *($!.backtrace)
          $stderr.puts "Couldn't create database for #{config.inspect}"
        end
      else
        $stderr.puts "#{config['database']} already exists"
      end
 
      #ensure the schema exists:
      if schema_name=config['working_schema']
        begin
          ActiveRecord::Base.establish_connection(config)
          ActiveRecord::Base.connection
        rescue ActiveRecord::StatementInvalid => e
          puts e.class.ancestors.inspect
          begin
            ccopy=config.dup.merge('schema_search_path' => 'public')
            ActiveRecord::Base.establish_connection(ccopy)
            ActiveRecord::Base.connection.execute("CREATE SCHEMA \"#{schema_name}\"")
            ActiveRecord::Base.establish_connection(config)
          rescue
            $stderr.puts $!, *($!.backtrace)
            $stderr.puts "Couldn't create database for #{config.inspect}"
          end
          #some error
        end
 
      end #schema
    end
  end
end
 
def drop_database(config)
  ActiveRecord::Base.establish_connection(config.
      merge('database' => 'postgres', 'schema_search_path' => 'public'))
 
  if schema_name=config['working_schema']
    ActiveRecord::Base.connection.execute "DROP SCHEMA IF EXISTS \"#{schema_name}\" CASCADE"
  else
    ActiveRecord::Base.connection.drop_database config['database']
  end
end

Die config/database.yml könnte wie folgt aussehen:

test:
  adapter: postgresql
  database: development
  schema_search_path: test,base_data,public
  working_schema: test
  host: myhost
  username: username
  password: password

Durch diesen Patch kann man ein “working_schema” wie eine richtige Datenbank verwenden. Wozu das gut ist?

  • Mehrere Applikationen können sich eine Datenbank teilen.
  • Die Applikationen können sich Basisdaten (User, Geolocations, …) und andere Datenbankobjekte teilen.
  • Man benötigt keine DROP/CREATE DATABASE Privilegien.
  • Im Gegensatz zu Datenbanken können Abfragen schemata-übergreifend formuliert werden.

Lasst euch was einfallen und viel Spaß beim einem interessanten Setup (und das bestimmt nicht nach Schema F).

Bookmark and Share

Schlagworte: ,

Autor: Peter Schrammel,

Ein Rails-Entwickler in München. Immer auf der Suche nach Hirnfutter.

Artikel bewerten:

1 Sterne2 Sterne3 Sterne4 Sterne5 Sterne (1 Bewertung(en), durchschnittlich: 5.00 (max. 5)
Loading ... Loading ...

Comments are closed.