Browse Source

Finish Database.search() (closes #19)

tags/v1.0^2
Ben Kurtovic 10 years ago
parent
commit
860260d0ad
3 changed files with 45 additions and 15 deletions
  1. +39
    -10
      bitshift/database/__init__.py
  2. +1
    -1
      bitshift/query/__init__.py
  3. +5
    -4
      bitshift/query/nodes.py

+ 39
- 10
bitshift/database/__init__.py View File

@@ -9,6 +9,7 @@ import mmh3
import oursql

from .migration import VERSION, MIGRATIONS
from ..codelet import Codelet
from ..query.nodes import (String, Regex, Text, Language, Author, Date, Symbol,
BinaryOp, UnaryOp)

@@ -65,7 +66,35 @@ class Database(object):
num_results = 0 # TODO: NotImplemented
return ids, num_results

def _get_codelets_from_ids(self, ids):
def _get_authors_for_codelet(self, cursor, codelet_id):
"""Return a list of authors for a given codelet."""
query = """SELECT author_name, author_url
FROM authors
WHERE author_codelet = ?"""

cursor.execute(query, (codelet_id,))
return cursor.fetchall()

def _get_symbols_for_code(self, cursor, code_id):
"""Return a list of symbols for a given codelet."""
query = """SELECT symbol_type, symbol_name, sloc_type, sloc_row,
sloc_col, sloc_end_row, sloc_end_col
FROM symbols
INNER JOIN symbol_locations ON sloc_symbol = symbol_id
WHERE symbol_code = ?"""

symbols = {type_: {} for type_ in Symbol.TYPES_INV}
cursor.execute(query, (code_id,))
for type_, name, loc_type, row, col, erow, ecol in cursor.fetchall():
sdict = symbols[Symbol.TYPES_INV[type_]]
if name not in sdict:
sdict[name] = ((), ())
sdict[name][loc_type].append((row, col, erow, ecol))
for type_, sdict in symbols.items():
symbols[type_] = [(n, d, u) for n, (d, u) in sdict.iteritems()]
return symbols

def _get_codelets_from_ids(self, cursor, ids):
"""Return a list of Codelet objects given a list of codelet IDs."""
query = """SELECT *
FROM codelets
@@ -73,17 +102,18 @@ class Database(object):
INNER JOIN origins ON codelet_origin = origin_id
WHERE codelet_id = ?"""

with self._conn.cursor(oursql.DictCursor) as cursor:
cursor.executemany(query, [(id,) for id in ids])
for row in cursor.fetchone():
with self._conn.cursor(oursql.DictCursor) as dict_cursor:
dict_cursor.executemany(query, [(id,) for id in ids])
for row in dict_cursor.fetchone():
codelet_id = row["codelet_id"]
if row["origin_url_base"]:
url = row["codelet_url"]
else:
url = row["origin_url_base"] + row["codelet_url"]
origin = (row["origin_name"], row["origin_url"],
row["origin_image"])
authors = NotImplemented # TODO: list of 3-tuples (author_name, author_url or None)
symbols = NotImplemented # TODO: dict of {sym_type: (name, decls, uses)}
authors = self._get_authors_for_codelet(cursor, codelet_id)
symbols = self._get_symbols_for_code(cursor, row["code_id"])
yield Codelet(
row["codelet_name"], row["code_code"], None,
row["code_lang"], authors, url,
@@ -103,13 +133,12 @@ class Database(object):

def _insert_symbols(self, cursor, code_id, sym_type, symbols):
"""Insert a list of symbols of a given type into the database."""
sym_types = ["functions", "classes", "variables"]
query1 = "INSERT INTO symbols VALUES (DEFAULT, ?, ?, ?)"
query2 = """INSERT INTO symbol_locations VALUES
(DEFAULT, ?, ?, ?, ?, ?, ?)"""

for (name, decls, uses) in symbols:
cursor.execute(query1, (code_id, sym_types.index(sym_type), name))
cursor.execute(query1, (code_id, Symbol.TYPES_INV[sym_type], name))
sym_id = cursor.lastrowid
params = ([tuple([sym_id, 0] + list(loc)) for loc in decls] +
[tuple([sym_id, 1] + list(loc)) for loc in uses])
@@ -153,8 +182,8 @@ class Database(object):
num_mnt = num_results / (10 ** num_exp)
cursor.execute(query2, (cache_id, num_mnt, num_exp))
cursor.executemany(query3, [(cache_id, c_id) for c_id in ids])
codelet_gen = self._get_codelets_from_ids(ids)
return (num_results, list(codelet_gen))
codelet_gen = self._get_codelets_from_ids(cursor, ids)
return (num_results, list(codelet_gen))

def insert(self, codelet):
"""


+ 1
- 1
bitshift/query/__init__.py View File

@@ -231,7 +231,7 @@ class _QueryParser(object):
index = nest.index(UnaryOp.NOT)
if index == len(nest) - 1:
err = "Invalid query: '%s' given without argument."
raise QueryParseException(err % UnaryOp.OPS[op])
raise QueryParseException(err % UnaryOp.OPS[UnaryOp.NOT])
right = UnaryOp(UnaryOp.NOT, self._parse_nest(nest[index + 1:]))
if index > 0:
left = self._parse_nest(nest[:index])


+ 5
- 4
bitshift/query/nodes.py View File

@@ -190,11 +190,12 @@ class Symbol(_Node):

Searches in symbol_type and symbol_name.
"""
ALL = 0
FUNCTION = 1
CLASS = 2
VARIABLE = 3
ALL = -1
FUNCTION = 0
CLASS = 1
VARIABLE = 2
TYPES = {FUNCTION: "FUNCTION", CLASS: "CLASS", VARIABLE: "VARIABLE"}
TYPES_INV = ["functions", "classes", "variables"]

def __init__(self, type_, name):
"""


Loading…
Cancel
Save