aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2021-07-26 22:12:29 -0400
committerGravatar - 2021-07-26 22:56:50 -0400
commit9fda89f559c217d825ce1c94c5942529fa314d9d (patch)
treeaf1be9f767b737e75180f58b3c2da253f0336a4c
parentnatargs: add missing import (diff)
add command line option for search
As of right now NOT queries do not work correctly for cards with more than one tag.
-rw-r--r--queryparse.py31
-rwxr-xr-xunderwriter9
2 files changed, 28 insertions, 12 deletions
diff --git a/queryparse.py b/queryparse.py
index 544e9c4..7ebd0ab 100644
--- a/queryparse.py
+++ b/queryparse.py
@@ -53,15 +53,16 @@ class ParseTree:
self.l = l
def query_lit(alist, lit, isNot):
+ id = len(alist) + 1
if lit.op == LitType.TAGGLOB:
- qr = f"""tag in (SELECT id FROM tags
- WHERE name GLOB ?{len(alist)})"""
+ qr = f"""tag in (SELECT DISTINCT id FROM tags
+ WHERE name GLOB ?{id})"""
elif lit.op == LitType.TITLEGLOB:
- qr = f"""card in (SELECT id FROM cards
- WHERE name GLOB ?{len(alist)})"""
+ qr = f"""card in (SELECT DISTINCT id FROM cards
+ WHERE name GLOB ?{id})"""
elif lit.op == LitType.TAG:
qr = f"""tag in (SELECT id FROM tags
- WHERE name = ?{len(alist)} LIMIT 1)"""
+ WHERE name = ?{id} LIMIT 1)"""
else:
raise ParseError
@@ -69,14 +70,14 @@ def query_lit(alist, lit, isNot):
if isNot:
qr = f"NOT ({qr})"
- return f"SELECT card FROM tagmap WHERE {qr}"
+ return f"SELECT DISTINCT card FROM tagmap WHERE {qr}"
# Returns bl,xpr where bl = True when xpr is for a literal
-def build(alist, pt):
+def build_r(alist, pt):
if pt.op == TokType.OR:
conn = "UNION"
elif pt.op == TokType.AND:
- conn = "INTERSECTION"
+ conn = "INTERSECT"
elif pt.op == TokType.NOT:
return True,query_lit(alist, pt.l[0], True)
elif pt.op in LitType:
@@ -84,16 +85,22 @@ def build(alist, pt):
else:
raise ParseError
- v, r = build(alist, pt.l[0])
+ v, r = build_r(alist, pt.l[0])
if not v:
- r = f"SELECT card FROM ({r})"
+ r = f"SELECT DISTINCT card FROM ({r})"
for i in pt.l[1:]:
- v,exr = build(alist, i)
+ v,exr = build_r(alist, i)
if not v:
- exr = f"SELECT card FROM f({exr})"
+ exr = f"SELECT DISTINCT card FROM f({exr})"
r = f"{r} {conn} {exr}"
return False,r
+def build(l):
+ lits = []
+ _,r = build_r(lits, parse(l))
+ return tuple(lits), f"""SELECT DISTINCT name FROM ({r})
+ AS tbl INNER JOIN cards ON tbl.card = cards.id"""
+
def encapsulate(pt, op):
if pt.op != op:
pt = ParseTree(op, [pt])
diff --git a/underwriter b/underwriter
index f54b1fd..63404a8 100755
--- a/underwriter
+++ b/underwriter
@@ -6,6 +6,7 @@ import sys
from datetime import datetime, timezone
import base64
from natargs import Arguments
+import queryparse
def current_time():
return int(datetime.now(timezone.utc).timestamp())
@@ -118,6 +119,13 @@ class Context:
self.db.execute("SELECT name FROM tags").fetchall():
print(i)
+ def query(self, l):
+ lits,exec = queryparse.build(l)
+ print(exec)
+ print(lits)
+ for (i,) in self.db.execute(exec, lits).fetchall():
+ print(i)
+
def __init__(self, name):
if not os.path.isfile(name):
self.db = Context.initdb(name)
@@ -152,5 +160,6 @@ if __name__ == "__main__":
argparse.addarg(["untag"], lambda x:x > 1, ctx.card_remove_tags)
argparse.addarg(["list", "tags"], lambda x: x == 0, ctx.list_tags)
argparse.addarg(["list", "cards"], lambda x: x == 0, ctx.list_cards)
+ argparse.addarg(["search"], lambda x: x > 0, ctx.query)
argparse.execarg(args)