resolve calls to db relations

This commit is contained in:
Erik Krogh Kristensen
2021-10-13 17:03:24 +02:00
parent 1a1770fc06
commit 31394878a2
3 changed files with 82 additions and 4 deletions

View File

@@ -232,6 +232,45 @@ class Predicate extends TPredicate, AstNode, Declaration {
override string getAPrimaryQlClass() { result = "Predicate" }
}
/**
* A relation in the database.
*/
class Relation extends TDBRelation, AstNode, Declaration {
Generated::DbTable table;
Relation() { this = TDBRelation(table) }
/**
* Gets the name of the relation.
*/
override string getName() { result = table.getTableName().getChild().getValue() }
private Generated::DbColumn getColumn(int i) {
result =
rank[i + 1](Generated::DbColumn column, int child |
table.getChild(child) = column
|
column order by child
)
}
/** Gets the `i`th parameter name */
string getParameterName(int i) { result = getColumn(i).getColName().getValue() }
/** Gets the `i`th parameter type */
string getParameterType(int i) {
// TODO: This is just using the name of the type, not the actual type. Checkout Type.qll
result = getColumn(i).getColType().getChild().(Generated::Token).getValue()
}
/**
* Gets the number of parameters.
*/
int getArity() { result = count(getColumn(_)) }
override string getAPrimaryQlClass() { result = "Relation" }
}
/**
* An expression that refers to a predicate, e.g. `BasicBlock::succ/2`.
*/
@@ -2154,9 +2193,6 @@ module YAML {
/** Gets the version of this qlpack */
string getVersion() { result = getProperty("version") }
/** Gets the database scheme of this qlpack */
string getDbScheme() { result = getProperty("dbscheme") }
/** Gets the extractor of this qlpack */
string getExtractor() { result = getProperty("extractor") }
@@ -2190,6 +2226,19 @@ module YAML {
)
}
/** Gets the database scheme of this qlpack */
File getDBScheme() {
result.getBaseName() = getProperty("dbscheme") and
result = file.getParentContainer().getFile(any(string s | s.matches("%.dbscheme")))
}
pragma[noinline]
Container getAFileInPack() {
result.getParentContainer() = file.getParentContainer()
or
result = getAFileInPack().(Folder).getAChildContainer()
}
/**
* Gets a QLPack that this QLPack depends on.
*/

View File

@@ -10,6 +10,7 @@ newtype TAstNode =
TClass(Generated::Dataclass dc) or
TCharPred(Generated::Charpred pred) or
TClassPredicate(Generated::MemberPredicate pred) or
TDBRelation(Generated::DbTable table) or
TSelect(Generated::Select sel) or
TModule(Generated::Module mod) or
TNewType(Generated::Datatype dt) or
@@ -153,6 +154,8 @@ Generated::AstNode toGenerated(AST::AstNode n) {
or
n = TClassPredicate(result)
or
n = TDBRelation(result)
or
n = TSelect(result)
or
n = TModule(result)
@@ -184,7 +187,7 @@ Generated::AstNode toGenerated(AST::AstNode n) {
n = TSuper(result)
}
class TPredicate = TCharPred or TClasslessPredicate or TClassPredicate;
class TPredicate = TCharPred or TClasslessPredicate or TClassPredicate or TDBRelation;
class TModuleMember = TModuleDeclaration or TImport or TSelect or TQLDoc;

View File

@@ -88,11 +88,37 @@ private module Cached {
)
}
pragma[noinline]
private predicate candidate(Relation rel, PredicateCall pc) {
rel.getName() = pc.getPredicateName()
}
private predicate resolveDBRelation(PredicateCall pc, DefinedPredicate p) {
exists(Relation rel | p = TPred(rel) |
candidate(rel, pc) and
rel.getArity() = pc.getNumberOfArguments() and
(
exists(YAML::QLPack libPack, YAML::QLPack qlPack |
rel.getLocation().getFile() = libPack.getDBScheme() and
qlPack.getADependency*() = libPack and
qlPack.getAFileInPack() = pc.getLocation().getFile()
)
or
// upgrade scripts don't have a qlpack
rel.getLocation().getFile().getParentContainer() =
pc.getLocation().getFile().getParentContainer()
)
)
}
cached
predicate resolveCall(Call c, PredicateOrBuiltin p) {
resolvePredicateCall(c, p)
or
resolveMemberCall(c, p)
or
not resolvePredicateCall(c, _) and
resolveDBRelation(c, p)
}
cached