1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # mojo, a Python library for implementing document based databases
5 # Copyright (C) 2013-2014 by Javier Sancho Fernandez <jsf at jsancho dot org>
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
33 class Query(dbutils.Query):
36 res += ",".join(["(%s)" % f.sql() for f in self.fields])
39 res += ",".join([t.sql() for t in self.tables])
43 res += " AND ".join(["(%s)" % c.sql() for c in self.constraints])
48 class Field(dbutils.Field):
50 return "%s.`%s`" % (self.table.sql(), self.field_name)
53 class Table(dbutils.Table):
55 return "`%s`.`%s`" % (self.db_name, self.table_name)
58 class Constraint(dbutils.Constraint):
60 operator = self.operator.strip().lower()
61 if operator == "starts":
62 return "(%s) LIKE (%s)" % (self.args[0].sql(), self.args[1].sql()[:-1] + "%'")
63 elif operator == "in":
64 return "(%s) IN (%s)" % (self.args[0].sql(), ",".join(["(%s)" % a.sql() for a in self.args[1:]]))
66 return "(%s) = (%s)" % (self.args[0].sql(), self.args[1].sql())
68 token = " %s " % operator.upper()
69 return token.join(["(%s)" % a.sql() for a in self.args])
72 class Literal(dbutils.Literal):
74 if type(self.value) in (int, float):
75 return "%s" % self.value
77 return "'%s'" % str(self.value).replace("'", "''")
80 class Connection(connection.Connection):
84 Constraint = Constraint
87 def __init__(self, host="localhost", user="", passwd="", *args, **kwargs):
88 self._db_con = MySQLdb.connect(host=host, user=user, passwd=passwd)
89 self._db_con_autocommit = MySQLdb.connect(host=host, user=user, passwd=passwd)
90 super(Connection, self).__init__(*args, **kwargs)
92 def query(self, sql, db=None):
102 def execute(self, sql, db=None):
106 res = cur.execute(sql)
111 def _get_databases(self):
112 return [x[0] for x in self.query("SHOW DATABASES")]
114 def _get_tables(self, db_name):
115 return [x[0] for x in self.query("SHOW TABLES FROM `%s`" % db_name)]
117 def _count_rows(self, db_name, table_name):
118 return self.query("SELECT COUNT(*) FROM `%s`.`%s`" % (db_name, table_name))[0][0]
120 def _create_database(self, db_name):
121 return (self.execute("CREATE DATABASE `%s`" % db_name, db=self._db_con_autocommit) or False) and True
123 def _get_sql_field_type(self, field_type):
124 return SQL_FIELD_TYPES.get(field_type, "UNKNOW")
126 def _create_table(self, db_name, table_name, fields):
128 sql = "CREATE TABLE `%s`.`%s` (" % (db_name, table_name)
132 sql_field = "%s %s" % (f['name'], self._get_sql_field_type(f['type']))
134 sql_field += "(%s)" % f['size']
136 primary.append(f['name'])
137 if 'null' in f and not f['null']:
138 sql_field += " NOT NULL"
139 sql_fields.append(sql_field)
140 sql += ",".join(sql_fields)
143 sql += ", PRIMARY KEY(%s)" % ",".join(primary)
147 return (self.execute(sql, db=self._db_con_autocommit) or False) and True
149 def _get_cursor(self, query):
150 cur = self._db_con.cursor()
151 cur.execute(query.sql())
154 def _next(self, cur):
155 return cur.fetchone()
157 def _insert(self, db_name, table_name, values):
160 for k, v in values.iteritems():
163 vals.append("'%s'" % v.replace("'", "''"))
166 sql = "INSERT INTO `%s`.`%s`(%s) VALUES (%s)" % (db_name, table_name, ",".join(keys), ",".join(vals))
167 return self.execute(sql)
170 self._db_con.commit()
173 self._db_con.rollback()