Postgres, MySQL, SQLite3

Before the db_hook rake task is invoked, Solano CI will install a database.yml into the config directory of your application. It then sets the environment so that the database.yml will point to the right database instance each time the db_hook is run and whenever one of your tests is run. A sample stanza from database.yml for the test environment is shown below; the same configuration is available in the production, staging, development, etc. environments.

test: &test
  adapter: <%= ENV['TDDIUM_DB_ADAPTER'] %>
  database: <%= ENV['TDDIUM_DB_NAME'] %>
  username: <%= ENV['TDDIUM_DB_USER'] %>
  password: <%= ENV['TDDIUM_DB_PASSWORD'] %>

When MySQL is configured, Solano CI will also export the TDDIUM_DB_MYSQL_SOCKET environment variable with the path to the MySQL Unix domain socket. For both Postgres, TDDIUM_DB_PG_HOST and TDDIUM_DB_PG_PORT contain the host address and TCP port for the database server; similarly for TDDIUM_DB_MYSQL_HOST and TDDIUM_DB_MYSQL_PORT.

In some rare cases you may need to specify the database adapter Solano CI configures. For instance, if you have both the mysql and mysql2 gems in your Gemfile, there is no general way to determine which adapter to use. You can force the choice of adapter like so:

---
mysql:
  adapter: 'mysql2'

In some cases you may need to load Postgres contrib packages or language extensions; the canonical way to do this is via a custom database initialization Rake hook task. You can read more about this process on the Loading Postgres Extensions page. Similarly, if you need to load a raw SQL schema dump, you can do so via the custom initialization hook; you can read more about raw SQL dump support on the Setup Hooks page.

Note that sqlite3, if enabled, will be configured to place the databases in the top-level db directory in your repository.

Postgres Extension Guide

Postgres ships with a number of “contrib” packages that provide extension languages, user-defined types, triggers, etc. By default, Solano CI does not install any of these extensions into your database cluster, however you can easily do so in the database setup hook. You can also load your own extensions out of your git repository.

As a simple example, take the PostGIS extension, which must be manually loaded into the database. You can do so by defining a custom db_hook. Assuming that this is the only setup required, you can use the following snippet:

---
hooks:
  worker_setup: createdb $TDDIUM_DB_NAME; psql $TDDIUM_DB_NAME -c 'CREATE EXTENSION postgis;'

Note that the postgis version can be forced explicitly via solano.yml; the default is the most recent available for the version of Postgres that you have enabled.

Alternatively, you can define a Rake task suitable for use in a Rails application (also as a gist):

namespace :tddium do
  desc "load database extensions"
  task db_hook: :"db:create" do
    # Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016  Solano Labs All Rights Reserved
    # https://gist.github.com/3006942
    Kernel.system("psql #{ENV['TDDIUM_DB_NAME']} -c 'CREATE EXTENSION postgis;'")

    Rake::Task["tddium:default_db_hook"].invoke
  end
end

Installing Extensions with Ruby

For a standard extension such as hstore, the simplest approach is to define a tddium:db_hook that first invokes the default db_hook and then loads the extension.

If your schema depends on the extension, it may be necessary to invoke the db:create task, load the extension, and then run migrations or load schema.rb. Some extensions are not captured by schema.rb, so you may need to invoke the db:structure:load task instead of our default, which tries db:schema:load.

A simple example for Postgres 8.4 that loads the hstore extension is shown below. If you are using Postgres 9.1 or later, be sure to use CREATE EXTENSION instead; you can read more about loading extensions in Postgres 9.1 here or adapt this gist: https://gist.github.com/3006942.

# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Solano Labs All Rights Reserved

namespace :tddium do
  desc "load database extensions"
  task :db_hook do
    Rake::Task["tddium:default_db_hook"].invoke

    # There is not yet a way to determine Tddium PG version from environment
    contrib = '/usr/share/postgresql/8.4/contrib/hstore.sql'
    Kernel.system("psql #{ENV['TDDIUM_DB_NAME']} -f #{contrib}")
  end
end

The above example is available as a gist: https://gist.github.com/2042687

Multiple Relational Database Servers

Solano CI supports the use of multiple relational database servers by the same application at the same time. For instance, an application may wish to use both MySQL and PostgreSQL at the same time:

mysql:
  version: '5.5'
postgresql:
  version: '9.3'

To support this, Solano CI will stand up a copy of each database server, export configuration information to the environment, and write out a configuration file, config/tddium-database.yml. A snippet of this configuration file follows showing both the format of the YAML configuration file and the environment variables exported by Solano CI:

sqlite:
  test: &test
    adapter: <%= ENV['TDDIUM_DB_SQLITE_ADAPTER'] %>
    database: <%= ENV['TDDIUM_DB_SQLITE_NAME'] %>
    username: <%= ENV['TDDIUM_DB_SQLITE_USER'] %>
    password: <%= ENV['TDDIUM_DB_SQLITE_PASSWORD'] %>
    <%= "socket: #{ENV['TDDIUM_DB_SQLITE_SOCKET']}" if ENV['TDDIUM_DB_SQLITE_SOCKET'] %>

The top-level keys are symbols naming the type of the database (sqlite, postgres, mysql). The next level of the nested hash are strings naming environments (test, development, etc.). The last is as in database.yml above.