def build_inner_query(request, tags): """Build an "inner query" -- a query which yields a list of stream ids (indexes in the stream table). These match the identifiers used in the reading db, or can be used as part of a join. The query performs auth checks and will check for the tags specified. """ # the inner query builds a list of streams matching all the # clauses which we can then select from clauses = [] uuid_clause = "true" for (k, v) in tags: if k == 'uuid': if v != None: uuid_clause = "s.uuid = %s" % escape_string(v) continue if v != None: clauses.append("hstore(%s, %s)" % (escape_string(k), escape_string(v))) else: break if len(clauses) == 0: clauses = ["hstore(array[]::varchar[])"] inner_query = """ (SELECT s.id FROM stream s, subscription sub WHERE s.subscription_id = sub.id AND (%s) AND (%s) AND s.metadata @> (%s)) """ % (build_authcheck(request), uuid_clause, ' || '.join(clauses)) return inner_query, clauses
def build_query(db, request, tags): """Will wrap a query which an appropriate selector to yield distinct tagnames, tagvals, or uuids depending on what is needed. """ inner_query, clauses = build_inner_query(request, tags) if len(tags) and tags[-1][0] == 'uuid': # if we select uuid as the trailing tag we have to be special query = """ SELECT DISTINCT s.uuid FROM stream AS s WHERE s.id IN """ + inner_query elif len(tags) and (tags[-1][1] == None or tags[-1][1] == ''): # odd-numbered clasues, so we print matching values of tags t = escape_string(tags[-1][0]) query = """ SELECT DISTINCT metadata -> %s AS svals FROM stream WHERE id IN %s AND metadata ? %s ORDER BY svals ASC""" % (t, inner_query, t) else: # otherwise we print all tags matching the restriction query = """ SELECT DISTINCT skeys FROM ( SELECT skeys(metadata) FROM stream WHERE id IN %s ) AS skeys ORDER BY skeys ASC""" % inner_query log.msg(query) d = db.runQuery(query) d.addCallback(log_time, time.time()) return d
def build_authcheck(request, ti='', forceprivate=False): """Build an SQL WHERE clause which enforces access restrictions. Will pull any credentials out of the request object passed in. """ if not 'private' in request.args and not forceprivate: query = "(sub%s.public " % ti else: query = "(false " if 'key' in request.args: query += 'OR ' + ' OR '.join(["sub.key = %s" % escape_string(x + ti) for x in request.args['key']]) query += ")" return query