A semantic search engine for source code https://bitshift.benkurtovic.com/
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

120 Zeilen
3.7 KiB

  1. """
  2. Subpackage with classes and functions to handle communication with the MySQL
  3. database backend, which manages the search index.
  4. """
  5. import os
  6. import mmh3
  7. import oursql
  8. from .migration import VERSION, MIGRATIONS
  9. __all__ = ["Database"]
  10. class Database(object):
  11. """Represents the MySQL database."""
  12. def __init__(self, migrate=False):
  13. self._connect()
  14. self._check_version(migrate)
  15. def _connect(self):
  16. """Establish a connection to the database."""
  17. root = os.path.dirname(os.path.abspath(__file__))
  18. default_file = os.path.join(root, ".my.cnf")
  19. self._conn = oursql.connect(read_default_file=default_file,
  20. autoping=True, autoreconnect=True)
  21. def _migrate(self, cursor, current):
  22. """Migrate the database to the latest schema version."""
  23. for version in xrange(current, VERSION):
  24. for query in MIGRATIONS[version - 1]:
  25. cursor.execute(query)
  26. def _check_version(self, migrate):
  27. """Check the database schema version and respond accordingly.
  28. If the schema is out of date, migrate if *migrate* is True, else raise
  29. an exception.
  30. """
  31. with self._conn.cursor() as cursor:
  32. cursor.execute("SELECT version FROM version")
  33. version = cursor.fetchone()[0]
  34. if version < VERSION:
  35. if migrate:
  36. self._migrate(cursor, version)
  37. else:
  38. err = "Database schema out of date. " \
  39. "Run `python -m bitshift.database.migration`."
  40. raise RuntimeError(err)
  41. def close(self):
  42. """Disconnect from the database."""
  43. self._conn.close()
  44. def search(self, query, page=1):
  45. """
  46. Search the database for a query and return the *n*\ th page of results.
  47. :param query: The query to search for.
  48. :type query: :py:class:`~.query.tree.Tree`
  49. :param page: The result page to display.
  50. :type page: int
  51. :return: A list of search results.
  52. :rtype: list of :py:class:`.Codelet`\ s
  53. """
  54. # search for cache_hash = mmh3.hash(query.serialize() + str(page))
  55. # cache HIT:
  56. # update cache_last_used
  57. # return codelets
  58. # cache MISS:
  59. # build complex search query
  60. # fetch codelets
  61. # cache results
  62. # return codelets
  63. pass
  64. def insert(self, codelet):
  65. """
  66. Insert a codelet into the database.
  67. :param codelet: The codelet to insert.
  68. :type codelet: :py:class:`.Codelet`
  69. """
  70. query1 = """INSERT INTO code VALUES (?, ?)
  71. ON DUPLICATE KEY UPDATE code_id=code_id"""
  72. query2 = "INSERT INTO codelets VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
  73. query3 = "INSERT INTO authors VALUES", " (?, ?, ?)"
  74. query4 = "INSERT INTO symbols VALUES", " (?, ?, ?, ?, ?)"
  75. # LAST_INSERT_ID()
  76. # codelet_id -- auto_increment used here
  77. codelet_name
  78. codelet_code_id
  79. codelet_lang
  80. codelet_origin
  81. codelet_url
  82. codelet_rank
  83. codelet_date_created
  84. codelet_date_modified
  85. # codelet fields
  86. codelet.name
  87. codelet.code
  88. codelet.filename
  89. codelet.language
  90. codelet.authors
  91. codelet.code_url
  92. codelet.date_created
  93. codelet.date_modified
  94. #######################################################################
  95. code_id = mmh3.hash64(codelet.code.encode("utf8"))[0]
  96. with self._conn.cursor() as cursor:
  97. cursor.execute(query1, (code_id, codelet.code))