# $SnapHashLicense:
#
# SnapLogic - Open source data services
#
# Copyright (C) 2009, SnapLogic, Inc. All rights reserved.
#
# See http://www.snaplogic.org for more information about
# the SnapLogic project.
#
# This program is free software, distributed under the terms of
# the GNU General Public License Version 2. See the LEGAL file
# at the top of the source tree.
#
# "SnapLogic" is a trademark of SnapLogic, Inc.
#
#
# $
# $Id: mysql.py 6157 2009-01-29 14:04:26Z kurt $
"""
MySQL store module.
This module contains the MySQL store object providing interfaces for MySQL specific operations.
"""
__docformat__ = "epytext en"
# Imports
import sys
import MySQLdb
from snaplogic.server.repository.snap_sql_store import SnapSQLStore
from snaplogic.server.repository import reg_keys
from snaplogic.common.snap_exceptions import *
from snaplogic.common.db_utils import SQLQueryBuilder
# Public names
__all__ = [ "MySQL" ]
class MySQL(SnapSQLStore):
"""
MySQL store class. This class derives from SnapStore class and implemets MySQL specific operations
for the inherited interfaces.
"""
# XXX 767 seems to be the max blob key size in some MySQL versions.
CREATE_TABLE_RESOURCE = """
CREATE TABLE resource (uri blob(1000) NOT NULL,
guid char(32) NOT NULL,
gen_id int NOT NULL,
object longtext NOT NULL,
validated int NOT NULL,
PRIMARY KEY(uri(767)))
"""
CREATE_TABLE_SCHEDULER_EVENT = """
CREATE TABLE scheduler_event (uri blob(767) NOT NULL,
event text NOT NULL,
PRIMARY KEY(uri(767)))
"""
CREATE_TABLE_REGISTRY = """CREATE TABLE registry (name varchar(255) PRIMARY KEY NOT NULL, value text)"""
INSERT_OR_UPDATE_REGISTRY_ENTRY = SQLQueryBuilder("""
INSERT INTO registry
VALUES (${name}, ${value})
ON DUPLICATE KEY UPDATE value = ${value}
""")
def __init__(self):
"""
Initialization.
"""
super(MySQL, self).__init__(MySQLdb)
self._conn_params = {}
@classmethod
def create(cls, host, port, db_name, user, passwd):
"""
Create a MySQL repository store in the given database.
The database is expected to already exist. This method will only create and initialize tables
and indexes.
@param host: Hostname of the MySQL server.
@type host: string
@param port: Port of the MySQL server. None for default.
@type port: int
@param db_name: Name of database to use.
@type db_name: string
@param user: Username to connect to MySQL server as.
@type user: string
@param passwd: Password of user to connect to MySQL server as.
@type passwd: string
@raise SnapRepInitError: Error connecting to MySQL database or creating repository store.
"""
if port is None:
port = 3306
try:
db = MySQLdb.connect(user=user, passwd=passwd, db=db_name, port=port, host=host)
except Exception, e:
raise SnapException.chain(e, SnapRepInitError("Cannot connect to MySQL database:",
str(e),
('host', host),
('port', port),
('db_name', db_name),
('user', user),
('passwd', '*' * len(passwd))))
try:
cls._createTables(db, MySQLdb)
except MySQLdb.Error, e:
raise SnapException.chain(e, SnapRepInitError("Error creating MySQL repository:",
str(e),
('host', host),
('port', port),
('db_name', db_name),
('user', user),
('passwd', '*' * len(passwd))))
finally:
if db:
db.close()
@classmethod
def destroy(cls, host, port, db_name, user, passwd):
"""
Destroy the repository store contained in the database.
Only the tables and indexes related to the store are destroyed. The database will remain.
@param host: Hostname of the MySQL server.
@type host: string
@param port: Port of the MySQL server. None for default.
@type port: int
@param db_name: Name of database to use.
@type db_name: string
@param user: Username to connect to MySQL server as.
@type user: string
@param passwd: Password of user to connect to MySQL server as.
@type passwd: string
@raise SnapRepInitError: Error connecting to MySQL database or destroying store.
"""
if port is None:
port = 3306
db = None
try:
db = MySQLdb.connect(user=user, passwd=passwd, db=db_name, port=port, host=host)
cls._destroy(db, MySQLdb)
except Exception, e:
raise SnapException.chain(e, SnapRepInitError("Cannot connect to MySQL database:",
str(e),
('host', host),
('port', port),
('db_name', db_name),
('user', user),
('passwd', '*' * len(passwd))))
finally:
if db:
db.close()
def connect(self, host, port, db_name, user, passwd):
"""
Connect to the MySQL database.
@param host: Hostname of the MySQL server.
@type host: string
@param port: Port of the MySQL server. None for default.
@type port: int
@param db_name: Name of database to use.
@type db_name: string
@param user: Username to connect to MySQL server as.
@type user: string
@param passwd: Password of user to connect to MySQL server as.
@type passwd: string
@raise SnapRepInitError: Error connecting to MySQL database.
"""
if self._db is not None:
raise SnapRepError("Repository is already connected")
if port is None:
port = 3306
try:
self._db = MySQLdb.connect(user=user, passwd=passwd, db=db_name, port=port, host=host)
except Exception, e:
raise SnapException.chain(e, SnapRepInitError("Cannot connect to MySQL database:",
str(e),
('host', host),
('port', port),
('db_name', db_name),
('user', user),
('passwd', '*' * len(passwd))))
self._conn_params = {'user': user, 'passwd': passwd, 'db_name': db_name, 'port': port, 'host': host}
def _upgrade_store_2_to_3(self, handle):
handle.execute('ALTER TABLE resource MODIFY object longtext NOT NULL')
handle.commit()
def clone(self):
instance = MySQL()
instance.connect(**self._conn_params)
return instance
|