Skip to content

Commit

Permalink
Refactoring mysql.py into a more abstract db tier.
Browse files Browse the repository at this point in the history
  • Loading branch information
heynemann committed Aug 4, 2010
1 parent 49f62c2 commit 4dc7f71
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -28,7 +28,7 @@ compile: clean
test: compile
@make clean
@echo "Starting tests..."
@nosetests -s --verbose --with-coverage --cover-erase --cover-package=cli,config,core,helpers,main,mysql tests/*
@nosetests -s --verbose --with-coverage --cover-erase --cover-package=cli,config,core,dbtier,helpers,main,mysql tests/*
@make clean

install:
Expand Down
2 changes: 2 additions & 0 deletions setup.py
@@ -1,3 +1,5 @@
# coding: utf-8

from setuptools import setup, find_packages
import re

Expand Down
2 changes: 2 additions & 0 deletions src/__init__.py
@@ -1,3 +1,5 @@
# coding: utf-8

from getpass import getpass
import codecs
import sys
Expand Down
2 changes: 2 additions & 0 deletions src/cli.py
@@ -1,3 +1,5 @@
# coding: utf-8

from optparse import OptionParser
import sys

Expand Down
2 changes: 2 additions & 0 deletions src/config.py
@@ -1,3 +1,5 @@
# coding: utf-8

import codecs
import os
import sys
Expand Down
56 changes: 56 additions & 0 deletions src/dbtier.py
@@ -0,0 +1,56 @@
# coding: utf-8

from core.exceptions import MigrationException

class DbTier(object):
def __init__(self, config, db_driver):
"""initializes a new DbTier"""
self.config = config
self.db_driver = db_driver

#orchestrators
def initialize_db(self):
if self.config.get("drop_db_first"):
self.drop_db()
self.create_db()

def verify_db_consistency(self):
self.create_primary_key_in_versions_table()

#executers

def create_db(self):
db_name = self.config.get("db_name")
sql = "create database if not exists %s;" % db_name

self.db_driver.execute(sql)

def drop_db(self):
try:
db_name = self.config.get("db_name")
sql = "set foreign_key_checks=0; drop database if exists %s;" % db_name
self.db_driver.execute(sql)
except MigrationException, e:
raise MigrationException("can't drop database '%s'; database doesn't exist" % db_name)

def create_version_table(self):
version_table = self.config.get("db_version_table")
sql = "create table if not exists %s ( version varchar(20) NOT NULL default \"0\" );" % version_table
self.db_driver.execute(sql)

def verify_if_migration_zero_is_present(self):
version_table = self.config.get("db_version_table")
sql = "select count(*) from %s;" % version_table
count = self.db_driver.query_scalar(sql)

# if there is not a version register, insert one
if count == 0:
sql = "insert into %s (version) values (\"0\");" % version_table
self.db_driver.execute(sql)

def create_primary_key_in_versions_table(self):
try:
sql = "alter table version add id int(11) primary key auto_increment not null;"
self.db_driver.execute(sql)
except MigrationException:
pass
2 changes: 2 additions & 0 deletions src/helpers.py
@@ -1,3 +1,5 @@
# coding: utf-8

import re

class Lists(object):
Expand Down
2 changes: 2 additions & 0 deletions src/main.py
@@ -1,3 +1,5 @@
# coding: utf-8

from cli import CLI
from core import Migration, SimpleDBMigrate
from helpers import Lists
Expand Down
9 changes: 8 additions & 1 deletion src/mysql.py
Expand Up @@ -34,7 +34,14 @@ def __mysql_connect(self, connect_using_db_name=True):
return conn
except Exception, e:
raise Exception("could not connect to database: %s" % e)


def query_scalar(self, sql):
db = self.__mysql_connect()
cursor = db.cursor()
cursor.execute(sql)
count = cursor.fetchone()[0]
db.close()

def __execute(self, sql, execution_log=None):
db = self.__mysql_connect()
cursor = db.cursor()
Expand Down
2 changes: 2 additions & 0 deletions tests/cli_test.py
@@ -1,3 +1,5 @@
# coding: utf-8

import unittest

from cli import *
Expand Down
2 changes: 2 additions & 0 deletions tests/config_test.py
@@ -1,3 +1,5 @@
# coding: utf-8

import codecs
import unittest

Expand Down
153 changes: 153 additions & 0 deletions tests/dbtier_tests.py
@@ -0,0 +1,153 @@
# coding: utf-8

from fudge import Fake, with_fakes, with_patched_object, clear_expectations
from fudge.inspector import arg

from src.dbtier import DbTier
from src.core.exceptions import MigrationException

def get_tier():
config = Fake('config')
driver = Fake('driver')
tier = DbTier(config, driver)

return tier, config, driver

@with_fakes
def test_new_db_tier_keeps_track_of_db_driver():
clear_expectations()

tier, config, driver = get_tier()

assert tier.db_driver == driver

@with_fakes
@with_patched_object(DbTier, 'create_primary_key_in_versions_table', Fake(callable=True))
def test_verify_db_consistency_calls_the_right_methods():
clear_expectations()

tier, config, driver = get_tier()

tier.verify_db_consistency()

@with_fakes
def test_create_primary_key_in_versions_table_finishes_if_everything_works():
clear_expectations()

tier, config, driver = get_tier()

driver.expects('execute').with_args('alter table version add id int(11) primary key auto_increment not null;')

tier.create_primary_key_in_versions_table()

@with_fakes
def test_create_primary_key_in_versions_table_does_nothing_if_fails():
clear_expectations()

tier, config, driver = get_tier()

driver.expects('execute').with_args('alter table version add id int(11) primary key auto_increment not null;').raises(MigrationException())

tier.create_primary_key_in_versions_table()

@with_fakes
def test_drop_database_if_everything_works():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('db_name').returns('myDb')

driver.expects('execute').with_args('set foreign_key_checks=0; drop database if exists myDb;')

tier.drop_db()

@with_fakes
def test_drop_database_raises_migration_error_when_exception():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('db_name').returns('myDb')

driver.expects('execute').with_args('set foreign_key_checks=0; drop database if exists myDb;').raises(MigrationException())

try:
tier.drop_db()
except MigrationException, m:
assert str(m) == "can't drop database 'myDb'; database doesn't exist"
return

assert False, "should not have gotten this far"

@with_fakes
@with_patched_object(DbTier, 'drop_db', Fake(callable=True))
@with_patched_object(DbTier, 'create_db', Fake(callable=True))
def test_initialize_db_calls_drop_if_config_says_to():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('drop_db_first').returns(True)

tier.initialize_db()

@with_fakes
@with_patched_object(DbTier, 'create_db', Fake(callable=True))
def test_initialize_db_does_not_call_drop_if_config_says_not_to():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('drop_db_first').returns(False)

tier.initialize_db()

@with_fakes
def test_create_db():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('db_name').returns('myDb')

driver.expects('execute').with_args("create database if not exists myDb;")

tier.create_db()

@with_fakes
def test_create_version_table():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('db_version_table').returns('versions')

driver.expects('execute').with_args('create table if not exists versions ( version varchar(20) NOT NULL default \"0\" );')

tier.create_version_table()

@with_fakes
def test_that_no_migration_zero_is_inserted_if_some_migration_is_there():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('db_version_table').returns('versions')

driver.expects('query_scalar').with_args('select count(*) from versions;').returns(1)

tier.verify_if_migration_zero_is_present()

@with_fakes
def test_that_migration_zero_is_inserted_when_needed():
clear_expectations()

tier, config, driver = get_tier()

config.expects('get').with_args('db_version_table').returns('versions')

driver.expects('query_scalar').with_args('select count(*) from versions;').returns(0)
driver.expects('execute').with_args('insert into versions (version) values (\"0\");')

tier.verify_if_migration_zero_is_present()

0 comments on commit 4dc7f71

Please sign in to comment.