FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Refactor: extract common CREATE TABLE logic into AbstractTableGenerator by mrigger · Pull Request #1339 · sqlancer/sqlancer · GitHub

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .java  (8) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
77 changes: 77 additions & 0 deletions src/sqlancer/common/gen/AbstractTableGenerator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package sqlancer.common.gen;

import java.util.List;

import sqlancer.common.schema.AbstractTableColumn;

public abstract class AbstractTableGenerator<C extends AbstractTableColumn<?, ?>> extends AbstractGenerator {

/**
* Appends {@code CREATE TABLE <name>}.
*
* @param tableName
* the name of the table to create.
*/
protected void appendCreateTable(String tableName) {
appendCreateTable(tableName, false);
}

/**
* Appends {@code CREATE TABLE [IF NOT EXISTS ]<name>}.
*
* @param tableName
* the name of the table to create.
* @param ifNotExists
* whether to emit the {@code IF NOT EXISTS} clause.
*/
protected void appendCreateTable(String tableName, boolean ifNotExists) {
sb.append("CREATE TABLE ");
if (ifNotExists) {
sb.append("IF NOT EXISTS ");
}
sb.append(tableName);
}

/**
* Appends a parenthesized, comma-separated column definition list, e.g. {@code (c0 INT, c1 TEXT)}. Delegates each
* column's rendering to {@link #appendColumnDefinition(AbstractTableColumn)}.
*
* @param columns
* the columns to render.
*/
protected void appendColumnDefinitions(List<C> columns) {
sb.append("(");
appendColumnDefinitionList(columns);
sb.append(")");
}

/**
* Appends a comma-separated column definition list without enclosing parentheses, e.g. {@code c0 INT, c1 TEXT}.
* Useful when subclasses also emit table-level constraints (e.g. {@code PRIMARY KEY (...)}) inside the same parens.
*
* @param columns
* the columns to render.
*/
protected void appendColumnDefinitionList(List<C> columns) {
for (int i = 0; i < columns.size(); i++) {
if (i != 0) {
sb.append(", ");
}
appendColumnDefinition(columns.get(i));
}
}

/**
* Appends a single column's definition. Default output is {@code <name> <type>}, e.g. {@code c0 INT}. Override to
* add constraints such as {@code NOT NULL}, {@code DEFAULT ...}, or {@code CHECK (...)}.
*
* @param column
* the column whose definition to render.
*/
protected void appendColumnDefinition(C column) {
sb.append(column.getName());
sb.append(" ");
sb.append(column.getType());
}

}
65 changes: 35 additions & 30 deletions src/sqlancer/databend/gen/DatabendTableGenerator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import java.util.List;

import sqlancer.Randomly;
import sqlancer.common.gen.AbstractTableGenerator;
import sqlancer.common.gen.TypedExpressionGenerator;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.databend.DatabendErrors;
import sqlancer.databend.DatabendProvider.DatabendGlobalState;
Expand All @@ -15,44 +15,49 @@
import sqlancer.databend.DatabendToStringVisitor;
import sqlancer.databend.ast.DatabendExpression;

