Skip to content

Commit

Permalink
Add views, triggers and procedures
Browse files Browse the repository at this point in the history
  • Loading branch information
sixela committed Sep 9, 2015
1 parent 350e47a commit 81d4f12
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 2 deletions.
36 changes: 34 additions & 2 deletions schemaobject/database.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from schemaobject.option import SchemaOption
from schemaobject.table import TableSchemaBuilder
from schemaobject.procedure import ProcedureSchemaBuilder
from schemaobject.collections import OrderedDict

from schemaobject.trigger import TriggerSchemaBuilder
from schemaobject.view import ViewSchemaBuilder

def DatabaseSchemaBuilder(instance):
"""
Expand All @@ -26,7 +28,7 @@ def DatabaseSchemaBuilder(instance):
else:
params = None

databases = conn.execute(sql, params)
databases = conn.execute(sql, (params,))

if not databases:
return d
Expand Down Expand Up @@ -70,6 +72,9 @@ def __init__(self, name, parent):
self.name = name
self._options = None
self._tables = None
self._procedures = None
self._triggers = None
self._views = None

@property
def tables(self):
Expand All @@ -82,6 +87,15 @@ def tables(self):
self._tables = TableSchemaBuilder(database=self)
return self._tables

@property
def views(self):
"""
Lazily loaded dictionnary of all the views within this database. See ViewSchema for usage
"""
if self._views == None:
self._views = ViewSchemaBuilder(database=self)
return self._views

@property
def options(self):
"""
Expand All @@ -94,6 +108,24 @@ def options(self):
self._options = OrderedDict()
return self._options

@property
def procedures(self):
"""
Lazily loaded dictionnary of all the procedures within this database. See ProcedureSchema for usage.
"""
if self._procedures is None:
self._procedures = ProcedureSchemaBuilder(database=self)
return self._procedures

@property
def triggers(self):
"""
Lazily loaded dictionnary of all the triggers within this database. See TriggerSchema for usage.
"""
if self._triggers is None:
self._triggers = TriggerSchemaBuilder(database=self)
return self._triggers

def select(self):
"""
Generate the SQL to select this database
Expand Down
76 changes: 76 additions & 0 deletions schemaobject/procedure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import re
from schemaobject.collections import OrderedDict

def ProcedureSchemaBuilder(database):
conn = database.parent.connection

p = OrderedDict()

sql = """
SELECT name, param_list, body, created, modified, comment
FROM mysql.proc
WHERE type = 'PROCEDURE'
AND db = '%s'
"""

procedures = conn.execute(sql % database.name)

if not procedures:
return p

for proc_info in procedures:
proc_name = proc_info['name']

proc = ProcedureSchema(name=proc_name, parent=database)
proc.param_list = proc_info['param_list']
body = re.sub('--.*','',proc_info['body']) # Remove SQL comments
# Remove newlines to be able to compare strings
body = body.replace('\n',' ').replace('\r', ' ').replace('\r\n', ' ')
proc.body = body
proc.created = proc_info['created']
proc.modified = proc_info['modified']
proc.comment = proc_info['comment']

p[proc_name] = proc

return p

class ProcedureSchema(object):
def __init__(self, name, parent):
self.parent = parent
self.name = name
self.param_list = None
self.body = None
self.created = None
self.modified = None
self.comment = None

def define(self):
sql = []
sql.append("`%s` (%s) %s" % (self.name, self.param_list,self.body))

if self.comment is not None and len(self.comment) > 0:
sql.append("COMMENT '%s'" % self.comment)

return ' '.join(sql)

def create(self):
return "DELIMITER ;; CREATE PROCEDURE %s;; DELIMITER ;" % self.define()

def modify(self, *args, **kwargs):
pass # Not needed for now, one cannot alter body

def drop(self):
return "DROP PROCEDURE `%s`;" % self.name

def __eq__(self, other):
if not isinstance(other, ProcedureSchema):
return False

return ((self.name == other.name)
and (self.param_list == other.param_list)
and (self.body == other.body)
and (self.comment == other.comment))

def __ne__(self, other):
return not self.__eq__(other)
72 changes: 72 additions & 0 deletions schemaobject/trigger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from schemaobject.collections import OrderedDict

def TriggerSchemaBuilder(database):
conn = database.parent.connection

t = OrderedDict()

sql = """
SELECT TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE,
ACTION_STATEMENT, ACTION_TIMING
FROM INFORMATION_SCHEMA.TRIGGERS
WHERE TRIGGER_SCHEMA='%s'
"""

triggers = conn.execute(sql % database.name)

if not triggers:
return t

for trigger in triggers:
trig_name = trigger['TRIGGER_NAME']

trig = TriggerSchema(name=trig_name, parent=database)
trig.statement = trigger['ACTION_STATEMENT']
trig.timing = trigger['ACTION_TIMING']
trig.event = trigger['EVENT_MANIPULATION']
trig.table = trigger['EVENT_OBJECT_TABLE']

t[trig_name] = trig

return t

class TriggerSchema(object):
def __init__(self, name, parent):
self.parent = parent
self.name = name
self.statement = None
self.timing = None
self.event = None
self.table = None

def define(self):
sql = []
sql.append("`%s` %s %s ON %s FOR EACH ROW %s" % (self.name,
self.timing,
self.event,
self.table,
self.statement))

return ' '.join(sql)

def create(self):
return "DELIMITER ;; CREATE TRIGGER %s;; DELIMITER ;" % self.define()

def modify(self):
pass # Need to drop + re-create

def drop(self):
return "DROP TRIGGER `%s`;" % self.name

def __eq__(self,other):
if not isinstance(other, TriggerSchema):
return False

return ((self.name == other.name)
and (self.statement == other.statement)
and (self.timing == other.timing)
and (self.table == other.table)
and (self.event == other.event))

def __ne__(self, other):
return not self._eq__(other)
53 changes: 53 additions & 0 deletions schemaobject/view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from schemaobject.collections import OrderedDict

def ViewSchemaBuilder(database):
conn = database.parent.connection

v = OrderedDict()
sql = """
SELECT TABLE_NAME, VIEW_DEFINITION
FROM information_schema.views
WHERE TABLE_SCHEMA = '%s'
"""
views = conn.execute(sql % database.name)

if not views:
return v

for view_info in views:
view_name = view_info['TABLE_NAME']

vv = ViewSchema(name=view_name,parent=database)
vv.definition = view_info['VIEW_DEFINITION']

v[view_name] = vv

return v

class ViewSchema(object):
def __init__(self,name,parent):
self.parent = parent
self.name = name
self.definition = None

def define(self):
return self.definition

def create(self):
return "CREATE VIEW `%s` AS %s;" % (self.name, self.definition)

def modify(self):
return "ALTER VIEW `%s` AS %s;" % (self.name, self.definition)

def drop(self):
return "DROP VIEW `%s`;" % self.name

def __eq__(self,other):
if not isinstance(other, ViewSchema):
return False

return ((self.name == other.name)
and (self.definition == other.definition))

def __ne__(self,other):
return not self.__eq__(other)

0 comments on commit 81d4f12

Please sign in to comment.