Modify according to suggestions

This commit is contained in:
haby0
2021-12-01 11:57:57 +08:00
parent db04a0dadf
commit 08be8edbce
16 changed files with 158 additions and 262 deletions

View File

@@ -4,23 +4,21 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>MyBatis operates the database by using @Select, @Insert, etc. annotations in the method, and can use the $ character
to construct dynamic SQL statements. Attackers can modify the meaning of statements or execute arbitrary SQL commands.</p>
<p>MyBatis allows operating the database by annotating a method with the annotations <code>@Select</code>, <code>@Insert</code>, etc. to construct dynamic SQL statements.
If the syntax `${param}` is used in those statements, and `param` is a parameter of the annotated method, attackers can exploit this to tamper with the SQL statements or execute arbitrary SQL commands.</p>
</overview>
<<recommendation>
<p>
When writing MyBatis mapping statements, try to use the format "#{xxx}". If you have to use parameters
such as "${xxx}", you must manually filter to prevent SQL injection attacks.
When writing MyBatis mapping statements, try to use the syntax <code>#{xxx}</code>. If the syntax <code>${xxx}</code> must be used, any parameters included in it should be sanitized to prevent SQL injection attacks.
</p>
</recommendation>
<example>
<p>
The following examples show the bad situation and the good situation respectively. The <code>bad1</code> method uses <code>$(name)</code>
in the <code>@Select</code> annotation to dynamically splice SQL statements, and there is a SQL injection vulnerability.
The good1 method uses the <code>#{name}</code> method in the <code>@Select</code> annotation to splice SQL statements,
and the MyBatis framework will handle the dangerous characters entered by the user, And did not cause SQL injection vulnerabilities.
The following sample shows a bad and a good example of MyBatis annotations usage. The <code>bad1</code> method uses <code>$(name)</code>
in the <code>@Select</code> annotation to dynamically build a SQL statement, which causes a SQL injection vulnerability.
The <code>good1</code> method uses <code>#{name}</code> in the <code>@Select</code> annotation to to dynamically include the parameter in a SQL statement, which allows the MyBatis framework to handle the sanitization, preventing the vulnerability.
</p>
<sample src="MyBatisAnnotationSqlInjection.java" />
</example>

View File