public class DatabendTableGenerator {
public class DatabendTableGenerator extends AbstractTableGenerator<DatabendColumn> {

private DatabendGlobalState globalState;
private TypedExpressionGenerator<DatabendExpression, DatabendColumn, DatabendDataType> gen;

public DatabendTableGenerator() {
this.canAffectSchema = true;
}

public SQLQueryAdapter getQuery(DatabendGlobalState globalState) {
ExpectedErrors errors = new ExpectedErrors();
this.globalState = globalState;
return getStatement();
}

@Override
public void buildStatement() {
DatabendErrors.addExpressionErrors(errors);
StringBuilder sb = new StringBuilder();
String tableName = globalState.getSchema().getFreeTableName();
sb.append("CREATE TABLE ");
sb.append(tableName);
sb.append("(");
appendCreateTable(tableName);
List<DatabendColumn> columns = getNewColumns();
TypedExpressionGenerator<DatabendExpression, DatabendColumn, DatabendDataType> gen = new DatabendNewExpressionGenerator(
globalState).setColumns(columns);
for (int i = 0; i < columns.size(); i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(columns.get(i).getName());
sb.append(" ");
sb.append(columns.get(i).getType());
gen = new DatabendNewExpressionGenerator(globalState).setColumns(columns);
appendColumnDefinitions(columns);
}

if (globalState.getDbmsSpecificOptions().testNotNullConstraints
&& Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" NOT NULL");
} else {
sb.append(" NULL"); // Databend 默认字段为非空,这个将它默认设置为允许空
}
@Override
protected void appendColumnDefinition(DatabendColumn column) {
sb.append(column.getName());
sb.append(" ");
sb.append(column.getType());

if (Randomly.getBoolean() && globalState.getDbmsSpecificOptions().testDefaultValues) {
sb.append(" DEFAULT(");
sb.append(DatabendToStringVisitor.asString(// 常量类型于字段类型等同
gen.generateConstant(columns.get(i).getType().getPrimitiveDataType())));
sb.append(")");
}
if (globalState.getDbmsSpecificOptions().testNotNullConstraints
&& Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" NOT NULL");
} else {
sb.append(" NULL"); // Databend 默认字段为非空,这个将它默认设置为允许空
}

sb.append(")");
return new SQLQueryAdapter(sb.toString(), errors, true);
if (Randomly.getBoolean() && globalState.getDbmsSpecificOptions().testDefaultValues) {
sb.append(" DEFAULT(");
sb.append(DatabendToStringVisitor.asString(// 常量类型于字段类型等同
gen.generateConstant(column.getType().getPrimitiveDataType())));
sb.append(")");
}
}

private static List<DatabendColumn> getNewColumns() {
Expand Down
92 changes: 50 additions & 42 deletions src/sqlancer/duckdb/gen/DuckDBTableGenerator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import java.util.stream.Collectors;

import sqlancer.Randomly;
import sqlancer.common.gen.AbstractTableGenerator;
import sqlancer.common.gen.UntypedExpressionGenerator;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.duckdb.DuckDBErrors;
import sqlancer.duckdb.DuckDBProvider.DuckDBGlobalState;
Expand All @@ -16,50 +16,28 @@
import sqlancer.duckdb.DuckDBToStringVisitor;
import sqlancer.duckdb.ast.DuckDBExpression;

public class DuckDBTableGenerator {
public class DuckDBTableGenerator extends AbstractTableGenerator<DuckDBColumn> {

private DuckDBGlobalState globalState;
private UntypedExpressionGenerator<DuckDBExpression, DuckDBColumn> gen;

public DuckDBTableGenerator() {
this.canAffectSchema = true;
}

public SQLQueryAdapter getQuery(DuckDBGlobalState globalState) {
ExpectedErrors errors = new ExpectedErrors();
StringBuilder sb = new StringBuilder();
this.globalState = globalState;
return getStatement();
}

@Override
public void buildStatement() {
String tableName = globalState.getSchema().getFreeTableName();
sb.append("CREATE TABLE ");
sb.append(tableName);
sb.append("(");
appendCreateTable(tableName);
List<DuckDBColumn> columns = getNewColumns();
UntypedExpressionGenerator<DuckDBExpression, DuckDBColumn> gen = new DuckDBExpressionGenerator(globalState)
.setColumns(columns);
for (int i = 0; i < columns.size(); i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(columns.get(i).getName());
sb.append(" ");
sb.append(columns.get(i).getType());
if (globalState.getDbmsSpecificOptions().testCollate && Randomly.getBooleanWithRatherLowProbability()
&& columns.get(i).getType().getPrimitiveDataType() == DuckDBDataType.VARCHAR) {
sb.append(" COLLATE ");
sb.append(getRandomCollate());
}
if (globalState.getDbmsSpecificOptions().testIndexes && Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" UNIQUE");
}
if (globalState.getDbmsSpecificOptions().testNotNullConstraints
&& Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" NOT NULL");
}
if (globalState.getDbmsSpecificOptions().testCheckConstraints
&& Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" CHECK(");
sb.append(DuckDBToStringVisitor.asString(gen.generateExpression()));
DuckDBErrors.addExpressionErrors(errors);
sb.append(")");
}
if (Randomly.getBoolean() && globalState.getDbmsSpecificOptions().testDefaultValues) {
sb.append(" DEFAULT(");
sb.append(DuckDBToStringVisitor.asString(gen.generateConstant()));
sb.append(")");
}
}
gen = new DuckDBExpressionGenerator(globalState).setColumns(columns);
sb.append("(");
appendColumnDefinitionList(columns);
if (globalState.getDbmsSpecificOptions().testIndexes && Randomly.getBoolean()) {
errors.add("Invalid type for index");
List<DuckDBColumn> primaryKeyColumns = Randomly.nonEmptySubset(columns);
Expand All @@ -68,7 +46,37 @@ public SQLQueryAdapter getQuery(DuckDBGlobalState globalState) {
sb.append(")");
}
sb.append(")");
return new SQLQueryAdapter(sb.toString(), errors, true);
}

@Override
protected void appendColumnDefinition(DuckDBColumn column) {
sb.append(column.getName());
sb.append(" ");
sb.append(column.getType());
if (globalState.getDbmsSpecificOptions().testCollate && Randomly.getBooleanWithRatherLowProbability()
&& column.getType().getPrimitiveDataType() == DuckDBDataType.VARCHAR) {
sb.append(" COLLATE ");
sb.append(getRandomCollate());
}
if (globalState.getDbmsSpecificOptions().testIndexes && Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" UNIQUE");
}
if (globalState.getDbmsSpecificOptions().testNotNullConstraints
&& Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" NOT NULL");
}
if (globalState.getDbmsSpecificOptions().testCheckConstraints
&& Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" CHECK(");
sb.append(DuckDBToStringVisitor.asString(gen.generateExpression()));
DuckDBErrors.addExpressionErrors(errors);
sb.append(")");
}
if (Randomly.getBoolean() && globalState.getDbmsSpecificOptions().testDefaultValues) {
sb.append(" DEFAULT(");
sb.append(DuckDBToStringVisitor.asString(gen.generateConstant()));
sb.append(")");
}
}

