SqlStatementInfo as AutoValue

This commit is contained in:
Piotr Glazar 2021-03-04 14:10:58 +01:00
parent c18acb858e
commit b0621bbd2d
5 changed files with 51 additions and 78 deletions

View File

@ -10,7 +10,7 @@ apply from: "$rootDir/gradle/publish.gradle"
project.ext.minimumBranchCoverage = 0.0
project.ext.minimumInstructionCoverage = 0.0
def jflexTargetDir = file"${project.buildDir}/generated/jflex/sql"
def jflexTargetDir = file "${project.buildDir}/generated/jflex/sql"
def jflexTask = tasks.create("sqlSanitizerJflex", org.xbib.gradle.plugin.JFlexTask) {
group = 'jflex'
description = 'Generate SqlSanitizer'
@ -25,6 +25,8 @@ dependencies {
compileOnly deps.opentelemetrySdk
implementation deps.slf4j
implementation project(':instrumentation-api')
compileOnly deps.autoValueAnnotations
annotationProcessor deps.autoValue
testImplementation project(':testing-common')
testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0'

View File

@ -5,52 +5,23 @@
package io.opentelemetry.javaagent.instrumentation.api.db;
import java.util.Objects;
import com.google.auto.value.AutoValue;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class SqlStatementInfo {
@Nullable private final String fullStatement;
@Nullable private final String operation;
@Nullable private final String table;
@AutoValue
public abstract class SqlStatementInfo {
public SqlStatementInfo(
public static SqlStatementInfo create(
@Nullable String fullStatement, @Nullable String operation, @Nullable String table) {
this.fullStatement = fullStatement;
this.operation = operation;
this.table = table;
return new AutoValue_SqlStatementInfo(fullStatement, operation, table);
}
@Nullable
public String getFullStatement() {
return fullStatement;
}
public abstract String getFullStatement();
@Nullable
public String getOperation() {
return operation;
}
public abstract String getOperation();
@Nullable
public String getTable() {
return table;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof SqlStatementInfo)) {
return false;
}
SqlStatementInfo other = (SqlStatementInfo) obj;
return Objects.equals(fullStatement, other.fullStatement)
&& Objects.equals(operation, other.operation)
&& Objects.equals(table, other.table);
}
@Override
public int hashCode() {
return Objects.hash(fullStatement, operation, table);
}
public abstract String getTable();
}

View File

@ -23,7 +23,7 @@ public final class SqlStatementSanitizer {
public static SqlStatementInfo sanitize(String statement) {
if (!isStatementSanitizationEnabled() || statement == null) {
return new SqlStatementInfo(statement, null, null);
return SqlStatementInfo.create(statement, null, null);
}
return sqlToStatementInfoCache.get(
statement,

View File

@ -43,7 +43,7 @@ WHITESPACE = [ \t\r\n]+
return sanitizer.getResult();
} catch (java.io.IOException e) {
// should never happen
return new SqlStatementInfo(null, null, null);
return SqlStatementInfo.create(null, null, null);
}
}
@ -107,7 +107,7 @@ WHITESPACE = [ \t\r\n]+
}
SqlStatementInfo getResult(String fullStatement) {
return new SqlStatementInfo(fullStatement, getClass().getSimpleName().toUpperCase(), mainTable);
return SqlStatementInfo.create(fullStatement, getClass().getSimpleName().toUpperCase(), mainTable);
}
}
@ -115,7 +115,7 @@ WHITESPACE = [ \t\r\n]+
static final Operation INSTANCE = new NoOp();
SqlStatementInfo getResult(String fullStatement) {
return new SqlStatementInfo(fullStatement, null, null);
return SqlStatementInfo.create(fullStatement, null, null);
}
}

View File

