|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- """
- Subpackage with classes and functions to handle communication with the MySQL
- database backend, which manages the search index.
- """
-
- import os
-
- import mmh3
- import oursql
-
- from .migration import VERSION, MIGRATIONS
-
- __all__ = ["Database"]
-
- class Database(object):
- """Represents the MySQL database."""
-
- def __init__(self, migrate=False):
- self._connect()
- self._check_version(migrate)
-
- def _connect(self):
- """Establish a connection to the database."""
- root = os.path.dirname(os.path.abspath(__file__))
- default_file = os.path.join(root, ".my.cnf")
- self._conn = oursql.connect(read_default_file=default_file,
- autoping=True, autoreconnect=True)
-
- def _migrate(self, cursor, current):
- """Migrate the database to the latest schema version."""
- for version in xrange(current, VERSION):
- for query in MIGRATIONS[version - 1]:
- cursor.execute(query)
-
- def _check_version(self, migrate):
- """Check the database schema version and respond accordingly.
-
- If the schema is out of date, migrate if *migrate* is True, else raise
- an exception.
- """
- with self._conn.cursor() as cursor:
- cursor.execute("SELECT version FROM version")
- version = cursor.fetchone()[0]
- if version < VERSION:
- if migrate:
- self._migrate(cursor, version)
- else:
- err = "Database schema out of date. " \
- "Run `python -m bitshift.database.migration`."
- raise RuntimeError(err)
-
- def close(self):
- """Disconnect from the database."""
- self._conn.close()
-
- def search(self, query, page=1):
- """
- Search the database for a query and return the *n*\ th page of results.
-
- :param query: The query to search for.
- :type query: :py:class:`~.query.tree.Tree`
- :param page: The result page to display.
- :type page: int
-
- :return: A list of search results.
- :rtype: list of :py:class:`.Codelet`\ s
- """
- # search for cache_hash = mmh3.hash(query.serialize() + str(page))
- # cache HIT:
- # update cache_last_used
- # return codelets
- # cache MISS:
- # build complex search query
- # fetch codelets
- # cache results
- # return codelets
- pass
-
- def insert(self, codelet):
- """
- Insert a codelet into the database.
-
- :param codelet: The codelet to insert.
- :type codelet: :py:class:`.Codelet`
- """
- query1 = """INSERT INTO code VALUES (?, ?)
- ON DUPLICATE KEY UPDATE code_id=code_id"""
- query2 = "INSERT INTO codelets VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
- query3 = "INSERT INTO authors VALUES", " (?, ?, ?)"
- query4 = "INSERT INTO symbols VALUES", " (?, ?, ?, ?, ?)"
-
- # LAST_INSERT_ID()
-
- # codelet_id -- auto_increment used here
- codelet_name
- codelet_code_id
- codelet_lang
- codelet_origin
- codelet_url
- codelet_rank
- codelet_date_created
- codelet_date_modified
-
- # codelet fields
- codelet.name
- codelet.code
- codelet.filename
- codelet.language
- codelet.authors
- codelet.code_url
- codelet.date_created
- codelet.date_modified
-
- #######################################################################
-
- code_id = mmh3.hash64(codelet.code.encode("utf8"))[0]
-
- with self._conn.cursor() as cursor:
- cursor.execute(query1, (code_id, codelet.code))
|