@@ -232,6 +232,45 @@ class Predicate extends TPredicate, AstNode, Declaration {
232232 override string getAPrimaryQlClass ( ) { result = "Predicate" }
233233}
234234
235+ /**
236+ * A relation in the database.
237+ */
238+ class Relation extends TDBRelation , AstNode , Declaration {
239+ Generated:: DbTable table ;
240+
241+ Relation ( ) { this = TDBRelation ( table ) }
242+
243+ /**
244+ * Gets the name of the relation.
245+ */
246+ override string getName ( ) { result = table .getTableName ( ) .getChild ( ) .getValue ( ) }
247+
248+ private Generated:: DbColumn getColumn ( int i ) {
249+ result =
250+ rank [ i + 1 ] ( Generated:: DbColumn column , int child |
251+ table .getChild ( child ) = column
252+ |
253+ column order by child
254+ )
255+ }
256+
257+ /** Gets the `i`th parameter name */
258+ string getParameterName ( int i ) { result = getColumn ( i ) .getColName ( ) .getValue ( ) }
259+
260+ /** Gets the `i`th parameter type */
261+ string getParameterType ( int i ) {
262+ // TODO: This is just using the name of the type, not the actual type. Checkout Type.qll
263+ result = getColumn ( i ) .getColType ( ) .getChild ( ) .( Generated:: Token ) .getValue ( )
264+ }
265+
266+ /**
267+ * Gets the number of parameters.
268+ */
269+ int getArity ( ) { result = count ( getColumn ( _) ) }
270+
271+ override string getAPrimaryQlClass ( ) { result = "Relation" }
272+ }
273+
235274/**
236275 * An expression that refers to a predicate, e.g. `BasicBlock::succ/2`.
237276 */
@@ -2030,3 +2069,204 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
20302069 pred = directMember ( "getQualifier" ) and result = this .getQualifier ( )
20312070 }
20322071}
2072+
2073+ /**
2074+ * Classes modelling YAML AST nodes.
2075+ */
2076+ module YAML {
2077+ /** A node in a YAML file */
2078+ class YAMLNode extends TYAMLNode , AstNode {
2079+ /** Holds if the predicate is a root node (has no parent) */
2080+ predicate isRoot ( ) { not exists ( getParent ( ) ) }
2081+ }
2082+
2083+ /** A YAML comment. */
2084+ class YAMLComment extends TYamlCommemt , YAMLNode {
2085+ Generated:: YamlComment yamlcomment ;
2086+
2087+ YAMLComment ( ) { this = TYamlCommemt ( yamlcomment ) }
2088+
2089+ override string getAPrimaryQlClass ( ) { result = "YAMLComment" }
2090+ }
2091+
2092+ /** A YAML entry. */
2093+ class YAMLEntry extends TYamlEntry , YAMLNode {
2094+ Generated:: YamlEntry yamle ;
2095+
2096+ YAMLEntry ( ) { this = TYamlEntry ( yamle ) }
2097+
2098+ /** Gets the key of this YAML entry. */
2099+ YAMLKey getKey ( ) {
2100+ exists ( Generated:: YamlKeyvaluepair pair |
2101+ pair .getParent ( ) = yamle and
2102+ result = TYamlKey ( pair .getKey ( ) )
2103+ )
2104+ }
2105+
2106+ /** Gets the value of this YAML entry. */
2107+ YAMLValue getValue ( ) {
2108+ exists ( Generated:: YamlKeyvaluepair pair |
2109+ pair .getParent ( ) = yamle and
2110+ result = TYamlValue ( pair .getValue ( ) )
2111+ )
2112+ }
2113+
2114+ override string getAPrimaryQlClass ( ) { result = "YAMLEntry" }
2115+ }
2116+
2117+ /** A YAML key. */
2118+ class YAMLKey extends TYamlKey , YAMLNode {
2119+ Generated:: YamlKey yamlkey ;
2120+
2121+ YAMLKey ( ) { this = TYamlKey ( yamlkey ) }
2122+
2123+ /**
2124+ * Gets the value of this YAML key.
2125+ */
2126+ YAMLValue getValue ( ) {
2127+ exists ( Generated:: YamlKeyvaluepair pair |
2128+ pair .getKey ( ) = yamlkey and result = TYamlValue ( pair .getValue ( ) )
2129+ )
2130+ }
2131+
2132+ override string getAPrimaryQlClass ( ) { result = "YAMLKey" }
2133+
2134+ /** Gets the value of this YAML value. */
2135+ string getNamePart ( int i ) {
2136+ i = 0 and result = yamlkey .getChild ( 0 ) .( Generated:: SimpleId ) .getValue ( )
2137+ or
2138+ exists ( YAMLKey child |
2139+ child = TYamlKey ( yamlkey .getChild ( 1 ) ) and
2140+ result = child .getNamePart ( i - 1 )
2141+ )
2142+ }
2143+
2144+ /**
2145+ * Gets all the name parts of this YAML key concatenated with `/`.
2146+ * Dashes are replaced with `/` (because we don't have that information in the generated AST).
2147+ */
2148+ string getQualifiedName ( ) {
2149+ result = concat ( string part , int i | part = getNamePart ( i ) | part , "/" order by i )
2150+ }
2151+ }
2152+
2153+ /** A YAML list item. */
2154+ class YAMLListItem extends TYamlListitem , YAMLNode {
2155+ Generated:: YamlListitem yamllistitem ;
2156+
2157+ YAMLListItem ( ) { this = TYamlListitem ( yamllistitem ) }
2158+
2159+ /**
2160+ * Gets the value of this YAML list item.
2161+ */
2162+ YAMLValue getValue ( ) { result = TYamlValue ( yamllistitem .getChild ( ) ) }
2163+
2164+ override string getAPrimaryQlClass ( ) { result = "YAMLListItem" }
2165+ }
2166+
2167+ /** A YAML value. */
2168+ class YAMLValue extends TYamlValue , YAMLNode {
2169+ Generated:: YamlValue yamlvalue ;
2170+
2171+ YAMLValue ( ) { this = TYamlValue ( yamlvalue ) }
2172+
2173+ override string getAPrimaryQlClass ( ) { result = "YAMLValue" }
2174+
2175+ /** Gets the value of this YAML value. */
2176+ string getValue ( ) { result = yamlvalue .getValue ( ) }
2177+ }
2178+
2179+ // to not expose the entire `File` API on `QlPack`.
2180+ private newtype TQLPack = MKQlPack ( File file ) { file .getBaseName ( ) = "qlpack.yml" }
2181+
2182+ YAMLEntry test ( ) { not result .isRoot ( ) }
2183+
2184+ /**
2185+ * A `qlpack.yml` file.
2186+ */
2187+ class QLPack extends MKQlPack {
2188+ File file ;
2189+
2190+ QLPack ( ) { this = MKQlPack ( file ) }
2191+
2192+ private string getProperty ( string name ) {
2193+ exists ( YAMLEntry entry |
2194+ entry .isRoot ( ) and
2195+ entry .getKey ( ) .getQualifiedName ( ) = name and
2196+ result = entry .getValue ( ) .getValue ( ) .trim ( ) and
2197+ entry .getLocation ( ) .getFile ( ) = file
2198+ )
2199+ }
2200+
2201+ /** Gets the name of this qlpack */
2202+ string getName ( ) { result = getProperty ( "name" ) }
2203+
2204+ /** Gets the version of this qlpack */
2205+ string getVersion ( ) { result = getProperty ( "version" ) }
2206+
2207+ /** Gets the extractor of this qlpack */
2208+ string getExtractor ( ) { result = getProperty ( "extractor" ) }
2209+
2210+ string toString ( ) { result = getName ( ) }
2211+
2212+ /** Gets the file that this `QLPack` represents. */
2213+ File getFile ( ) { result = file }
2214+
2215+ private predicate isADependency ( YAMLEntry entry ) {
2216+ exists ( YAMLEntry deps |
2217+ deps .getLocation ( ) .getFile ( ) = file and entry .getLocation ( ) .getFile ( ) = file
2218+ |
2219+ deps .isRoot ( ) and
2220+ deps .getKey ( ) .getQualifiedName ( ) = "dependencies" and
2221+ entry .getLocation ( ) .getStartLine ( ) = 1 + deps .getLocation ( ) .getStartLine ( ) and
2222+ entry .getLocation ( ) .getStartColumn ( ) > deps .getLocation ( ) .getStartColumn ( )
2223+ )
2224+ or
2225+ exists ( YAMLEntry prev | isADependency ( prev ) |
2226+ prev .getLocation ( ) .getFile ( ) = file and
2227+ entry .getLocation ( ) .getFile ( ) = file and
2228+ entry .getLocation ( ) .getStartLine ( ) = 1 + prev .getLocation ( ) .getStartLine ( ) and
2229+ entry .getLocation ( ) .getStartColumn ( ) = prev .getLocation ( ) .getStartColumn ( )
2230+ )
2231+ }
2232+
2233+ predicate hasDependency ( string name , string version ) {
2234+ exists ( YAMLEntry entry | isADependency ( entry ) |
2235+ entry .getKey ( ) .getQualifiedName ( ) = name and
2236+ entry .getValue ( ) .getValue ( ) = version
2237+ )
2238+ }
2239+
2240+ /** Gets the database scheme of this qlpack */
2241+ File getDBScheme ( ) {
2242+ result .getBaseName ( ) = getProperty ( "dbscheme" ) and
2243+ result = file .getParentContainer ( ) .getFile ( any ( string s | s .matches ( "%.dbscheme" ) ) )
2244+ }
2245+
2246+ pragma [ noinline]
2247+ Container getAFileInPack ( ) {
2248+ result .getParentContainer ( ) = file .getParentContainer ( )
2249+ or
2250+ result = getAFileInPack ( ) .( Folder ) .getAChildContainer ( )
2251+ }
2252+
2253+ /**
2254+ * Gets a QLPack that this QLPack depends on.
2255+ */
2256+ QLPack getADependency ( ) {
2257+ exists ( string name | hasDependency ( name , _) | result .getName ( ) .replaceAll ( "-" , "/" ) = name )
2258+ }
2259+
2260+ Location getLocation ( ) {
2261+ // hacky, just pick the first node in the file.
2262+ result =
2263+ min ( YAMLNode entry , Location l , File f |
2264+ entry .getLocation ( ) .getFile ( ) = file and
2265+ f = file and
2266+ l = entry .getLocation ( )
2267+ |
2268+ entry order by l .getStartLine ( ) , l .getStartColumn ( ) , l .getEndColumn ( ) , l .getEndLine ( )
2269+ ) .getLocation ( )
2270+ }
2271+ }
2272+ }
0 commit comments