public static String getRandomCollate() {
Expand Down
60 changes: 32 additions & 28 deletions src/sqlancer/hsqldb/gen/HSQLDBTableGenerator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,48 @@
import javax.annotation.Nullable;

import sqlancer.Randomly;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.gen.AbstractTableGenerator;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.hsqldb.HSQLDBProvider;
import sqlancer.hsqldb.HSQLDBSchema;

public class HSQLDBTableGenerator {
public class HSQLDBTableGenerator extends AbstractTableGenerator<HSQLDBSchema.HSQLDBColumn> {

private HSQLDBProvider.HSQLDBGlobalState globalState;
private String tableName;

public HSQLDBTableGenerator() {
this.canAffectSchema = true;
}

public SQLQueryAdapter getQuery(HSQLDBProvider.HSQLDBGlobalState globalState, @Nullable String tableName) {
ExpectedErrors errors = new ExpectedErrors();
StringBuilder sb = new StringBuilder();
this.globalState = globalState;
this.tableName = tableName;
return getStatement();
}

@Override
public void buildStatement() {
String name = tableName;
if (tableName == null) {
if (name == null) {
name = globalState.getSchema().getFreeTableName();
}
sb.append("CREATE TABLE ");
if (Randomly.getBoolean()) {
sb.append("IF NOT EXISTS ");
}
sb.append(name);
sb.append("(");
List<HSQLDBSchema.HSQLDBColumn> columns = getNewColumns();
for (int i = 0; i < columns.size(); i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(columns.get(i).getName());
sb.append(" ");
sb.append(columns.get(i).getType().getType().name());
if (columns.get(i).getType().getSize() > 0) {
// Cannot specify size for non composite data types
sb.append("(");
sb.append(columns.get(i).getType().getSize());
sb.append(")");
}
}
sb.append(")");
appendCreateTable(name, Randomly.getBoolean());
appendColumnDefinitions(getNewColumns());
sb.append(";");
return new SQLQueryAdapter(sb.toString(), errors, true);
}

@Override
protected void appendColumnDefinition(HSQLDBSchema.HSQLDBColumn column) {
sb.append(column.getName());
sb.append(" ");
sb.append(column.getType().getType().name());
if (column.getType().getSize() > 0) {
// Cannot specify size for non composite data types
sb.append("(");
sb.append(column.getType().getSize());
sb.append(")");
}
}

private static List<HSQLDBSchema.HSQLDBColumn> getNewColumns() {
Expand Down
Loading
Loading

Back | FazBrowse Home | New Git URL