h2-create语句流程分析

1
stat.execute("create table test(id int primary key, name varchar(255))");

总流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//解析生成Command
CommandInterface command = conn.prepareCommand(sql, fetchSize);
boolean lazy = false;
boolean returnsResultSet;
synchronized (session) {
setExecutingStatement(command);
try {
if (command.isQuery()) {
returnsResultSet = true;
boolean scrollable = resultSetType != ResultSet.TYPE_FORWARD_ONLY;
boolean updatable = resultSetConcurrency == ResultSet.CONCUR_UPDATABLE;
ResultInterface result = command.executeQuery(maxRows, scrollable);
lazy = result.isLazy();
resultSet = new JdbcResultSet(conn, this, command, result, id,
closedByResultSet, scrollable, updatable);
} else {
returnsResultSet = false;
//执行Command命令
ResultWithGeneratedKeys result = command.executeUpdate(
conn.scopeGeneratedKeys() ? null : generatedKeysRequest);
updateCount = result.getUpdateCount();
ResultInterface gk = result.getGeneratedKeys();
if (gk != null) {
generatedKeys = new JdbcResultSet(conn, this, command, gk, id,
false, true, false);
}
}
} finally {
if (!lazy) {
setExecutingStatement(null);
}
}
}

主要就是两步:

  • 解析sql语句生成Command
  • 执行Command命令

解析sql语句生成Command

1
2
3
4
5
6
org.h2.command.Parser#prepareCommand
->org.h2.command.Parser#parse(java.lang.String)
->org.h2.command.Parser#parsePrepared(这一步解析出是create语句)
->org.h2.command.Parser#parseCreate
->org.h2.command.Parser#parseCreateTable
->org.h2.command.Parser#parseTableColumnDefinition
  • org.h2.command.Parser#parseCreateTable这一步会新建一个CreateTable对象
1
2
3
4
5
6
7
8
9
//获取schema 构建创建sql语句
Schema schema = getSchema();
CreateTable command = new CreateTable(session, schema);
command.setPersistIndexes(persistIndexes);
command.setTemporary(temp);
command.setGlobalTemporary(globalTemp);
command.setIfNotExists(ifNotExists);
command.setTableName(tableName);
command.setComment(readCommentIf());

这个Schema就是创建DataBase对象时生成的PUBLIC Schema

  • org.h2.command.Parser#parseTableColumnDefinition这一步会解析出列-Column对象
1
2
3
4
5
6
7
8
9
10
11
12
13
Column column = parseColumnForTable(columnName, true, true);
if (column.isAutoIncrement() && column.isPrimaryKey()) {
column.setPrimaryKey(false);
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = column.getName();
AlterTableAddConstraint pk = new AlterTableAddConstraint(
session, schema, false);
pk.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY);
pk.setTableName(tableName);
pk.setIndexColumns(cols);
command.addConstraintCommand(pk);
}
command.addColumn(column);

这里最重要的是往 CreateTable 的columns 变量添加column。最终会返回一个CreateTable的Command

执行update命令

1
2
3
org.h2.command.Command#executeUpdate
->org.h2.command.CommandContainer#update
->org.h2.command.ddl.CreateTable#update
  • org.h2.command.CommandContainer#update这步会新建一个表对象-Table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
changePrimaryKeysToNotNull(data.columns);
data.id = getObjectId();
data.create = create;
data.session = session;
//根据schema创建table
Table table = getSchema().createTable(data);

ArrayList<Sequence> sequences = generateSequences(data.columns, data.temporary);
table.setComment(comment);
if (isSessionTemporary) {
if (onCommitDrop) {
table.setOnCommitDrop(true);
}
if (onCommitTruncate) {
table.setOnCommitTruncate(true);
}
session.addLocalTempTable(table);
} else {
db.lockMeta(session);
db.addSchemaObject(session, table);
}

其中db.addSchemaObject(session, table); 会往PUBLIC这个Schema的变量tablesAndViews(类型为ConcurrentHashMap)出入变量:

  • key: TEST
  • value: 对应的建表语句生成的Table对象

表对象有了,接下来的insert语句会去PUBLIC这个Schema根据key找对应表对象