bug fixed for 'null constraint' and 'default null'. issue #1349

This commit is contained in:
wenshao
2016-08-04 12:11:41 +08:00
parent 7fe5515c03
commit e75a304fe9
20 changed files with 77 additions and 81 deletions
@@ -17,9 +17,9 @@ package com.alibaba.druid.sql.ast.statement;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class NotNullConstraint extends SQLConstraintImpl implements SQLColumnConstraint {
public class SQLNotNullConstraint extends SQLConstraintImpl implements SQLColumnConstraint {
public NotNullConstraint(){
public SQLNotNullConstraint(){
}
@@ -17,9 +17,9 @@ package com.alibaba.druid.sql.ast.statement;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class NullConstraint extends SQLConstraintImpl implements SQLColumnConstraint {
public class SQLNullConstraint extends SQLConstraintImpl implements SQLColumnConstraint {
public NullConstraint(){
public SQLNullConstraint(){
}
@Override
@@ -323,12 +323,8 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
if (x.getDefaultExpr() != null) {
if (x.getDefaultExpr() instanceof SQLNullExpr) {
print0(ucase ? " NULL" : " null");
} else {
print0(ucase ? " DEFAULT " : " default ");
x.getDefaultExpr().accept(this);
}
print0(ucase ? " DEFAULT " : " default ");
x.getDefaultExpr().accept(this);
}
if (x.getStorage() != null) {
@@ -64,8 +64,8 @@ import com.alibaba.druid.sql.ast.expr.SQLSomeExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.NotNullConstraint;
import com.alibaba.druid.sql.ast.statement.NullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
import com.alibaba.druid.sql.ast.statement.SQLCheck;
@@ -1683,13 +1683,13 @@ public class SQLExprParser extends SQLParser {
if (lexer.token() == Token.NOT) {
lexer.nextToken();
accept(Token.NULL);
column.addConstraint(new NotNullConstraint());
column.addConstraint(new SQLNotNullConstraint());
return parseColumnRest(column);
}
if (lexer.token() == Token.NULL) {
lexer.nextToken();
column.getConstraints().add(new NullConstraint());
column.getConstraints().add(new SQLNullConstraint());
return parseColumnRest(column);
}
@@ -1746,7 +1746,7 @@ public class SQLExprParser extends SQLParser {
if (lexer.token() == Token.NOT) {
lexer.nextToken();
accept(Token.NULL);
NotNullConstraint notNull = new NotNullConstraint();
SQLNotNullConstraint notNull = new SQLNotNullConstraint();
notNull.setName(name);
column.addConstraint(notNull);
return parseColumnRest(column);
@@ -1182,7 +1182,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
return false;
}
public boolean visit(NotNullConstraint x) {
public boolean visit(SQLNotNullConstraint x) {
if (x.getName() != null) {
print0(ucase ? "CONSTRAINT " : "constraint ");
x.getName().accept(this);
@@ -1192,7 +1192,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
return false;
}
public boolean visit(NullConstraint x) {
public boolean visit(SQLNullConstraint x) {
if (x.getName() != null) {
print0(ucase ? "CONSTRAINT " : "constraint ");
x.getName().accept(this);
@@ -245,9 +245,9 @@ public interface SQLASTVisitor {
void endVisit(SQLCreateViewStatement.Column x);
boolean visit(NotNullConstraint x);
boolean visit(SQLNotNullConstraint x);
void endVisit(NotNullConstraint x);
void endVisit(SQLNotNullConstraint x);
void endVisit(SQLMethodInvokeExpr x);
@@ -717,8 +717,8 @@ public interface SQLASTVisitor {
void endVisit(SQLErrorLoggingClause x);
boolean visit(NullConstraint x);
boolean visit(SQLNullConstraint x);
void endVisit(NullConstraint x);
void endVisit(SQLNullConstraint x);
}
@@ -352,11 +352,11 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
public void endVisit(SQLCreateViewStatement.Column x) {
}
public boolean visit(NotNullConstraint x) {
public boolean visit(SQLNotNullConstraint x) {
return true;
}
public void endVisit(NotNullConstraint x) {
public void endVisit(SQLNotNullConstraint x) {
}
@Override
@@ -1567,11 +1567,11 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
}
@Override
public boolean visit(NullConstraint x) {
public boolean visit(SQLNullConstraint x) {
return true;
}
@Override
public void endVisit(NullConstraint x) {
public void endVisit(SQLNullConstraint x) {
}
}
@@ -11,7 +11,7 @@ import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLSomeExpr;
import com.alibaba.druid.sql.ast.statement.NotNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAlterColumn;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableConstraint;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropConstraint;
@@ -48,7 +48,7 @@ public class SQLASTVisitorAdapterTest extends TestCase {
new SQLCurrentOfCursorExpr ().accept(adapter);
new SQLInsertStatement ().accept(adapter);
new SQLUpdateStatement ().accept(adapter);
new NotNullConstraint ().accept(adapter);
new SQLNotNullConstraint ().accept(adapter);
new SQLMethodInvokeExpr ().accept(adapter);
new SQLCallStatement ().accept(adapter);
new SQLSomeExpr ().accept(adapter);
@@ -32,11 +32,11 @@ public class MySqlAlterTableAddPrimaryKey extends TestCase {
parser.match(Token.EOF);
Assert.assertEquals("ALTER TABLE `test`.`tb1`" + //
"\n\tCHANGE COLUMN `fid` `fid` INT(11) NOT NULL NULL,\n\t" + //
"\n\tCHANGE COLUMN `fid` `fid` INT(11) NOT NULL DEFAULT NULL,\n\t" + //
"ADD PRIMARY KEY (`fid`)", SQLUtils.toMySqlString(stmt));
Assert.assertEquals("alter table `test`.`tb1`" + //
"\n\tchange column `fid` `fid` INT(11) not null null,\n\t" + //
"\n\tchange column `fid` `fid` INT(11) not null default null,\n\t" + //
"add primary key (`fid`)", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
}
@@ -32,7 +32,7 @@ public class MySqlAlterTableTest extends TestCase {
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("ALTER TABLE `test`.`tb1`\n\tCHANGE COLUMN `fname` `fname1` VARCHAR(45) NULL", output);
Assert.assertEquals("ALTER TABLE `test`.`tb1`\n\tCHANGE COLUMN `fname` `fname1` VARCHAR(45) NULL DEFAULT NULL", output);
}
public void test_alter_1() throws Exception {
@@ -33,7 +33,7 @@ public class MySqlAlterTableTest3 extends TestCase {
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("ALTER TABLE `test`.`tb1`" + //
"\n\tDROP COLUMN `f3`," + //
"\n\tCHANGE COLUMN `fname` `fname` VARCHAR(45) CHARACTER SET latin1 NULL AFTER `fid`",
"\n\tCHANGE COLUMN `fname` `fname` VARCHAR(45) CHARACTER SET latin1 NULL DEFAULT NULL AFTER `fid`",
output);
}
@@ -46,10 +46,10 @@ public class MySqlCreateTableTest14 extends MysqlTest {
Assert.assertEquals("CREATE TABLE `OptionList` ("
+ "\n\t`ID` int(11) NOT NULL AUTO_INCREMENT, "
+ "\n\t`OptionID` int(11) NULL COMMENT '选项ID', "
+ "\n\t`QuizID` int(11) NULL COMMENT '竞猜题目ID', "
+ "\n\t`OptionName` varchar(500) NULL COMMENT '选项名称', "
+ "\n\t`OptionCount` int(11) NULL COMMENT '选择的人数', "
+ "\n\t`OptionID` int(11) DEFAULT NULL COMMENT '选项ID', "
+ "\n\t`QuizID` int(11) DEFAULT NULL COMMENT '竞猜题目ID', "
+ "\n\t`OptionName` varchar(500) DEFAULT NULL COMMENT '选项名称', "
+ "\n\t`OptionCount` int(11) DEFAULT NULL COMMENT '选择的人数', "
+ "\n\tPRIMARY KEY (`ID`), "
+ "\n\tKEY `quizId` USING BTREE (`QuizID`), "
+ "\n\tKEY `optionId` USING BTREE (`OptionID`)"
@@ -57,10 +57,10 @@ public class MySqlCreateTableTest14 extends MysqlTest {
SQLUtils.toMySqlString(stmt));
Assert.assertEquals("create table `OptionList` ("
+ "\n\t`ID` int(11) not null auto_increment, "
+ "\n\t`OptionID` int(11) null comment '选项ID', "
+ "\n\t`QuizID` int(11) null comment '竞猜题目ID', "
+ "\n\t`OptionName` varchar(500) null comment '选项名称', "
+ "\n\t`OptionCount` int(11) null comment '选择的人数', "
+ "\n\t`OptionID` int(11) default null comment '选项ID', "
+ "\n\t`QuizID` int(11) default null comment '竞猜题目ID', "
+ "\n\t`OptionName` varchar(500) default null comment '选项名称', "
+ "\n\t`OptionCount` int(11) default null comment '选择的人数', "
+ "\n\tprimary key (`ID`), "
+ "\n\tkey `quizId` using BTREE (`QuizID`), "
+ "\n\tkey `optionId` using BTREE (`OptionID`)"
@@ -100,26 +100,26 @@ public class MySqlCreateTableTest54 extends MysqlTest {
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("CREATE TABLE `t_activity_node` ("
+ "\n\t`id` bigint(20) NOT NULL, "
+ "\n\t`sellerId` bigint(20) NULL, "
+ "\n\t`sellerId` bigint(20) DEFAULT NULL, "
+ "\n\t`canvas_id` bigint(20) NOT NULL COMMENT '画布ID', "
+ "\n\t`view_node_id` bigint(20) NOT NULL COMMENT '对应显示的节点id', "
+ "\n\t`activity_type` int(11) NOT NULL COMMENT '活动类型', "
+ "\n\t`node_type` int(11) NOT NULL COMMENT '节点类型', "
+ "\n\t`node_title` varchar(200) NOT NULL COMMENT '节点标题', "
+ "\n\t`status` int(11) NOT NULL DEFAULT '0' COMMENT '页面的显示状态', "
+ "\n\t`update_status` int(11) NULL COMMENT '节点创建后的修改状态', "
+ "\n\t`execute_status` int(11) NULL COMMENT '节点当前的执行状态', "
+ "\n\t`start_time` datetime NULL COMMENT '该节点活动的开始时间', "
+ "\n\t`end_time` datetime NULL COMMENT '该节点活动的结束时间', "
+ "\n\t`activity_start_time` datetime NULL COMMENT '营销活动的开始时间', "
+ "\n\t`activity_end_time` datetime NULL COMMENT '营销活动的结束时间', "
+ "\n\t`report_start_time` datetime NULL COMMENT '该节点活动效果报告的开始时间', "
+ "\n\t`report_end_time` datetime NULL COMMENT '该节点活动效果报告的结束时间', "
+ "\n\t`cron_rule` varchar(100) NULL COMMENT '周期性营销的时间表达式', "
+ "\n\t`split_rule` varchar(1000) NULL COMMENT '节点拆分规则', "
+ "\n\t`search_json` varchar(5000) NULL COMMENT '索引查找的条件字符串', "
+ "\n\t`filter_json` varchar(1000) NULL COMMENT '各种过滤条件的设置', "
+ "\n\t`buyer_count` int(11) NULL COMMENT '营销的会员数量', "
+ "\n\t`update_status` int(11) DEFAULT NULL COMMENT '节点创建后的修改状态', "
+ "\n\t`execute_status` int(11) DEFAULT NULL COMMENT '节点当前的执行状态', "
+ "\n\t`start_time` datetime DEFAULT NULL COMMENT '该节点活动的开始时间', "
+ "\n\t`end_time` datetime DEFAULT NULL COMMENT '该节点活动的结束时间', "
+ "\n\t`activity_start_time` datetime DEFAULT NULL COMMENT '营销活动的开始时间', "
+ "\n\t`activity_end_time` datetime DEFAULT NULL COMMENT '营销活动的结束时间', "
+ "\n\t`report_start_time` datetime DEFAULT NULL COMMENT '该节点活动效果报告的开始时间', "
+ "\n\t`report_end_time` datetime DEFAULT NULL COMMENT '该节点活动效果报告的结束时间', "
+ "\n\t`cron_rule` varchar(100) DEFAULT NULL COMMENT '周期性营销的时间表达式', "
+ "\n\t`split_rule` varchar(1000) DEFAULT NULL COMMENT '节点拆分规则', "
+ "\n\t`search_json` varchar(5000) DEFAULT NULL COMMENT '索引查找的条件字符串', "
+ "\n\t`filter_json` varchar(1000) DEFAULT NULL COMMENT '各种过滤条件的设置', "
+ "\n\t`buyer_count` int(11) DEFAULT NULL COMMENT '营销的会员数量', "
+ "\n\t`gmt_modified` datetime NOT NULL COMMENT '活动最后修改时间', "
+ "\n\t`gmt_create` datetime NOT NULL COMMENT '活动创建时间', "
+ "\n\tPRIMARY KEY (`id`), "
@@ -132,26 +132,26 @@ public class MySqlCreateTableTest54 extends MysqlTest {
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("create table `t_activity_node` ("
+ "\n\t`id` bigint(20) not null, "
+ "\n\t`sellerId` bigint(20) null, "
+ "\n\t`sellerId` bigint(20) default null, "
+ "\n\t`canvas_id` bigint(20) not null comment '画布ID', "
+ "\n\t`view_node_id` bigint(20) not null comment '对应显示的节点id', "
+ "\n\t`activity_type` int(11) not null comment '活动类型', "
+ "\n\t`node_type` int(11) not null comment '节点类型', "
+ "\n\t`node_title` varchar(200) not null comment '节点标题', "
+ "\n\t`status` int(11) not null default '0' comment '页面的显示状态', "
+ "\n\t`update_status` int(11) null comment '节点创建后的修改状态', "
+ "\n\t`execute_status` int(11) null comment '节点当前的执行状态', "
+ "\n\t`start_time` datetime null comment '该节点活动的开始时间', "
+ "\n\t`end_time` datetime null comment '该节点活动的结束时间', "
+ "\n\t`activity_start_time` datetime null comment '营销活动的开始时间', "
+ "\n\t`activity_end_time` datetime null comment '营销活动的结束时间', "
+ "\n\t`report_start_time` datetime null comment '该节点活动效果报告的开始时间', "
+ "\n\t`report_end_time` datetime null comment '该节点活动效果报告的结束时间', "
+ "\n\t`cron_rule` varchar(100) null comment '周期性营销的时间表达式', "
+ "\n\t`split_rule` varchar(1000) null comment '节点拆分规则', "
+ "\n\t`search_json` varchar(5000) null comment '索引查找的条件字符串', "
+ "\n\t`filter_json` varchar(1000) null comment '各种过滤条件的设置', "
+ "\n\t`buyer_count` int(11) null comment '营销的会员数量', "
+ "\n\t`update_status` int(11) default null comment '节点创建后的修改状态', "
+ "\n\t`execute_status` int(11) default null comment '节点当前的执行状态', "
+ "\n\t`start_time` datetime default null comment '该节点活动的开始时间', "
+ "\n\t`end_time` datetime default null comment '该节点活动的结束时间', "
+ "\n\t`activity_start_time` datetime default null comment '营销活动的开始时间', "
+ "\n\t`activity_end_time` datetime default null comment '营销活动的结束时间', "
+ "\n\t`report_start_time` datetime default null comment '该节点活动效果报告的开始时间', "
+ "\n\t`report_end_time` datetime default null comment '该节点活动效果报告的结束时间', "
+ "\n\t`cron_rule` varchar(100) default null comment '周期性营销的时间表达式', "
+ "\n\t`split_rule` varchar(1000) default null comment '节点拆分规则', "
+ "\n\t`search_json` varchar(5000) default null comment '索引查找的条件字符串', "
+ "\n\t`filter_json` varchar(1000) default null comment '各种过滤条件的设置', "
+ "\n\t`buyer_count` int(11) default null comment '营销的会员数量', "
+ "\n\t`gmt_modified` datetime not null comment '活动最后修改时间', "
+ "\n\t`gmt_create` datetime not null comment '活动创建时间', "
+ "\n\tprimary key (`id`), "
@@ -40,7 +40,7 @@ public class MySqlCreateTableTest61 extends MysqlTest {
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("CREATE TABLE t ("
+ "\n\tpk int PRIMARY KEY AUTO_INCREMENT, "
+ "\n\ta timestamp DEFAULT current_timestamp ON UPDATE current_timestamp, "
+ "\n\ta timestamp NULL DEFAULT current_timestamp ON UPDATE current_timestamp, "
+ "\n\tb timestamp NULL"
+ "\n)", output);
}
@@ -48,7 +48,7 @@ public class MySqlCreateTableTest61 extends MysqlTest {
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("create table t ("
+ "\n\tpk int primary key auto_increment, "
+ "\n\ta timestamp default current_timestamp on update current_timestamp, "
+ "\n\ta timestamp null default current_timestamp on update current_timestamp, "
+ "\n\tb timestamp null"
+ "\n)", output);
}
@@ -39,13 +39,13 @@ public class MySqlCreateTableTest62 extends MysqlTest {
{
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("CREATE TABLE a ("
+ "\n\tb varchar(15) CHARACTER SET latin1 NULL"
+ "\n\tb varchar(15) CHARACTER SET latin1 DEFAULT NULL"
+ "\n)", output);
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("create table a ("
+ "\n\tb varchar(15) character set latin1 null"
+ "\n\tb varchar(15) character set latin1 default null"
+ "\n)", output);
}
}
@@ -65,11 +65,11 @@ public class MySqlCreateTableTest70 extends MysqlTest {
+ "\n\t`id` bigint(20) NOT NULL AUTO_INCREMENT, "
+ "\n\t`created_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, "
+ "\n\t`created_date` datetime NOT NULL, "
+ "\n\t`last_modified_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL, "
+ "\n\t`last_modified_date` datetime NULL, "
+ "\n\t`last_modified_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, "
+ "\n\t`last_modified_date` datetime NULL DEFAULT NULL, "
+ "\n\t`version` bigint(20) NOT NULL, "
+ "\n\t`device_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, "
+ "\n\t`customer_info` bigint(20) NULL, "
+ "\n\t`customer_info` bigint(20) NULL DEFAULT NULL, "
+ "\n\tPRIMARY KEY (`id`), "
+ "\n\tFOREIGN KEY (`customer_info`) REFERENCES `app_customer_info` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, "
+ "\n\tINDEX `fk_app_customer_info_id` USING BTREE(`customer_info`), "
@@ -83,11 +83,11 @@ public class MySqlCreateTableTest70 extends MysqlTest {
+ "\n\t`id` bigint(20) not null auto_increment, "
+ "\n\t`created_by` varchar(50) character set utf8 collate utf8_general_ci not null, "
+ "\n\t`created_date` datetime not null, "
+ "\n\t`last_modified_by` varchar(50) character set utf8 collate utf8_general_ci null, "
+ "\n\t`last_modified_date` datetime null, "
+ "\n\t`last_modified_by` varchar(50) character set utf8 collate utf8_general_ci null default null, "
+ "\n\t`last_modified_date` datetime null default null, "
+ "\n\t`version` bigint(20) not null, "
+ "\n\t`device_id` varchar(20) character set utf8 collate utf8_general_ci not null, "
+ "\n\t`customer_info` bigint(20) null, "
+ "\n\t`customer_info` bigint(20) null default null, "
+ "\n\tprimary key (`id`), "
+ "\n\tforeign key (`customer_info`) references `app_customer_info` (`id`) on delete restrict on update restrict, "
+ "\n\tindex `fk_app_customer_info_id` using BTREE(`customer_info`), "
@@ -42,7 +42,7 @@ public class MySqlHintStatementTest extends TestCase {
+ "\n"
+ "\nCREATE TABLE `item_similarity` ("
+ "\n\t`id` bigint(20) UNSIGNED NOT NULL, "
+ "\n\t`sellerId` bigint(20) NULL, "
+ "\n\t`sellerId` bigint(20) DEFAULT NULL, "
+ "\n\tPRIMARY KEY (`id`)"
+ "\n) ENGINE = InnoDB CHARSET = utf8;"
+ "\n"
@@ -51,7 +51,7 @@ public class PGSetTest extends PGTest {
// System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
Assert.assertEquals(1, visitor.getColumns().size());
Assert.assertEquals(0, visitor.getColumns().size());
String mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, JdbcUtils.POSTGRESQL);
System.out.println(mergedSql);
@@ -45,7 +45,7 @@ public class SQLServerAlterTableTest_10 extends TestCase {
String output = SQLUtils.toSQLString(stmt, JdbcConstants.SQL_SERVER);
Assert.assertEquals("ALTER TABLE dbo.doc_exc"
+ "\n\tADD (column_b VARCHAR(20) DEFAULT NULL CONSTRAINT exb_unique UNIQUE)", output);
+ "\n\tADD (column_b VARCHAR(20) NULL CONSTRAINT exb_unique UNIQUE)", output);
Assert.assertEquals(1, visitor.getTables().size());
Assert.assertEquals(1, visitor.getColumns().size());
@@ -44,7 +44,7 @@ public class SQLServerAlterTableTest_7 extends TestCase {
String output = SQLUtils.toSQLString(stmt, JdbcConstants.SQL_SERVER);
Assert.assertEquals("ALTER TABLE dbo.doc_exa"//
+ "\n\tADD (column_b VARCHAR(20) DEFAULT NULL)", output);
+ "\n\tADD (column_b VARCHAR(20) NULL)", output);
Assert.assertEquals(1, visitor.getTables().size());
Assert.assertEquals(1, visitor.getColumns().size());