mirror of
https://github.com/github/codeql.git
synced 2026-02-11 12:41:06 +01:00
resolve calls to db relations
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user