@@ -1,12 +1,12 @@
/**
* @name MyBatis annotation sql injection
* @name SQL injection in MyBatis annotation
* @description Constructing a dynamic SQL statement with input that comes from an
* untrusted source could allow an attacker to modify the statement's
* meaning or to execute arbitrary SQL commands.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/sql-injection
* @id java/mybatis-annotation-sql-injection
* @tags security
* external/cwe/cwe-089
*/
@@ -14,7 +14,6 @@
import java
import DataFlow::PathGraph
import MyBatisAnnotationSqlInjectionLib
import semmle.code.java.security.SanitizerGuard
import semmle.code.java.dataflow.FlowSources
private class MyBatisAnnotationSqlInjectionConfiguration extends TaintTracking::Configuration {
@@ -32,10 +31,6 @@ private class MyBatisAnnotationSqlInjectionConfiguration extends TaintTracking::
node.getType() instanceof NumberType
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof ContainsSanitizer or guard instanceof EqualsSanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType() instanceof MapType and
@@ -60,5 +55,5 @@ where
cfg.hasFlowPath(source, sink) and
isMybatisAnnotationSqlInjection(sink.getNode(), isoa)
select sink.getNode(), source, sink,
"MyBatis annotation sql injection might include code from $@ to $@.", source.getNode(),
"this user input", isoa, "this sql operation"
"MyBatis annotation SQL injection might include code from $@ to $@.", source.getNode(),
"this user input", isoa, "this SQL operation"

View File

@@ -1,3 +1,7 @@
/**
* Provides classes for SQL injection detection in MyBatis annotation.
*/
import java
import MyBatisCommonLib
import semmle.code.xml.MyBatisMapperXML
@@ -7,7 +11,7 @@ import semmle.code.java.frameworks.Properties
/** A sink for MyBatis annotation method call an argument. */
class MyBatisAnnotationMethodCallAnArgument extends DataFlow::Node {
MyBatisAnnotationMethodCallAnArgument() {
exists(MybatisSqlOperationAnnotationMethod msoam, MethodAccess ma | ma.getMethod() = msoam |
exists(MyBatisSqlOperationAnnotationMethod msoam, MethodAccess ma | ma.getMethod() = msoam |
ma.getAnArgument() = this.asExpr()
)
}
@@ -15,7 +19,7 @@ class MyBatisAnnotationMethodCallAnArgument extends DataFlow::Node {
/** Get the #{...} or ${...} parameters in the Mybatis annotation value. */
private string getAnMybatiAnnotationSetValue(IbatisSqlOperationAnnotation isoa) {
result = isoa.getSqlValue().trim().regexpFind("(#|\\$)(\\{([^\\}]*\\}))", _, _)
result = isoa.getSqlValue().trim().regexpFind("(#|\\$)\\{[^\\}]*\\}", _, _)
}
predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperationAnnotation isoa) {
@@ -27,15 +31,15 @@ predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperatio
// @Select(select id,name from test where name like '%${value}%')
// Test test(String name);
// ```
exists(MybatisSqlOperationAnnotationMethod msoam, MethodAccess ma, string res |
exists(MyBatisSqlOperationAnnotationMethod msoam, MethodAccess ma, string res |
msoam = ma.getMethod()
|
msoam.getAnAnnotation() = isoa and
res = getAnMybatiAnnotationSetValue(isoa) and
msoam.getNumberOfParameters() = 1 and
not ma.getMethod().getAParameter().hasAnnotation() and
not ma.getMethod().getAParameter().getAnAnnotation().getType() instanceof TypeParam and
res.matches("%${%}") and
not res.matches("${" + getAnMybatisConfigurationVariableKey() + "}") and
not res = "${" + getAnMybatisConfigurationVariableKey() + "}" and
ma.getAnArgument() = node.asExpr()
)
or
@@ -47,11 +51,11 @@ predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperatio
// @Select(select id,name from test where name like '%${value}%')
// Test test(Map map);
// ```
exists(MybatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, string res |
exists(MyBatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, string res |
msoam = ma.getMethod()
|
msoam.getAnAnnotation() = isoa and
not ma.getMethod().getParameter(i).hasAnnotation() and
not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and
(
ma.getMethod().getParameterType(i) instanceof MapType or
ma.getMethod().getParameterType(i) instanceof ListType or
@@ -59,7 +63,7 @@ predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperatio
) and
res = getAnMybatiAnnotationSetValue(isoa) and
res.matches("%${%}") and
not res.matches("${" + getAnMybatisConfigurationVariableKey() + "}") and
not res = "${" + getAnMybatisConfigurationVariableKey() + "}" and
ma.getArgument(i) = node.asExpr()
)
or
@@ -71,13 +75,13 @@ predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperatio
// @Select(select id,name from test order by ${name,jdbcType=VARCHAR})
// void test(Test test);
// ```
exists(MybatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, Class c |
exists(MyBatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, RefType t |
msoam = ma.getMethod()
|
msoam.getAnAnnotation() = isoa and
not ma.getMethod().getParameter(i).hasAnnotation() and
ma.getMethod().getParameterType(i).getName() = c.getName() and
getAnMybatiAnnotationSetValue(isoa).matches("%${" + c.getAField().getName() + "%}") and
not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and
ma.getMethod().getParameterType(i).getName() = t.getName() and
getAnMybatiAnnotationSetValue(isoa).matches("%${" + t.getAField().getName() + "%}") and
ma.getArgument(i) = node.asExpr()
)
or
@@ -89,12 +93,10 @@ predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperatio
// @Select(select id,name from test order by ${orderby,jdbcType=VARCHAR})
// void test(@Param("orderby") String name);
// ```
exists(MybatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, Annotation annotation |
msoam = ma.getMethod()
exists(MyBatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, Annotation annotation |
msoam = ma.getMethod() and ma.getMethod().getParameter(i).getAnAnnotation() = annotation
|
msoam.getAnAnnotation() = isoa and
ma.getMethod().getParameter(i).hasAnnotation() and
ma.getMethod().getParameter(i).getAnAnnotation() = annotation and
annotation.getType() instanceof TypeParam and
getAnMybatiAnnotationSetValue(isoa)
.matches("%${" + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() +
@@ -109,18 +111,18 @@ predicate isMybatisAnnotationSqlInjection(DataFlow::Node node, IbatisSqlOperatio
// @Select(select id,name from test order by ${arg0,jdbcType=VARCHAR})
// void test(String name);
// ```
exists(MybatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, string res |
exists(MyBatisSqlOperationAnnotationMethod msoam, MethodAccess ma, int i, string res |
msoam = ma.getMethod()
|
msoam.getAnAnnotation() = isoa and
not ma.getMethod().getParameter(i).hasAnnotation() and
not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and
res = getAnMybatiAnnotationSetValue(isoa) and
(
res.matches("%${param" + (i + 1) + "%}")
or
res.matches("%${arg" + i + "%}")
) and
not res.matches("${" + getAnMybatisConfigurationVariableKey() + "}") and
not res = "${" + getAnMybatisConfigurationVariableKey() + "}" and
ma.getArgument(i) = node.asExpr()
)
}

View File

@@ -1,3 +1,7 @@
/**
* Provides public classes for MyBatis SQL injection detection.
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.MyBatis
@@ -28,15 +32,10 @@ private class PropertiesFlowConfig extends DataFlow2::Configuration {
string getAnMybatisConfigurationVariableKey() {
exists(PropertiesFlowConfig conf, DataFlow::Node n |
propertiesKey(n, result) and
conf.hasFlow(_, n)
conf.hasFlowTo(n)
)
}
/** The interface `org.apache.ibatis.annotations.Param`. */
class TypeParam extends Interface {
TypeParam() { this.hasQualifiedName("org.apache.ibatis.annotations", "Param") }
}
/** A reference type that extends a parameterization of `java.util.List`. */
class ListType extends RefType {
ListType() {

View File

@@ -9,8 +9,7 @@
<<recommendation>
<p>
When writing MyBatis mapping statements, try to use the format "#{xxx}". If you have to use parameters
such as "${xxx}", you must manually filter to prevent SQL injection attacks.
When writing MyBatis mapping statements, try to use the syntax <code>#{xxx}</code>. If the syntax <code>${xxx}</code> must be used, any parameters included in it should be sanitized to prevent SQL injection attacks.
</p>
</recommendation>
@@ -18,7 +17,7 @@ such as "${xxx}", you must manually filter to prevent SQL injection attacks.
<p>
The following examples show the bad situation and the good situation respectively. In <code>bad1</code>
and <code>bad2</code> and <code>bad3</code> and <code>bad4</code> and <code >bad5</code>, the program
${ xxx} are dynamic SQL statements, these five examples of SQL injection vulnerabilities. In <code>good1</code>,
${xxx} are dynamic SQL statements, these five examples of SQL injection vulnerabilities. In <code>good1</code>,
the program uses the ${xxx} dynamic feature SQL statement, but there are subtle restrictions on the data,
and there is no SQL injection vulnerability.
</p>

View File

@@ -1,12 +1,12 @@
/**
* @name MyBatis Mapper xml sql injection
* @name SQL injection in MyBatis Mapper XML
* @description Constructing a dynamic SQL statement with input that comes from an
* untrusted source could allow an attacker to modify the statement's
* meaning or to execute arbitrary SQL commands.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/sql-injection
* @id java/mybatis-xml-sql-injection
* @tags security
* external/cwe/cwe-089
*/
@@ -15,7 +15,6 @@ import java
import DataFlow::PathGraph
import MyBatisMapperXmlSqlInjectionLib
import semmle.code.xml.MyBatisMapperXML
import semmle.code.java.security.SanitizerGuard
import semmle.code.java.dataflow.FlowSources
private class MyBatisMapperXmlSqlInjectionConfiguration extends TaintTracking::Configuration {
@@ -33,10 +32,6 @@ private class MyBatisMapperXmlSqlInjectionConfiguration extends TaintTracking::C
node.getType() instanceof NumberType
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof ContainsSanitizer or guard instanceof EqualsSanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType() instanceof MapType and
@@ -61,5 +56,5 @@ where
cfg.hasFlowPath(source, sink) and
isMapperXmlSqlInjection(sink.getNode(), xmle)
select sink.getNode(), source, sink,
"MyBatis Mapper XML sql injection might include code from $@ to $@.", source.getNode(),
"this user input", xmle, "this sql operation"
"MyBatis Mapper XML SQL injection might include code from $@ to $@.", source.getNode(),
"this user input", xmle, "this SQL operation"

View File

@@ -1,3 +1,7 @@
/**
* Provide classes for SQL injection detection in MyBatis Mapper XML.
*/
import java
import MyBatisCommonLib
import semmle.code.xml.MyBatisMapperXML
@@ -17,116 +21,120 @@ class MyBatisMapperMethodCallAnArgument extends DataFlow::Node {
/** Get the #{...} or ${...} parameters in the Mybatis mapper xml file */
private string getAnMybatiXmlSetValue(XMLElement xmle) {
result = xmle.getTextValue().trim().regexpFind("(#|\\$)(\\{([^\\}]*\\}))", _, _)
result = xmle.getTextValue().trim().regexpFind("(#|\\$)\\{[^\\}]*\\}", _, _)
}
predicate isMapperXmlSqlInjection(DataFlow::Node node, XMLElement xmle) {
// MyBatis Mapper method Param Annotation sql injection vulnerabilities.
// e.g. MyBatis Mapper method: `void test(@Param("orderby") String name);` and MyBatis Mapper XML file:`select id,name from test order by ${orderby,jdbcType=VARCHAR}`
exists(
MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess mc, int i,
Annotation annotation
|
mbmxe.getMapperMethod() = mc.getMethod()
exists(MyBatisMapperSqlOperation mbmxe, MethodAccess ma, int i, Annotation annotation |
mbmxe.getMapperMethod() = ma.getMethod()
|
(
mbmxe.getAChild*() = xmle
or
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
exists(MyBatisMapperSql mbms |
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
)
) and
mc.getMethod().getParameter(i).hasAnnotation() and
mc.getMethod().getParameter(i).getAnAnnotation() = annotation and
ma.getMethod().getParameter(i).getAnAnnotation() = annotation and
annotation.getType() instanceof TypeParam and
getAnMybatiXmlSetValue(xmle)
.matches("%${" + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() +
"%}") and
mc.getArgument(i) = node.asExpr()
ma.getArgument(i) = node.asExpr()
)
or
// MyBatis Mapper method Class Field sql injection vulnerabilities.
// e.g. MyBatis Mapper method: `void test(Test test);` and MyBatis Mapper XML file:`select id,name from test order by ${name,jdbcType=VARCHAR}`
exists(MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess mc, int i, Class c |
mbmxe.getMapperMethod() = mc.getMethod()
exists(MyBatisMapperSqlOperation mbmxe, MethodAccess ma, int i, RefType t |
mbmxe.getMapperMethod() = ma.getMethod()
|
(
mbmxe.getAChild*() = xmle
or
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
exists(MyBatisMapperSql mbms |
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
)
) and
not mc.getMethod().getParameter(i).hasAnnotation() and
mc.getMethod().getParameterType(i).getName() = c.getName() and
getAnMybatiXmlSetValue(xmle).matches("%${" + c.getAField().getName() + "%}") and
mc.getArgument(i) = node.asExpr()
not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and
ma.getMethod().getParameterType(i).getName() = t.getName() and
getAnMybatiXmlSetValue(xmle).matches("%${" + t.getAField().getName() + "%}") and
ma.getArgument(i) = node.asExpr()
)
or
// The parameter type of MyBatis Mapper method is Map or List or Array, which may cause SQL injection vulnerability.
// e.g. MyBatis Mapper method: `void test(Map<String, String> params);` and MyBatis Mapper XML file:`select id,name from test where name like '%${name}%'`
exists(
MyBatisMapperSqlOperation mbmxe, MyBatisMapperForeach mbmf, MyBatisMapperSql mbms,
MethodAccess mc, int i, string res
MyBatisMapperSqlOperation mbmxe, MyBatisMapperForeach mbmf, MethodAccess ma, int i, string res
|
mbmxe.getMapperMethod() = mc.getMethod()
mbmxe.getMapperMethod() = ma.getMethod()
|
mbmf = xmle and
(
mbmxe.getAChild*() = xmle
or
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
exists(MyBatisMapperSql mbms |
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
)
) and
not mc.getMethod().getParameter(i).hasAnnotation() and
not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and
(
mc.getMethod().getParameterType(i) instanceof MapType or
mc.getMethod().getParameterType(i) instanceof ListType or
mc.getMethod().getParameterType(i) instanceof Array
ma.getMethod().getParameterType(i) instanceof MapType or
ma.getMethod().getParameterType(i) instanceof ListType or
ma.getMethod().getParameterType(i) instanceof Array
) and
res = getAnMybatiXmlSetValue(xmle) and
res.matches("%${%}") and
not res.matches("${" + getAnMybatisConfigurationVariableKey() + "}") and
mc.getArgument(i) = node.asExpr()
not res = "${" + getAnMybatisConfigurationVariableKey() + "}" and
ma.getArgument(i) = node.asExpr()
)
or
// SQL injection vulnerability where the MyBatis Mapper method has only one parameter and the parameter is not annotated with `@Param`.
// e.g. MyBatis Mapper method: `void test(String name);` and MyBatis Mapper XML file:`select id,name from test where name like '%${value}%'`
exists(MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess mc, string res |
mbmxe.getMapperMethod() = mc.getMethod()
exists(MyBatisMapperSqlOperation mbmxe, MethodAccess ma, string res |
mbmxe.getMapperMethod() = ma.getMethod()
|
(
mbmxe.getAChild*() = xmle
or
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
exists(MyBatisMapperSql mbms |
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
)
) and
res = getAnMybatiXmlSetValue(xmle) and
mc.getMethod().getNumberOfParameters() = 1 and
not mc.getMethod().getAParameter().hasAnnotation() and
ma.getMethod().getNumberOfParameters() = 1 and
not ma.getMethod().getAParameter().getAnAnnotation().getType() instanceof TypeParam and
res.matches("%${%}") and
not res.matches("${" + getAnMybatisConfigurationVariableKey() + "}") and
mc.getAnArgument() = node.asExpr()
not res = "${" + getAnMybatisConfigurationVariableKey() + "}" and
ma.getAnArgument() = node.asExpr()
)
or
// MyBatis Mapper method default parameter sql injection vulnerabilities.the default parameter form of the method is arg[0...n] or param[1...n].
// e.g. MyBatis Mapper method: `void test(String name);` and MyBatis Mapper XML file:`select id,name from test where name like '%${arg0 or param1}%'`
exists(
MyBatisMapperSqlOperation mbmxe, MyBatisMapperSql mbms, MethodAccess mc, int i, string res
|
mbmxe.getMapperMethod() = mc.getMethod()
exists(MyBatisMapperSqlOperation mbmxe, MethodAccess ma, int i, string res |
mbmxe.getMapperMethod() = ma.getMethod()
|
(
mbmxe.getAChild*() = xmle
or
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
exists(MyBatisMapperSql mbms |
mbmxe.getInclude().getRefid() = mbms.getId() and
mbms.getAChild*() = xmle
)
) and
not mc.getMethod().getParameter(i).hasAnnotation() and
not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and
res = getAnMybatiXmlSetValue(xmle) and
(
res.matches("%${param" + (i + 1) + "%}")
or
res.matches("%${arg" + i + "%}")
) and
mc.getArgument(i) = node.asExpr()
not res = "${" + getAnMybatisConfigurationVariableKey() + "}" and
ma.getArgument(i) = node.asExpr()
)
}

View File

@@ -1,33 +0,0 @@
/**
* Provide universal sanitizer guards.
*/
import java
import semmle.code.java.dataflow.DataFlow
/**
* An contains method sanitizer guard.
*
* e.g. `if(test.contains("test")) {...`
*/
class ContainsSanitizer extends DataFlow::BarrierGuard {
ContainsSanitizer() { this.(MethodAccess).getMethod().hasName("contains") }
override predicate checks(Expr e, boolean branch) {
e = this.(MethodAccess).getArgument(0) and branch = true
}
}
/**
* An equals method sanitizer guard.
*
* e.g. `if("test".equals(test)) {...`
*/
class EqualsSanitizer extends DataFlow::BarrierGuard {
EqualsSanitizer() { this.(MethodAccess).getMethod().hasName("equals") }
override predicate checks(Expr e, boolean branch) {
e = [this.(MethodAccess).getArgument(0), this.(MethodAccess).getQualifier()] and
branch = true
}
}

View File

@@ -1,3 +1,7 @@
/**
* Provides classes for working with MyBatis mapper xml files and their content.
*/
import java
/**
@@ -20,12 +24,14 @@ class MyBatisMapperXMLElement extends XMLElement {
/**
* Gets the value for this element, with leading and trailing whitespace trimmed.
*/
string getValue() { result = allCharactersString().trim() }
string getValue() { result = this.allCharactersString().trim() }
/**
* Gets the reference type bound to MyBatis Mapper XML File.
*/
RefType getNamespaceRefType() { result.getQualifiedName() = getAttribute("namespace").getValue() }
RefType getNamespaceRefType() {
result.getQualifiedName() = this.getAttribute("namespace").getValue()
}
}
/**
@@ -37,8 +43,11 @@ abstract class MyBatisMapperSqlOperation extends MyBatisMapperXMLElement {
/**
* Gets the `<include>` element in a `MyBatisMapperSqlOperation`.
*/
MyBatisMapperInclude getInclude() { result = getAChild*() }
MyBatisMapperInclude getInclude() { result = this.getAChild*() }
/**
* Gets the method bound to MyBatis Mapper XML File.
*/
Method getMapperMethod() {
result.getName() = this.getId() and
result.getDeclaringType() = this.getParent().(MyBatisMapperXMLElement).getNamespaceRefType()
@@ -49,72 +58,72 @@ abstract class MyBatisMapperSqlOperation extends MyBatisMapperXMLElement {
* A `<insert>` element in a `MyBatisMapperSqlOperation`.
*/
class MyBatisMapperInsert extends MyBatisMapperSqlOperation {
MyBatisMapperInsert() { getName() = "insert" }
MyBatisMapperInsert() { this.getName() = "insert" }
/**
* Gets the value of the `id` attribute of this `<insert>`.
*/
override string getId() { result = getAttribute("id").getValue() }
override string getId() { result = this.getAttribute("id").getValue() }
}
/**
* A `<update>` element in a `MyBatisMapperSqlOperation`.
*/
class MyBatisMapperUpdate extends MyBatisMapperSqlOperation {
MyBatisMapperUpdate() { getName() = "update" }
MyBatisMapperUpdate() { this.getName() = "update" }
/**
* Gets the value of the `id` attribute of this `<update>`.
*/
override string getId() { result = getAttribute("id").getValue() }
override string getId() { result = this.getAttribute("id").getValue() }
}
/**
* A `<delete>` element in a `MyBatisMapperSqlOperation`.
*/
class MyBatisMapperDelete extends MyBatisMapperSqlOperation {
MyBatisMapperDelete() { getName() = "delete" }
MyBatisMapperDelete() { this.getName() = "delete" }
/**
* Gets the value of the `id` attribute of this `<delete>`.
*/
override string getId() { result = getAttribute("id").getValue() }
override string getId() { result = this.getAttribute("id").getValue() }
}
/**
* A `<select>` element in a `MyBatisMapperSqlOperation`.
*/
class MyBatisMapperSelect extends MyBatisMapperSqlOperation {
MyBatisMapperSelect() { getName() = "select" }
MyBatisMapperSelect() { this.getName() = "select" }
/**
* Gets the value of the `id` attribute of this `<select>`.
*/
override string getId() { result = getAttribute("id").getValue() }
override string getId() { result = this.getAttribute("id").getValue() }
}
/**
* A `<select>` element in a `MyBatisMapperXMLElement`.
*/
class MyBatisMapperSql extends MyBatisMapperXMLElement {
MyBatisMapperSql() { getName() = "sql" }
MyBatisMapperSql() { this.getName() = "sql" }
/**
* Gets the value of the `id` attribute of this `<sql>`.
*/
string getId() { result = getAttribute("id").getValue() }
string getId() { result = this.getAttribute("id").getValue() }
}
/**
* A `<include>` element in a `MyBatisMapperXMLElement`.
*/
class MyBatisMapperInclude extends MyBatisMapperXMLElement {
MyBatisMapperInclude() { getName() = "include" }
MyBatisMapperInclude() { this.getName() = "include" }
/**
* Gets the value of the `refid` attribute of this `<include>`.
*/
string getRefid() { result = getAttribute("refid").getValue() }
string getRefid() { result = this.getAttribute("refid").getValue() }
}
/**