| 392 | pass |
| 393 | |
| 394 | class Database(object): |
| 395 | |
| 396 | class Tables(dict): |
| 397 | # Table objects are lazily constructed when retrieved. |
| 398 | # This saves time because each table executes a metadata query when constructed. |
| 399 | def __init__(self, db, *args, **kwargs): |
| 400 | dict.__init__(self, *args, **kwargs); self.db=db |
| 401 | def __getitem__(self, k): |
| 402 | if dict.__getitem__(self, k) is None: |
| 403 | dict.__setitem__(self, k, Table(name=k, database=self.db)) |
| 404 | return dict.__getitem__(self, k) |
| 405 | |
| 406 | def __init__(self, name, host="localhost", port=3306, username="root", password="", type=SQLITE, unicode=True, **kwargs): |
| 407 | """ A collection of tables stored in an SQLite or MySQL database. |
| 408 | If the database does not exist, creates it. |
| 409 | If the host, user or password is wrong, raises DatabaseConnectionError. |
| 410 | """ |
| 411 | _import_db(type) |
| 412 | self.type = type |
| 413 | self.name = name |
| 414 | self.host = host |
| 415 | self.port = port |
| 416 | self.username = kwargs.get("user", username) |
| 417 | self.password = password |
| 418 | self._connection = None |
| 419 | self.connect(unicode) |
| 420 | # Table names are available in the Database.tables dictionary, |
| 421 | # table objects as attributes (e.g. Database.table_name). |
| 422 | q = self.type==SQLITE and "select name from sqlite_master where type='table';" or "show tables;" |
| 423 | self.tables = Database.Tables(self) |
| 424 | for name, in self.execute(q): |
| 425 | if not name.startswith(("sqlite_",)): |
| 426 | self.tables[name] = None |
| 427 | # The SQL syntax of the last query is kept in cache. |
| 428 | self._query = None |
| 429 | # Persistent relations between tables, stored as (table1, table2, key1, key2, join) tuples. |
| 430 | self.relations = [] |
| 431 | |
| 432 | def connect(self, unicode=True): |
| 433 | # Connections for threaded applications work differently, |
| 434 | # see http://tools.cherrypy.org/wiki/Databases |
| 435 | # (have one Database object for each thread). |
| 436 | if self._connection is not None: |
| 437 | return |
| 438 | # MySQL |
| 439 | if self.type == MYSQL: |
| 440 | try: |
| 441 | self._connection = MySQLdb.connect(self.host, self.username, self.password, self.name, port=self.port, use_unicode=unicode) |
| 442 | self._connection.autocommit(False) |
| 443 | except Exception, e: |
| 444 | # Create the database if it doesn't exist yet. |
| 445 | if "unknown database" not in str(e).lower(): |
| 446 | raise DatabaseConnectionError, e[1] # Wrong host, username and/or password. |
| 447 | connection = MySQLdb.connect(self.host, self.username, self.password) |
| 448 | cursor = connection.cursor() |
| 449 | cursor.execute("create database if not exists `%s`;" % self.name) |
| 450 | cursor.close() |
| 451 | connection.close() |
no outgoing calls
no test coverage detected
searching dependent graphs…