@ -92,46 +92,46 @@ class SqlStatementSanitizerTest extends Specification {
where:
sql | expected
// Select
'SELECT x, y, z FROM schema.table' | new SqlStatementInfo(sql, 'SELECT', 'schema.table')
'WITH subquery as (select a from b) SELECT x, y, z FROM table' | new SqlStatementInfo(sql, 'SELECT', null)
'SELECT x, y, (select a from b) as z FROM table' | new SqlStatementInfo(sql, 'SELECT', null)
'select delete, insert into, merge, update from table' | new SqlStatementInfo(sql, 'SELECT', 'table')
'select col /* from table2 */ from table' | new SqlStatementInfo(sql, 'SELECT', 'table')
'select col from table join anotherTable' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from (select * from anotherTable)' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from (select * from anotherTable) alias' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from table1 union select col from table2' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from table where col in (select * from anotherTable)' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from table1, table2' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from table1 t1, table2 t2' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from table1 as t1, table2 as t2' | new SqlStatementInfo(sql, 'SELECT', null)
'select col from table where col in (1, 2, 3)' | new SqlStatementInfo('select col from table where col in (?, ?, ?)', 'SELECT', 'table')
'select col from table order by col, col2' | new SqlStatementInfo(sql, 'SELECT', 'table')
'select ąś∂ń© from źćļńĶ order by col, col2' | new SqlStatementInfo(sql, 'SELECT', 'źćļńĶ')
'select 12345678' | new SqlStatementInfo('select ?', 'SELECT', null)
'/* update comment */ select * from table1' | new SqlStatementInfo(sql, 'SELECT', 'table1')
'select /*((*/abc from table' | new SqlStatementInfo(sql, 'SELECT', 'table')
'SeLeCT * FrOm TAblE' | new SqlStatementInfo(sql, 'SELECT', 'TAblE')
'SELECT x, y, z FROM schema.table' | SqlStatementInfo.create(sql, 'SELECT', 'schema.table')
'WITH subquery as (select a from b) SELECT x, y, z FROM table' | SqlStatementInfo.create(sql, 'SELECT', null)
'SELECT x, y, (select a from b) as z FROM table' | SqlStatementInfo.create(sql, 'SELECT', null)
'select delete, insert into, merge, update from table' | SqlStatementInfo.create(sql, 'SELECT', 'table')
'select col /* from table2 */ from table' | SqlStatementInfo.create(sql, 'SELECT', 'table')
'select col from table join anotherTable' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from (select * from anotherTable)' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from (select * from anotherTable) alias' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from table1 union select col from table2' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from table where col in (select * from anotherTable)' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from table1, table2' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from table1 t1, table2 t2' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from table1 as t1, table2 as t2' | SqlStatementInfo.create(sql, 'SELECT', null)
'select col from table where col in (1, 2, 3)' | SqlStatementInfo.create('select col from table where col in (?, ?, ?)', 'SELECT', 'table')
'select col from table order by col, col2' | SqlStatementInfo.create(sql, 'SELECT', 'table')
'select ąś∂ń© from źćļńĶ order by col, col2' | SqlStatementInfo.create(sql, 'SELECT', 'źćļńĶ')
'select 12345678' | SqlStatementInfo.create('select ?', 'SELECT', null)
'/* update comment */ select * from table1' | SqlStatementInfo.create(sql, 'SELECT', 'table1')
'select /*((*/abc from table' | SqlStatementInfo.create(sql, 'SELECT', 'table')
'SeLeCT * FrOm TAblE' | SqlStatementInfo.create(sql, 'SELECT', 'TAblE')
// Insert
' insert into table where lalala' | new SqlStatementInfo(sql, 'INSERT', 'table')
'insert insert into table where lalala' | new SqlStatementInfo(sql, 'INSERT', 'table')
'insert into db.table where lalala' | new SqlStatementInfo(sql, 'INSERT', 'db.table')
'insert without i-n-t-o' | new SqlStatementInfo(sql, 'INSERT', null)
' insert into table where lalala' | SqlStatementInfo.create(sql, 'INSERT', 'table')
'insert insert into table where lalala' | SqlStatementInfo.create(sql, 'INSERT', 'table')
'insert into db.table where lalala' | SqlStatementInfo.create(sql, 'INSERT', 'db.table')
'insert without i-n-t-o' | SqlStatementInfo.create(sql, 'INSERT', null)
// Delete
'delete from table where something something' | new SqlStatementInfo(sql, 'DELETE', 'table')
'delete from 12345678' | new SqlStatementInfo('delete from ?', 'DELETE', null)
'delete (((' | new SqlStatementInfo('delete (((', 'DELETE', null)
'delete from table where something something' | SqlStatementInfo.create(sql, 'DELETE', 'table')
'delete from 12345678' | SqlStatementInfo.create('delete from ?', 'DELETE', null)
'delete (((' | SqlStatementInfo.create('delete (((', 'DELETE', null)
// Update
'update table set answer=42' | new SqlStatementInfo('update table set answer=?', 'UPDATE', 'table')
'update /*table' | new SqlStatementInfo(sql, 'UPDATE', null)
'update table set answer=42' | SqlStatementInfo.create('update table set answer=?', 'UPDATE', 'table')
'update /*table' | SqlStatementInfo.create(sql, 'UPDATE', null)
// Merge
'merge into table' | new SqlStatementInfo(sql, 'MERGE', 'table')
'merge table (into is optional in some dbs)' | new SqlStatementInfo(sql, 'MERGE', 'table')
'merge (into )))' | new SqlStatementInfo(sql, 'MERGE', null)
'merge into table' | SqlStatementInfo.create(sql, 'MERGE', 'table')
'merge table (into is optional in some dbs)' | SqlStatementInfo.create(sql, 'MERGE', 'table')
'merge (into )))' | SqlStatementInfo.create(sql, 'MERGE', null)
// Unknown operation
'and now for something completely different' | new SqlStatementInfo(sql, null, null)
'' | new SqlStatementInfo(sql, null, null)
null | new SqlStatementInfo(sql, null, null)
'and now for something completely different' | SqlStatementInfo.create(sql, null, null)
'' | SqlStatementInfo.create(sql, null, null)
null | SqlStatementInfo.create(sql, null, null)
}
def "very long SELECT statements don't cause problems"() {
@ -144,7 +144,7 @@ class SqlStatementSanitizerTest extends Specification {
expect:
def sanitizedQuery = query.replace('=123', '=?').substring(0, AutoSqlSanitizer.LIMIT)
SqlStatementSanitizer.sanitize(query) == new SqlStatementInfo(sanitizedQuery, "SELECT", "table")
SqlStatementSanitizer.sanitize(query) == SqlStatementInfo.create(sanitizedQuery, "SELECT", "table")
}
def "lots and lots of ticks don't cause stack overflow or long runtimes"() {