Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
a7b6996b
提交
a7b6996b
authored
1月 09, 2018
作者:
Owner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Checkstyle and codeStyle fixes
上级
ee84407d
隐藏空白字符变更
内嵌
并排
正在显示
17 个修改的文件
包含
271 行增加
和
300 行删除
+271
-300
Parser.java
h2/src/main/org/h2/command/Parser.java
+81
-82
CreateView.java
h2/src/main/org/h2/command/ddl/CreateView.java
+4
-6
DropView.java
h2/src/main/org/h2/command/ddl/DropView.java
+3
-3
Delete.java
h2/src/main/org/h2/command/dml/Delete.java
+4
-5
MergeUsing.java
h2/src/main/org/h2/command/dml/MergeUsing.java
+2
-2
Select.java
h2/src/main/org/h2/command/dml/Select.java
+7
-8
Database.java
h2/src/main/org/h2/engine/Database.java
+12
-12
Session.java
h2/src/main/org/h2/engine/Session.java
+5
-5
ViewIndex.java
h2/src/main/org/h2/index/ViewIndex.java
+0
-1
MVTable.java
h2/src/main/org/h2/mvstore/db/MVTable.java
+23
-24
TableView.java
h2/src/main/org/h2/table/TableView.java
+18
-18
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+1
-1
AbstractBaseForCommonTableExpressions.java
...org/h2/test/db/AbstractBaseForCommonTableExpressions.java
+16
-14
TestGeneralCommonTableQueries.java
...rc/test/org/h2/test/db/TestGeneralCommonTableQueries.java
+55
-79
TestPersistentCommonTableExpressions.java
.../org/h2/test/db/TestPersistentCommonTableExpressions.java
+25
-27
TestMvccMultiThreaded2.java
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded2.java
+12
-10
TestMathUtils.java
h2/src/test/org/h2/test/unit/TestMathUtils.java
+3
-3
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
a7b6996b
...
@@ -170,6 +170,8 @@ import org.h2.value.ValueTimestampTimeZone;
...
@@ -170,6 +170,8 @@ import org.h2.value.ValueTimestampTimeZone;
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
*/
public
class
Parser
{
public
class
Parser
{
public
static
final
String
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
=
"WITH statement supports only SELECT, CREATE TABLE, INSERT, UPDATE, MERGE or DELETE statements"
;
// used during the tokenizer phase
// used during the tokenizer phase
private
static
final
int
CHAR_END
=
1
,
CHAR_VALUE
=
2
,
CHAR_QUOTED
=
3
;
private
static
final
int
CHAR_END
=
1
,
CHAR_VALUE
=
2
,
CHAR_QUOTED
=
3
;
...
@@ -197,9 +199,7 @@ public class Parser {
...
@@ -197,9 +199,7 @@ public class Parser {
return
o1
==
o2
?
0
:
compareTableFilters
(
o1
,
o2
);
return
o1
==
o2
?
0
:
compareTableFilters
(
o1
,
o2
);
}
}
};
};
public
static
final
String
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
=
"WITH statement supports only SELECT, CREATE TABLE, INSERT, UPDATE, MERGE or DELETE statements"
;
private
final
Database
database
;
private
final
Database
database
;
private
final
Session
session
;
private
final
Session
session
;
/**
/**
...
@@ -722,7 +722,7 @@ public class Parser {
...
@@ -722,7 +722,7 @@ public class Parser {
*
*
*/
*/
private
Schema
getSchemaWithDefault
()
{
private
Schema
getSchemaWithDefault
()
{
if
(
schemaName
==
null
)
{
if
(
schemaName
==
null
)
{
schemaName
=
session
.
getCurrentSchemaName
();
schemaName
=
session
.
getCurrentSchemaName
();
}
}
return
getSchema
(
schemaName
);
return
getSchema
(
schemaName
);
...
@@ -845,13 +845,13 @@ public class Parser {
...
@@ -845,13 +845,13 @@ public class Parser {
currentSelect
,
orderInFrom
,
null
);
currentSelect
,
orderInFrom
,
null
);
}
}
private
TableFilter
readSimpleTableFilterWithAliasExcludes
(
int
orderInFrom
,
Collection
<
String
>
excludeTokens
)
{
private
TableFilter
readSimpleTableFilterWithAliasExcludes
(
int
orderInFrom
,
Collection
<
String
>
excludeTokens
)
{
Table
table
=
readTableOrView
();
Table
table
=
readTableOrView
();
String
alias
=
null
;
String
alias
=
null
;
if
(
readIf
(
"AS"
))
{
if
(
readIf
(
"AS"
))
{
alias
=
readAliasIdentifier
();
alias
=
readAliasIdentifier
();
}
else
if
(
currentTokenType
==
IDENTIFIER
)
{
}
else
if
(
currentTokenType
==
IDENTIFIER
)
{
if
(!
equalsTokenIgnoreCase
(
currentToken
,
"SET"
)
&&
!
isTokenInList
(
excludeTokens
))
{
if
(!
equalsTokenIgnoreCase
(
currentToken
,
"SET"
)
&&
!
isTokenInList
(
excludeTokens
))
{
// SET is not a keyword (PostgreSQL supports it as a table name)
// SET is not a keyword (PostgreSQL supports it as a table name)
alias
=
readAliasIdentifier
();
alias
=
readAliasIdentifier
();
}
}
...
@@ -1080,13 +1080,13 @@ public class Parser {
...
@@ -1080,13 +1080,13 @@ public class Parser {
currentPrepared
=
command
;
currentPrepared
=
command
;
int
start
=
lastParseIndex
;
int
start
=
lastParseIndex
;
read
(
"INTO"
);
read
(
"INTO"
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"USING"
,
"KEY"
,
"VALUES"
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"USING"
,
"KEY"
,
"VALUES"
);
TableFilter
targetTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
TableFilter
targetTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
command
.
setTargetTableFilter
(
targetTableFilter
);
command
.
setTargetTableFilter
(
targetTableFilter
);
Table
table
=
command
.
getTargetTable
();
Table
table
=
command
.
getTargetTable
();
if
(
readIf
(
"USING"
)){
if
(
readIf
(
"USING"
))
{
return
parseMergeUsing
(
command
,
start
);
return
parseMergeUsing
(
command
,
start
);
}
}
if
(
readIf
(
"("
))
{
if
(
readIf
(
"("
))
{
if
(
isSelect
())
{
if
(
isSelect
())
{
...
@@ -1147,20 +1147,19 @@ public class Parser {
...
@@ -1147,20 +1147,19 @@ public class Parser {
temporarySourceTableView
,
command
.
getQueryAlias
(),
temporarySourceTableView
,
command
.
getQueryAlias
(),
rightsChecked
,
(
Select
)
command
.
getQuery
(),
0
,
null
);
rightsChecked
,
(
Select
)
command
.
getQuery
(),
0
,
null
);
command
.
setSourceTableFilter
(
sourceTableFilter
);
command
.
setSourceTableFilter
(
sourceTableFilter
);
}
}
else
{
else
{
/* Its a table name, simulate a query by building a select query for the table */
/* Its a table name, simulate a query by building a select query for the table */
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"ON"
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"ON"
);
TableFilter
sourceTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
TableFilter
sourceTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
command
.
setSourceTableFilter
(
sourceTableFilter
);
command
.
setSourceTableFilter
(
sourceTableFilter
);
StringBuilder
buff
=
new
StringBuilder
(
StringBuilder
buff
=
new
StringBuilder
(
"SELECT * FROM "
+
sourceTableFilter
.
getTable
().
getName
());
"SELECT * FROM "
+
sourceTableFilter
.
getTable
().
getName
());
if
(
sourceTableFilter
.
getTableAlias
()!=
null
)
{
if
(
sourceTableFilter
.
getTableAlias
()
!=
null
)
{
buff
.
append
(
" AS "
+
sourceTableFilter
.
getTableAlias
());
buff
.
append
(
" AS "
+
sourceTableFilter
.
getTableAlias
());
}
}
Prepared
preparedQuery
=
prepare
(
session
,
buff
.
toString
(),
null
/*paramValues*/
);
Prepared
preparedQuery
=
prepare
(
session
,
buff
.
toString
(),
null
/*paramValues*/
);
command
.
setQuery
((
Select
)
preparedQuery
);
command
.
setQuery
((
Select
)
preparedQuery
);
}
}
read
(
"ON"
);
read
(
"ON"
);
...
@@ -1169,27 +1168,27 @@ public class Parser {
...
@@ -1169,27 +1168,27 @@ public class Parser {
command
.
setOnCondition
(
condition
);
command
.
setOnCondition
(
condition
);
read
(
")"
);
read
(
")"
);
if
(
readIfAll
(
"WHEN"
,
"MATCHED"
,
"THEN"
))
{
if
(
readIfAll
(
"WHEN"
,
"MATCHED"
,
"THEN"
))
{
int
startMatched
=
lastParseIndex
;
int
startMatched
=
lastParseIndex
;
if
(
readIf
(
"UPDATE"
)){
if
(
readIf
(
"UPDATE"
))
{
Update
updateCommand
=
new
Update
(
session
);
Update
updateCommand
=
new
Update
(
session
);
//currentPrepared = updateCommand;
//currentPrepared = updateCommand;
TableFilter
filter
=
command
.
getTargetTableFilter
();
TableFilter
filter
=
command
.
getTargetTableFilter
();
updateCommand
.
setTableFilter
(
filter
);
updateCommand
.
setTableFilter
(
filter
);
parseUpdateSetClause
(
updateCommand
,
filter
,
startMatched
);
parseUpdateSetClause
(
updateCommand
,
filter
,
startMatched
);
command
.
setUpdateCommand
(
updateCommand
);
command
.
setUpdateCommand
(
updateCommand
);
}
}
startMatched
=
lastParseIndex
;
startMatched
=
lastParseIndex
;
if
(
readIf
(
"DELETE"
)){
if
(
readIf
(
"DELETE"
))
{
Delete
deleteCommand
=
new
Delete
(
session
);
Delete
deleteCommand
=
new
Delete
(
session
);
TableFilter
filter
=
command
.
getTargetTableFilter
();
TableFilter
filter
=
command
.
getTargetTableFilter
();
deleteCommand
.
setTableFilter
(
filter
);
deleteCommand
.
setTableFilter
(
filter
);
parseDeleteGivenTable
(
deleteCommand
,
null
,
startMatched
);
parseDeleteGivenTable
(
deleteCommand
,
null
,
startMatched
);
command
.
setDeleteCommand
(
deleteCommand
);
command
.
setDeleteCommand
(
deleteCommand
);
}
}
}
}
if
(
readIfAll
(
"WHEN"
,
"NOT"
,
"MATCHED"
,
"THEN"
))
{
if
(
readIfAll
(
"WHEN"
,
"NOT"
,
"MATCHED"
,
"THEN"
))
{
if
(
readIf
(
"INSERT"
)){
if
(
readIf
(
"INSERT"
))
{
Insert
insertCommand
=
new
Insert
(
session
);
Insert
insertCommand
=
new
Insert
(
session
);
insertCommand
.
setTable
(
command
.
getTargetTable
());
insertCommand
.
setTable
(
command
.
getTargetTable
());
parseInsertGivenTable
(
insertCommand
,
command
.
getTargetTable
());
parseInsertGivenTable
(
insertCommand
,
command
.
getTargetTable
());
...
@@ -1222,7 +1221,7 @@ public class Parser {
...
@@ -1222,7 +1221,7 @@ public class Parser {
Table
table
=
readTableOrView
();
Table
table
=
readTableOrView
();
command
.
setTable
(
table
);
command
.
setTable
(
table
);
Insert
returnedCommand
=
parseInsertGivenTable
(
command
,
table
);
Insert
returnedCommand
=
parseInsertGivenTable
(
command
,
table
);
if
(
returnedCommand
!=
null
)
{
if
(
returnedCommand
!=
null
)
{
return
returnedCommand
;
return
returnedCommand
;
}
}
if
(
database
.
getMode
().
onDuplicateKeyUpdate
)
{
if
(
database
.
getMode
().
onDuplicateKeyUpdate
)
{
...
@@ -1453,7 +1452,7 @@ public class Parser {
...
@@ -1453,7 +1452,7 @@ public class Parser {
}
}
}
}
// inherit alias for CTE as views from table name
// inherit alias for CTE as views from table name
if
(
table
.
isView
()
&&
table
.
isTableExpression
()
&&
alias
==
null
)
{
if
(
table
.
isView
()
&&
table
.
isTableExpression
()
&&
alias
==
null
)
{
alias
=
table
.
getName
();
alias
=
table
.
getName
();
}
}
return
new
TableFilter
(
session
,
table
,
alias
,
rightsChecked
,
return
new
TableFilter
(
session
,
table
,
alias
,
rightsChecked
,
...
@@ -1489,7 +1488,7 @@ public class Parser {
...
@@ -1489,7 +1488,7 @@ public class Parser {
private
String
readFromAlias
(
String
alias
)
{
private
String
readFromAlias
(
String
alias
)
{
// left and right are not keywords (because they are functions as
// left and right are not keywords (because they are functions as
// well)
// well)
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"LEFT"
,
"RIGHT"
,
"FULL"
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"LEFT"
,
"RIGHT"
,
"FULL"
);
return
readFromAlias
(
alias
,
excludeIdentifiers
);
return
readFromAlias
(
alias
,
excludeIdentifiers
);
}
}
...
@@ -1942,7 +1941,7 @@ public class Parser {
...
@@ -1942,7 +1941,7 @@ public class Parser {
params
.
add
(
parameters
.
get
(
i
));
params
.
add
(
parameters
.
get
(
i
));
}
}
command
.
setParameterList
(
params
);
command
.
setParameterList
(
params
);
if
(
command
instanceof
Query
)
{
if
(
command
instanceof
Query
)
{
Query
query
=
(
Query
)
command
;
Query
query
=
(
Query
)
command
;
query
.
init
();
query
.
init
();
}
}
...
@@ -2134,8 +2133,7 @@ public class Parser {
...
@@ -2134,8 +2133,7 @@ public class Parser {
Query
query
=
null
;
Query
query
=
null
;
try
{
try
{
query
=
(
Query
)
parseWith
();
query
=
(
Query
)
parseWith
();
}
}
catch
(
ClassCastException
e
)
{
catch
(
ClassCastException
e
){
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
"WITH statement supports only SELECT (query) in this context"
);
"WITH statement supports only SELECT (query) in this context"
);
}
}
...
@@ -3493,8 +3491,8 @@ public class Parser {
...
@@ -3493,8 +3491,8 @@ public class Parser {
* Reads passed token in list, in order and returns true on first match.
* Reads passed token in list, in order and returns true on first match.
* If none of the token matches returns false
* If none of the token matches returns false
*/
*/
private
boolean
readIfOr
(
String
...
tokens
)
{
private
boolean
readIfOr
(
String
...
tokens
)
{
for
(
String
token:
tokens
)
{
for
(
String
token:
tokens
)
{
if
(
readIf
(
token
))
{
if
(
readIf
(
token
))
{
return
true
;
return
true
;
}
}
...
@@ -3506,14 +3504,13 @@ public class Parser {
...
@@ -3506,14 +3504,13 @@ public class Parser {
* Reads every token in list, in order - returns true if all are found.
* Reads every token in list, in order - returns true if all are found.
* If any are not found, returns false - AND resets parsing back to state when called.
* If any are not found, returns false - AND resets parsing back to state when called.
*/
*/
private
boolean
readIfAll
(
String
...
tokens
)
{
private
boolean
readIfAll
(
String
...
tokens
)
{
// save parse location in case we have to fail this test
// save parse location in case we have to fail this test
int
start
=
lastParseIndex
;
int
start
=
lastParseIndex
;
for
(
String
token:
tokens
)
{
for
(
String
token:
tokens
)
{
if
(!
currentTokenQuoted
&&
equalsToken
(
token
,
currentToken
))
{
if
(!
currentTokenQuoted
&&
equalsToken
(
token
,
currentToken
))
{
read
();
read
();
}
}
else
{
else
{
// read failed - revert parse location to before when called
// read failed - revert parse location to before when called
parseIndex
=
start
;
parseIndex
=
start
;
read
();
read
();
...
@@ -3555,7 +3552,7 @@ public class Parser {
...
@@ -3555,7 +3552,7 @@ public class Parser {
return
false
;
return
false
;
}
}
private
boolean
isTokenInList
(
Collection
<
String
>
upperCaseTokenList
){
private
boolean
isTokenInList
(
Collection
<
String
>
upperCaseTokenList
)
{
String
upperCaseCurrentToken
=
currentToken
.
toUpperCase
();
String
upperCaseCurrentToken
=
currentToken
.
toUpperCase
();
return
upperCaseTokenList
.
contains
(
upperCaseCurrentToken
);
return
upperCaseTokenList
.
contains
(
upperCaseCurrentToken
);
}
}
...
@@ -4515,7 +4512,7 @@ public class Parser {
...
@@ -4515,7 +4512,7 @@ public class Parser {
String
enumerator0
=
readString
();
String
enumerator0
=
readString
();
enumeratorList
.
add
(
enumerator0
);
enumeratorList
.
add
(
enumerator0
);
original
+=
"'"
+
enumerator0
+
"'"
;
original
+=
"'"
+
enumerator0
+
"'"
;
while
(
readIf
(
","
))
{
while
(
readIf
(
","
))
{
original
+=
','
;
original
+=
','
;
String
enumeratorN
=
readString
();
String
enumeratorN
=
readString
();
original
+=
"'"
+
enumeratorN
+
"'"
;
original
+=
"'"
+
enumeratorN
+
"'"
;
...
@@ -4527,7 +4524,7 @@ public class Parser {
...
@@ -4527,7 +4524,7 @@ public class Parser {
}
}
try
{
try
{
ValueEnum
.
check
(
enumerators
);
ValueEnum
.
check
(
enumerators
);
}
catch
(
DbException
e
)
{
}
catch
(
DbException
e
)
{
throw
e
.
addSQL
(
original
);
throw
e
.
addSQL
(
original
);
}
}
}
else
if
(
readIf
(
"("
))
{
}
else
if
(
readIf
(
"("
))
{
...
@@ -5165,7 +5162,7 @@ public class Parser {
...
@@ -5165,7 +5162,7 @@ public class Parser {
// this WITH statement is not a temporary view - it is part of a persistent view
// this WITH statement is not a temporary view - it is part of a persistent view
// as in CREATE VIEW abc AS WITH my_cte - this auto detects that condition
// as in CREATE VIEW abc AS WITH my_cte - this auto detects that condition
if
(
session
.
isParsingCreateView
())
{
if
(
session
.
isParsingCreateView
())
{
isPersistent
=
true
;
isPersistent
=
true
;
}
}
...
@@ -5180,45 +5177,39 @@ public class Parser {
...
@@ -5180,45 +5177,39 @@ public class Parser {
// used in setCteCleanups
// used in setCteCleanups
Collections
.
reverse
(
viewsCreated
);
Collections
.
reverse
(
viewsCreated
);
if
(
isToken
(
"SELECT"
))
{
if
(
isToken
(
"SELECT"
))
{
Query
query
=
parseSelectUnion
();
Query
query
=
parseSelectUnion
();
query
.
setPrepareAlways
(
true
);
query
.
setPrepareAlways
(
true
);
query
.
setNeverLazy
(
true
);
query
.
setNeverLazy
(
true
);
p
=
query
;
p
=
query
;
}
}
else
if
(
readIf
(
"INSERT"
))
{
else
if
(
readIf
(
"INSERT"
))
{
p
=
parseInsert
();
p
=
parseInsert
();
p
.
setPrepareAlways
(
true
);
p
.
setPrepareAlways
(
true
);
}
}
else
if
(
readIf
(
"UPDATE"
))
{
else
if
(
readIf
(
"UPDATE"
))
{
p
=
parseUpdate
();
p
=
parseUpdate
();
p
.
setPrepareAlways
(
true
);
p
.
setPrepareAlways
(
true
);
}
}
else
if
(
readIf
(
"MERGE"
))
{
else
if
(
readIf
(
"MERGE"
))
{
p
=
parseMerge
();
p
=
parseMerge
();
p
.
setPrepareAlways
(
true
);
p
.
setPrepareAlways
(
true
);
}
}
else
if
(
readIf
(
"DELETE"
))
{
else
if
(
readIf
(
"DELETE"
))
{
p
=
parseDelete
();
p
=
parseDelete
();
p
.
setPrepareAlways
(
true
);
p
.
setPrepareAlways
(
true
);
}
}
else
if
(
readIf
(
"CREATE"
))
{
else
if
(
readIf
(
"CREATE"
))
{
if
(!
isToken
(
"TABLE"
))
{
if
(!
isToken
(
"TABLE"
)){
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
);
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
);
}
}
p
=
parseCreate
();
p
=
parseCreate
();
p
.
setPrepareAlways
(
true
);
p
.
setPrepareAlways
(
true
);
}
}
else
{
else
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
);
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
);
}
}
// clean up temporary views starting with last to first (in case of
// clean up temporary views starting with last to first (in case of
// dependencies) - but only if they are not persistent
// dependencies) - but only if they are not persistent
if
(!
isPersistent
)
{
if
(!
isPersistent
)
{
p
.
setCteCleanups
(
viewsCreated
);
p
.
setCteCleanups
(
viewsCreated
);
}
}
return
p
;
return
p
;
...
@@ -5227,7 +5218,7 @@ public class Parser {
...
@@ -5227,7 +5218,7 @@ public class Parser {
private
TableView
parseSingleCommonTableExpression
(
boolean
isPersistent
)
{
private
TableView
parseSingleCommonTableExpression
(
boolean
isPersistent
)
{
String
cteViewName
=
readIdentifierWithSchema
();
String
cteViewName
=
readIdentifierWithSchema
();
Schema
schema
=
getSchema
();
Schema
schema
=
getSchema
();
Table
recursiveTable
=
null
;
Table
recursiveTable
=
null
;
ArrayList
<
Column
>
columns
=
New
.
arrayList
();
ArrayList
<
Column
>
columns
=
New
.
arrayList
();
String
[]
cols
=
null
;
String
[]
cols
=
null
;
Database
db
=
session
.
getDatabase
();
Database
db
=
session
.
getDatabase
();
...
@@ -5244,10 +5235,9 @@ public class Parser {
...
@@ -5244,10 +5235,9 @@ public class Parser {
}
}
Table
oldViewFound
=
null
;
Table
oldViewFound
=
null
;
if
(
isPersistent
)
{
if
(
isPersistent
)
{
oldViewFound
=
getSchema
().
findTableOrView
(
session
,
cteViewName
);
oldViewFound
=
getSchema
().
findTableOrView
(
session
,
cteViewName
);
}
}
else
{
else
{
oldViewFound
=
session
.
findLocalTempTable
(
cteViewName
);
oldViewFound
=
session
.
findLocalTempTable
(
cteViewName
);
}
}
// this persistent check conflicts with check 10 lines down
// this persistent check conflicts with check 10 lines down
...
@@ -5261,21 +5251,21 @@ public class Parser {
...
@@ -5261,21 +5251,21 @@ public class Parser {
throw
DbException
.
get
(
ErrorCode
.
TABLE_OR_VIEW_ALREADY_EXISTS_1
,
throw
DbException
.
get
(
ErrorCode
.
TABLE_OR_VIEW_ALREADY_EXISTS_1
,
cteViewName
);
cteViewName
);
}
}
if
(
isPersistent
)
{
if
(
isPersistent
)
{
oldViewFound
.
lock
(
session
,
true
,
true
);
oldViewFound
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
oldViewFound
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
oldViewFound
);
}
else
{
}
else
{
session
.
removeLocalTempTable
(
oldViewFound
);
session
.
removeLocalTempTable
(
oldViewFound
);
}
}
oldViewFound
=
null
;
oldViewFound
=
null
;
}
}
// this table is created as a work around because recursive
// this table is created as a work around because recursive
// table expressions need to reference something that look like
// table expressions need to reference something that look like
// themselves
// themselves
// to work (its removed after creation in this method)
// to work (its removed after creation in this method)
// only create table data and table if we don't have a working CTE already
// only create table data and table if we don't have a working CTE already
if
(
oldViewFound
==
null
)
{
if
(
oldViewFound
==
null
)
{
recursiveTable
=
TableView
.
createShadowTableForRecursiveTableExpression
(
isPersistent
,
session
,
cteViewName
,
recursiveTable
=
TableView
.
createShadowTableForRecursiveTableExpression
(
isPersistent
,
session
,
cteViewName
,
schema
,
columns
,
db
);
schema
,
columns
,
db
);
}
}
...
@@ -5285,7 +5275,7 @@ public class Parser {
...
@@ -5285,7 +5275,7 @@ public class Parser {
read
(
"AS"
);
read
(
"AS"
);
read
(
"("
);
read
(
"("
);
Query
withQuery
=
parseSelect
();
Query
withQuery
=
parseSelect
();
if
(
isPersistent
)
{
if
(
isPersistent
)
{
withQuery
.
session
=
session
;
withQuery
.
session
=
session
;
}
}
read
(
")"
);
read
(
")"
);
...
@@ -5316,16 +5306,16 @@ public class Parser {
...
@@ -5316,16 +5306,16 @@ public class Parser {
// it twice - once without the flag set, and if we didn't see a recursive term,
// it twice - once without the flag set, and if we didn't see a recursive term,
// then we just compile it again.
// then we just compile it again.
TableView
view
;
TableView
view
;
synchronized
(
targetSession
)
{
synchronized
(
targetSession
)
{
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
parameters
,
columnTemplateArray
,
targetSession
,
parameters
,
columnTemplateArray
,
targetSession
,
allowRecursiveQueryDetection
,
false
/* literalsChecked */
,
true
/* isTableExpression */
,
isPersistent
);
allowRecursiveQueryDetection
,
false
/* literalsChecked */
,
true
/* isTableExpression */
,
isPersistent
);
if
(!
view
.
isRecursiveQueryDetected
()
&&
allowRecursiveQueryDetection
)
{
if
(!
view
.
isRecursiveQueryDetected
()
&&
allowRecursiveQueryDetection
)
{
if
(
isPersistent
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
targetSession
,
view
);
db
.
addSchemaObject
(
targetSession
,
view
);
view
.
lock
(
targetSession
,
true
,
true
);
view
.
lock
(
targetSession
,
true
,
true
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
view
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
view
);
}
else
{
}
else
{
session
.
removeLocalTempTable
(
view
);
session
.
removeLocalTempTable
(
view
);
}
}
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
parameters
,
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
parameters
,
...
@@ -5339,13 +5329,12 @@ public class Parser {
...
@@ -5339,13 +5329,12 @@ public class Parser {
view
.
setTemporary
(!
isPersistent
);
view
.
setTemporary
(!
isPersistent
);
view
.
setHidden
(
true
);
view
.
setHidden
(
true
);
view
.
setOnCommitDrop
(
false
);
view
.
setOnCommitDrop
(
false
);
if
(
addViewToSession
)
{
if
(
addViewToSession
)
{
if
(
isPersistent
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
targetSession
,
view
);
db
.
addSchemaObject
(
targetSession
,
view
);
view
.
unlock
(
targetSession
);
view
.
unlock
(
targetSession
);
db
.
unlockMeta
(
targetSession
);
db
.
unlockMeta
(
targetSession
);
}
}
else
{
else
{
targetSession
.
addLocalTempTable
(
view
);
targetSession
.
addLocalTempTable
(
view
);
}
}
}
}
...
@@ -5373,12 +5362,12 @@ public class Parser {
...
@@ -5373,12 +5362,12 @@ public class Parser {
read
(
"AS"
);
read
(
"AS"
);
try
{
try
{
Query
query
;
Query
query
;
session
.
setParsingCreateView
(
true
,
viewName
);
session
.
setParsingCreateView
(
true
,
viewName
);
try
{
try
{
query
=
parseSelect
();
query
=
parseSelect
();
query
.
prepare
();
query
.
prepare
();
}
finally
{
}
finally
{
session
.
setParsingCreateView
(
false
,
viewName
);
session
.
setParsingCreateView
(
false
,
viewName
);
}
}
command
.
setSelect
(
query
);
command
.
setSelect
(
query
);
}
catch
(
DbException
e
)
{
}
catch
(
DbException
e
)
{
...
@@ -6118,7 +6107,8 @@ public class Parser {
...
@@ -6118,7 +6107,8 @@ public class Parser {
command
.
setType
(
CommandInterface
.
ALTER_TABLE_DROP_COLUMN
);
command
.
setType
(
CommandInterface
.
ALTER_TABLE_DROP_COLUMN
);
ArrayList
<
Column
>
columnsToRemove
=
New
.
arrayList
();
ArrayList
<
Column
>
columnsToRemove
=
New
.
arrayList
();
Table
table
=
tableIfTableExists
(
schema
,
tableName
,
ifTableExists
);
Table
table
=
tableIfTableExists
(
schema
,
tableName
,
ifTableExists
);
boolean
openingBracketDetected
=
readIf
(
"("
);
// For Oracle compatibility - open bracket required
// For Oracle compatibility - open bracket required
boolean
openingBracketDetected
=
readIf
(
"("
);
do
{
do
{
String
columnName
=
readColumnIdentifier
();
String
columnName
=
readColumnIdentifier
();
if
(
table
==
null
)
{
if
(
table
==
null
)
{
...
@@ -6131,7 +6121,8 @@ public class Parser {
...
@@ -6131,7 +6121,8 @@ public class Parser {
columnsToRemove
.
add
(
column
);
columnsToRemove
.
add
(
column
);
}
while
(
readIf
(
","
));
}
while
(
readIf
(
","
));
if
(
openingBracketDetected
)
{
if
(
openingBracketDetected
)
{
read
(
")"
);
// For Oracle compatibility - close bracket
// For Oracle compatibility - close bracket
read
(
")"
);
}
}
command
.
setTableName
(
tableName
);
command
.
setTableName
(
tableName
);
command
.
setIfTableExists
(
ifTableExists
);
command
.
setIfTableExists
(
ifTableExists
);
...
@@ -6155,8 +6146,8 @@ public class Parser {
...
@@ -6155,8 +6146,8 @@ public class Parser {
command
.
setNewColumnName
(
newColumnName
);
command
.
setNewColumnName
(
newColumnName
);
return
command
;
return
command
;
}
else
if
(
readIf
(
"MODIFY"
))
{
}
else
if
(
readIf
(
"MODIFY"
))
{
// MySQL compatibility
// MySQL compatibility
(optional)
readIf
(
"COLUMN"
);
// optional
readIf
(
"COLUMN"
);
String
columnName
=
readColumnIdentifier
();
String
columnName
=
readColumnIdentifier
();
AlterTableAlterColumn
command
=
null
;
AlterTableAlterColumn
command
=
null
;
NullConstraintType
nullConstraint
=
parseNotNullConstraint
();
NullConstraintType
nullConstraint
=
parseNotNullConstraint
();
...
@@ -6759,13 +6750,16 @@ public class Parser {
...
@@ -6759,13 +6750,16 @@ public class Parser {
return
command
;
return
command
;
}
}
private
enum
NullConstraintType
{
/**
* Enumeration describing null constraints
*/
private
enum
NullConstraintType
{
NULL_IS_ALLOWED
,
NULL_IS_NOT_ALLOWED
,
NO_NULL_CONSTRAINT_FOUND
NULL_IS_ALLOWED
,
NULL_IS_NOT_ALLOWED
,
NO_NULL_CONSTRAINT_FOUND
}
}
private
NullConstraintType
parseNotNullConstraint
()
{
private
NullConstraintType
parseNotNullConstraint
()
{
NullConstraintType
nullConstraint
=
NullConstraintType
.
NO_NULL_CONSTRAINT_FOUND
;
NullConstraintType
nullConstraint
=
NullConstraintType
.
NO_NULL_CONSTRAINT_FOUND
;
if
(
(
isToken
(
"NOT"
)
||
isToken
(
"NULL"
)
))
{
if
(
isToken
(
"NOT"
)
||
isToken
(
"NULL"
))
{
if
(
readIf
(
"NOT"
))
{
if
(
readIf
(
"NOT"
))
{
read
(
"NULL"
);
read
(
"NULL"
);
nullConstraint
=
NullConstraintType
.
NULL_IS_NOT_ALLOWED
;
nullConstraint
=
NullConstraintType
.
NULL_IS_NOT_ALLOWED
;
...
@@ -6775,15 +6769,20 @@ public class Parser {
...
@@ -6775,15 +6769,20 @@ public class Parser {
}
}
if
(
database
.
getMode
().
getEnum
()
==
ModeEnum
.
Oracle
)
{
if
(
database
.
getMode
().
getEnum
()
==
ModeEnum
.
Oracle
)
{
if
(
readIf
(
"ENABLE"
))
{
if
(
readIf
(
"ENABLE"
))
{
readIf
(
"VALIDATE"
);
// Leave constraint 'as is'
// Leave constraint 'as is'
if
(
readIf
(
"NOVALIDATE"
))
{
// Turn off constraint, allow NULLs
readIf
(
"VALIDATE"
);
// Turn off constraint, allow NULLs
if
(
readIf
(
"NOVALIDATE"
))
{
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
}
}
}
}
if
(
readIf
(
"DISABLE"
))
{
// Turn off constraint, allow NULLs
// Turn off constraint, allow NULLs
if
(
readIf
(
"DISABLE"
))
{
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
readIf
(
"VALIDATE"
);
// ignore validate
// ignore validate
readIf
(
"NOVALIDATE"
);
// ignore novalidate
readIf
(
"VALIDATE"
);
// ignore novalidate
readIf
(
"NOVALIDATE"
);
}
}
}
}
}
}
...
...
h2/src/main/org/h2/command/ddl/CreateView.java
浏览文件 @
a7b6996b
...
@@ -73,7 +73,7 @@ public class CreateView extends SchemaCommand {
...
@@ -73,7 +73,7 @@ public class CreateView extends SchemaCommand {
}
}
public
void
setTableExpression
(
boolean
isTableExpression
)
{
public
void
setTableExpression
(
boolean
isTableExpression
)
{
this
.
isTableExpression
=
isTableExpression
;
this
.
isTableExpression
=
isTableExpression
;
}
}
@Override
@Override
...
@@ -116,11 +116,9 @@ public class CreateView extends SchemaCommand {
...
@@ -116,11 +116,9 @@ public class CreateView extends SchemaCommand {
}
}
}
}
if
(
view
==
null
)
{
if
(
view
==
null
)
{
if
(
isTableExpression
){
if
(
isTableExpression
)
{
view
=
TableView
.
createTableViewMaybeRecursive
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsStrings
,
session
,
false
/* literalsChecked */
,
isTableExpression
,
true
/*isPersistent*/
,
db
);
view
=
TableView
.
createTableViewMaybeRecursive
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsStrings
,
session
,
false
/* literalsChecked */
,
isTableExpression
,
true
/*isPersistent*/
,
db
);
}
}
else
{
else
{
view
=
new
TableView
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsUnknowns
,
session
,
false
/* allow recursive */
,
false
/* literalsChecked */
,
isTableExpression
,
true
);
view
=
new
TableView
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsUnknowns
,
session
,
false
/* allow recursive */
,
false
/* literalsChecked */
,
isTableExpression
,
true
);
}
}
}
else
{
}
else
{
...
...
h2/src/main/org/h2/command/ddl/DropView.java
浏览文件 @
a7b6996b
...
@@ -79,10 +79,10 @@ public class DropView extends SchemaCommand {
...
@@ -79,10 +79,10 @@ public class DropView extends SchemaCommand {
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
// remove dependent table expressions
// remove dependent table expressions
for
(
Table
childTable:
copyOfDependencies
)
{
for
(
Table
childTable:
copyOfDependencies
)
{
if
(
TableType
.
VIEW
==
childTable
.
getTableType
())
{
if
(
TableType
.
VIEW
==
childTable
.
getTableType
())
{
TableView
childTableView
=
(
TableView
)
childTable
;
TableView
childTableView
=
(
TableView
)
childTable
;
if
(
childTableView
.
isTableExpression
()
&&
childTableView
.
getName
()!=
null
)
{
if
(
childTableView
.
isTableExpression
()
&&
childTableView
.
getName
()
!=
null
)
{
session
.
getDatabase
().
removeSchemaObject
(
session
,
childTableView
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
childTableView
);
}
}
}
}
...
...
h2/src/main/org/h2/command/dml/Delete.java
浏览文件 @
a7b6996b
...
@@ -53,7 +53,7 @@ public class Delete extends Prepared {
...
@@ -53,7 +53,7 @@ public class Delete extends Prepared {
this
.
condition
=
condition
;
this
.
condition
=
condition
;
}
}
public
Expression
getCondition
(
)
{
public
Expression
getCondition
()
{
return
this
.
condition
;
return
this
.
condition
;
}
}
...
@@ -136,17 +136,16 @@ public class Delete extends Prepared {
...
@@ -136,17 +136,16 @@ public class Delete extends Prepared {
public
void
prepare
()
{
public
void
prepare
()
{
if
(
condition
!=
null
)
{
if
(
condition
!=
null
)
{
condition
.
mapColumns
(
targetTableFilter
,
0
);
condition
.
mapColumns
(
targetTableFilter
,
0
);
if
(
sourceTableFilter
!=
null
)
{
if
(
sourceTableFilter
!=
null
)
{
condition
.
mapColumns
(
sourceTableFilter
,
0
);
condition
.
mapColumns
(
sourceTableFilter
,
0
);
}
}
condition
=
condition
.
optimize
(
session
);
condition
=
condition
.
optimize
(
session
);
condition
.
createIndexConditions
(
session
,
targetTableFilter
);
condition
.
createIndexConditions
(
session
,
targetTableFilter
);
}
}
TableFilter
[]
filters
;
TableFilter
[]
filters
;
if
(
sourceTableFilter
==
null
)
{
if
(
sourceTableFilter
==
null
)
{
filters
=
new
TableFilter
[]
{
targetTableFilter
};
filters
=
new
TableFilter
[]
{
targetTableFilter
};
}
}
else
{
else
{
filters
=
new
TableFilter
[]
{
targetTableFilter
,
sourceTableFilter
};
filters
=
new
TableFilter
[]
{
targetTableFilter
,
sourceTableFilter
};
}
}
PlanItem
item
=
targetTableFilter
.
getBestPlanItem
(
session
,
filters
,
0
,
PlanItem
item
=
targetTableFilter
.
getBestPlanItem
(
session
,
filters
,
0
,
...
...
h2/src/main/org/h2/command/dml/MergeUsing.java
浏览文件 @
a7b6996b
...
@@ -112,11 +112,11 @@ public class MergeUsing extends Prepared {
...
@@ -112,11 +112,11 @@ public class MergeUsing extends Prepared {
private
Delete
deleteCommand
;
private
Delete
deleteCommand
;
private
Insert
insertCommand
;
private
Insert
insertCommand
;
private
String
queryAlias
;
private
String
queryAlias
;
private
int
countUpdatedRows
=
0
;
private
int
countUpdatedRows
;
private
Column
[]
sourceKeys
;
private
Column
[]
sourceKeys
;
private
Select
targetMatchQuery
;
private
Select
targetMatchQuery
;
private
HashMap
<
Value
,
Integer
>
targetRowidsRemembered
=
new
HashMap
<>();
private
HashMap
<
Value
,
Integer
>
targetRowidsRemembered
=
new
HashMap
<>();
private
int
sourceQueryRowNumber
=
0
;
private
int
sourceQueryRowNumber
;
public
MergeUsing
(
Merge
merge
)
{
public
MergeUsing
(
Merge
merge
)
{
super
(
merge
.
getSession
());
super
(
merge
.
getSession
());
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
a7b6996b
...
@@ -840,14 +840,14 @@ public class Select extends Query {
...
@@ -840,14 +840,14 @@ public class Select extends Query {
sort
=
prepareOrder
(
orderList
,
expressions
.
size
());
sort
=
prepareOrder
(
orderList
,
expressions
.
size
());
orderList
=
null
;
orderList
=
null
;
}
}
ColumnNamer
columnNamer
=
new
ColumnNamer
(
session
);
ColumnNamer
columnNamer
=
new
ColumnNamer
(
session
);
for
(
int
i
=
0
;
i
<
expressions
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
expressions
.
size
();
i
++)
{
Expression
e
=
expressions
.
get
(
i
);
Expression
e
=
expressions
.
get
(
i
);
String
proposedColumnName
=
e
.
getAlias
();
String
proposedColumnName
=
e
.
getAlias
();
String
columnName
=
columnNamer
.
getColumnName
(
e
,
i
,
proposedColumnName
);
String
columnName
=
columnNamer
.
getColumnName
(
e
,
i
,
proposedColumnName
);
// if the name changed, create an alias
// if the name changed, create an alias
if
(!
columnName
.
equals
(
proposedColumnName
))
{
if
(!
columnName
.
equals
(
proposedColumnName
))
{
e
=
new
Alias
(
e
,
columnName
,
true
);
e
=
new
Alias
(
e
,
columnName
,
true
);
}
}
expressions
.
set
(
i
,
e
.
optimize
(
session
));
expressions
.
set
(
i
,
e
.
optimize
(
session
));
}
}
...
@@ -1087,14 +1087,13 @@ public class Select extends Query {
...
@@ -1087,14 +1087,13 @@ public class Select extends Query {
for
(
TableFilter
f
:
topFilters
)
{
for
(
TableFilter
f
:
topFilters
)
{
Table
t
=
f
.
getTable
();
Table
t
=
f
.
getTable
();
TableView
tableView
=
(
t
instanceof
TableView
)
?
(
TableView
)
t
:
null
;
TableView
tableView
=
(
t
instanceof
TableView
)
?
(
TableView
)
t
:
null
;
if
(
tableView
!=
null
&&
tableView
.
isRecursive
()
&&
tableView
.
isTableExpression
())
{
if
(
tableView
!=
null
&&
tableView
.
isRecursive
()
&&
tableView
.
isTableExpression
())
{
if
(
tableView
.
isPersistent
())
{
if
(
tableView
.
isPersistent
())
{
// skip the generation of plan SQL for this already recursive persistent ctes, since using a with
// skip the generation of plan SQL for this already recursive persistent ctes, since using a with
// statement will re-create the common table expression views.
// statement will re-create the common table expression views.
continue
;
continue
;
}
}
else
{
else
{
buff
.
append
(
"WITH RECURSIVE "
).
append
(
t
.
getName
()).
append
(
'('
);
buff
.
append
(
"WITH RECURSIVE "
).
append
(
t
.
getName
()).
append
(
'('
);
buff
.
resetCount
();
buff
.
resetCount
();
for
(
Column
c
:
t
.
getColumns
())
{
for
(
Column
c
:
t
.
getColumns
())
{
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
a7b6996b
...
@@ -90,6 +90,9 @@ import org.h2.value.ValueInt;
...
@@ -90,6 +90,9 @@ import org.h2.value.ValueInt;
public
class
Database
implements
DataHandler
{
public
class
Database
implements
DataHandler
{
private
static
int
initialPowerOffCount
;
private
static
int
initialPowerOffCount
;
private
static
final
ThreadLocal
<
Session
>
META_LOCK_DEBUGGING
=
new
ThreadLocal
<
Session
>();
private
static
final
ThreadLocal
<
Throwable
>
META_LOCK_DEBUGGING_STACK
=
new
ThreadLocal
<
Throwable
>();
/**
/**
* The default name of the system user. This name is only used as long as
* The default name of the system user. This name is only used as long as
...
@@ -296,7 +299,7 @@ public class Database implements DataHandler {
...
@@ -296,7 +299,7 @@ public class Database implements DataHandler {
e
.
fillInStackTrace
();
e
.
fillInStackTrace
();
}
}
boolean
alreadyOpen
=
e
instanceof
DbException
boolean
alreadyOpen
=
e
instanceof
DbException
&&
((
DbException
)
e
).
getErrorCode
()
==
ErrorCode
.
DATABASE_ALREADY_OPEN_1
;
&&
((
DbException
)
e
).
getErrorCode
()
==
ErrorCode
.
DATABASE_ALREADY_OPEN_1
;
if
(
alreadyOpen
)
{
if
(
alreadyOpen
)
{
stopServer
();
stopServer
();
}
}
...
@@ -899,10 +902,7 @@ public class Database implements DataHandler {
...
@@ -899,10 +902,7 @@ public class Database implements DataHandler {
}
}
}
}
private
static
final
ThreadLocal
<
Session
>
metaLockDebugging
=
new
ThreadLocal
<
Session
>();
/**
private
static
final
ThreadLocal
<
Throwable
>
metaLockDebuggingStack
=
new
ThreadLocal
<
Throwable
>();
/**
* Lock the metadata table for updates.
* Lock the metadata table for updates.
*
*
* @param session the session
* @param session the session
...
@@ -917,13 +917,13 @@ public class Database implements DataHandler {
...
@@ -917,13 +917,13 @@ public class Database implements DataHandler {
return
true
;
return
true
;
}
}
if
(
SysProperties
.
CHECK2
)
{
if
(
SysProperties
.
CHECK2
)
{
final
Session
prev
=
metaLockDebugging
.
get
();
final
Session
prev
=
META_LOCK_DEBUGGING
.
get
();
if
(
prev
==
null
)
{
if
(
prev
==
null
)
{
metaLockDebugging
.
set
(
session
);
META_LOCK_DEBUGGING
.
set
(
session
);
metaLockDebuggingStack
.
set
(
new
Throwable
(
"Last meta lock granted in this stack trace, "
+
META_LOCK_DEBUGGING_STACK
.
set
(
new
Throwable
(
"Last meta lock granted in this stack trace, "
+
"this is debug information for following IllegalStateException"
));
"this is debug information for following IllegalStateException"
));
}
else
if
(
prev
!=
session
)
{
}
else
if
(
prev
!=
session
)
{
metaLockDebuggingStack
.
get
().
printStackTrace
();
META_LOCK_DEBUGGING_STACK
.
get
().
printStackTrace
();
throw
new
IllegalStateException
(
"meta currently locked by "
throw
new
IllegalStateException
(
"meta currently locked by "
+
prev
+
", sessionid="
+
prev
.
getId
()
+
prev
+
", sessionid="
+
prev
.
getId
()
+
" and trying to be locked by different session, "
+
" and trying to be locked by different session, "
...
@@ -953,9 +953,9 @@ public class Database implements DataHandler {
...
@@ -953,9 +953,9 @@ public class Database implements DataHandler {
*/
*/
public
void
unlockMetaDebug
(
Session
session
)
{
public
void
unlockMetaDebug
(
Session
session
)
{
if
(
SysProperties
.
CHECK2
)
{
if
(
SysProperties
.
CHECK2
)
{
if
(
metaLockDebugging
.
get
()
==
session
)
{
if
(
META_LOCK_DEBUGGING
.
get
()
==
session
)
{
metaLockDebugging
.
set
(
null
);
META_LOCK_DEBUGGING
.
set
(
null
);
metaLockDebuggingStack
.
set
(
null
);
META_LOCK_DEBUGGING_STACK
.
set
(
null
);
}
}
}
}
}
}
...
...
h2/src/main/org/h2/engine/Session.java
浏览文件 @
a7b6996b
...
@@ -232,16 +232,15 @@ public class Session extends SessionWithState {
...
@@ -232,16 +232,15 @@ public class Session extends SessionWithState {
// It can be recursive, thus implemented as counter.
// It can be recursive, thus implemented as counter.
this
.
parsingView
+=
parsingView
?
1
:
-
1
;
this
.
parsingView
+=
parsingView
?
1
:
-
1
;
assert
this
.
parsingView
>=
0
;
assert
this
.
parsingView
>=
0
;
if
(
parsingView
)
{
if
(
parsingView
)
{
viewNameStack
.
push
(
viewName
);
viewNameStack
.
push
(
viewName
);
}
else
}
else
{
{
assert
viewName
.
equals
(
viewNameStack
.
peek
());
assert
viewName
.
equals
(
viewNameStack
.
peek
());
viewNameStack
.
pop
();
viewNameStack
.
pop
();
}
}
}
}
public
String
getParsingCreateViewName
()
{
public
String
getParsingCreateViewName
()
{
if
(
viewNameStack
.
size
()==
0
)
{
if
(
viewNameStack
.
size
()
==
0
)
{
return
null
;
return
null
;
}
}
return
viewNameStack
.
peek
();
return
viewNameStack
.
peek
();
...
@@ -694,7 +693,8 @@ public class Session extends SessionWithState {
...
@@ -694,7 +693,8 @@ public class Session extends SessionWithState {
for
(
Table
table
:
tablesToAnalyze
)
{
for
(
Table
table
:
tablesToAnalyze
)
{
Analyze
.
analyzeTable
(
this
,
table
,
rows
,
false
);
Analyze
.
analyzeTable
(
this
,
table
,
rows
,
false
);
}
}
database
.
unlockMeta
(
this
);
// analyze can lock the meta
// analyze can lock the meta
database
.
unlockMeta
(
this
);
}
}
tablesToAnalyze
=
null
;
tablesToAnalyze
=
null
;
}
}
...
...
h2/src/main/org/h2/index/ViewIndex.java
浏览文件 @
a7b6996b
...
@@ -6,7 +6,6 @@
...
@@ -6,7 +6,6 @@
package
org
.
h2
.
index
;
package
org
.
h2
.
index
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.HashSet
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
...
...
h2/src/main/org/h2/mvstore/db/MVTable.java
浏览文件 @
a7b6996b
...
@@ -48,11 +48,24 @@ import org.h2.value.Value;
...
@@ -48,11 +48,24 @@ import org.h2.value.Value;
* A table stored in a MVStore.
* A table stored in a MVStore.
*/
*/
public
class
MVTable
extends
TableBase
{
public
class
MVTable
extends
TableBase
{
/**
* The table name this thread is waiting to lock.
*/
public
static
final
DebuggingThreadLocal
<
String
>
WAITING_FOR_LOCK
;
private
static
final
String
NO_EXTRA_INFO
=
""
;
/**
* The table names this thread has exclusively locked.
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
EXCLUSIVE_LOCKS
;
// lock event types for tracing...
/**
* The tables names this thread has a shared lock on.
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
SHARED_LOCKS
;
/**
* The type of trace lock events
*/
private
enum
TraceLockEvent
{
private
enum
TraceLockEvent
{
TRACE_LOCK_OK
(
"ok"
),
TRACE_LOCK_OK
(
"ok"
),
...
@@ -62,33 +75,19 @@ public class MVTable extends TableBase {
...
@@ -62,33 +75,19 @@ public class MVTable extends TableBase {
TRACE_LOCK_UNLOCK
(
"unlock"
),
TRACE_LOCK_UNLOCK
(
"unlock"
),
TRACE_LOCK_ADDED_FOR
(
"added for"
),
TRACE_LOCK_ADDED_FOR
(
"added for"
),
TRACE_LOCK_ADD_UPGRADED_FOR
(
"add (upgraded) for "
);
TRACE_LOCK_ADD_UPGRADED_FOR
(
"add (upgraded) for "
);
private
TraceLockEvent
(
String
eventText
){
private
final
String
eventText
;
TraceLockEvent
(
String
eventText
)
{
this
.
eventText
=
eventText
;
this
.
eventText
=
eventText
;
}
}
private
final
String
eventText
;
public
String
getEventText
()
{
public
String
getEventText
(){
return
eventText
;
return
eventText
;
}
}
}
}
private
static
final
String
NO_EXTRA_INFO
=
""
;
/**
* The table name this thread is waiting to lock.
*/
public
static
final
DebuggingThreadLocal
<
String
>
WAITING_FOR_LOCK
;
/**
* The table names this thread has exclusively locked.
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
EXCLUSIVE_LOCKS
;
/**
* The tables names this thread has a shared lock on.
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
SHARED_LOCKS
;
static
{
static
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<>();
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<>();
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
a7b6996b
...
@@ -112,18 +112,18 @@ public class TableView extends Table {
...
@@ -112,18 +112,18 @@ public class TableView extends Table {
private
Query
compileViewQuery
(
Session
session
,
String
sql
,
boolean
literalsChecked
,
String
viewName
)
{
private
Query
compileViewQuery
(
Session
session
,
String
sql
,
boolean
literalsChecked
,
String
viewName
)
{
Prepared
p
;
Prepared
p
;
session
.
setParsingCreateView
(
true
,
viewName
);
session
.
setParsingCreateView
(
true
,
viewName
);
try
{
try
{
p
=
session
.
prepare
(
sql
,
false
,
literalsChecked
);
p
=
session
.
prepare
(
sql
,
false
,
literalsChecked
);
}
finally
{
}
finally
{
session
.
setParsingCreateView
(
false
,
viewName
);
session
.
setParsingCreateView
(
false
,
viewName
);
}
}
if
(!(
p
instanceof
Query
))
{
if
(!(
p
instanceof
Query
))
{
throw
DbException
.
getSyntaxError
(
sql
,
0
);
throw
DbException
.
getSyntaxError
(
sql
,
0
);
}
}
Query
q
=
(
Query
)
p
;
Query
q
=
(
Query
)
p
;
// only potentially recursive cte queries need to be non-lazy
// only potentially recursive cte queries need to be non-lazy
if
(
isTableExpression
&&
allowRecursive
)
{
if
(
isTableExpression
&&
allowRecursive
)
{
q
.
setNeverLazy
(
true
);
q
.
setNeverLazy
(
true
);
}
}
return
q
;
return
q
;
...
@@ -183,7 +183,7 @@ public class TableView extends Table {
...
@@ -183,7 +183,7 @@ public class TableView extends Table {
if
(
name
==
null
)
{
if
(
name
==
null
)
{
name
=
expr
.
getAlias
();
name
=
expr
.
getAlias
();
}
}
name
=
columnNamer
.
getColumnName
(
expr
,
i
,
name
);
name
=
columnNamer
.
getColumnName
(
expr
,
i
,
name
);
if
(
type
==
Value
.
UNKNOWN
)
{
if
(
type
==
Value
.
UNKNOWN
)
{
type
=
expr
.
getType
();
type
=
expr
.
getType
();
}
}
...
@@ -455,7 +455,7 @@ public class TableView extends Table {
...
@@ -455,7 +455,7 @@ public class TableView extends Table {
@Override
@Override
public
String
getSQL
()
{
public
String
getSQL
()
{
if
(
isTemporary
()
&&
querySQL
!=
null
)
{
if
(
isTemporary
()
&&
querySQL
!=
null
)
{
return
"(\n"
+
StringUtils
.
indent
(
querySQL
)
+
")"
;
return
"(\n"
+
StringUtils
.
indent
(
querySQL
)
+
")"
;
}
}
return
super
.
getSQL
();
return
super
.
getSQL
();
...
@@ -707,7 +707,7 @@ public class TableView extends Table {
...
@@ -707,7 +707,7 @@ public class TableView extends Table {
return
true
;
return
true
;
}
}
public
List
<
Table
>
getTables
(){
public
List
<
Table
>
getTables
()
{
return
tables
;
return
tables
;
}
}
...
@@ -717,7 +717,7 @@ public class TableView extends Table {
...
@@ -717,7 +717,7 @@ public class TableView extends Table {
public
static
TableView
createTableViewMaybeRecursive
(
Schema
schema
,
int
id
,
String
name
,
String
querySQL
,
public
static
TableView
createTableViewMaybeRecursive
(
Schema
schema
,
int
id
,
String
name
,
String
querySQL
,
ArrayList
<
Parameter
>
parameters
,
Column
[]
columnTemplates
,
Session
session
,
ArrayList
<
Parameter
>
parameters
,
Column
[]
columnTemplates
,
Session
session
,
boolean
literalsChecked
,
boolean
isTableExpression
,
boolean
isPersistent
,
Database
db
){
boolean
literalsChecked
,
boolean
isTableExpression
,
boolean
isPersistent
,
Database
db
)
{
Table
recursiveTable
=
TableView
.
createShadowTableForRecursiveTableExpression
(
isPersistent
,
session
,
name
,
Table
recursiveTable
=
TableView
.
createShadowTableForRecursiveTableExpression
(
isPersistent
,
session
,
name
,
...
@@ -726,13 +726,13 @@ public class TableView extends Table {
...
@@ -726,13 +726,13 @@ public class TableView extends Table {
List
<
Column
>
columnTemplateList
;
List
<
Column
>
columnTemplateList
;
String
[]
querySQLOutput
=
new
String
[]{
null
};
String
[]
querySQLOutput
=
new
String
[]{
null
};
ArrayList
<
String
>
columnNames
=
new
ArrayList
<
String
>();
ArrayList
<
String
>
columnNames
=
new
ArrayList
<
String
>();
for
(
Column
columnTemplate:
columnTemplates
)
{
for
(
Column
columnTemplate:
columnTemplates
)
{
columnNames
.
add
(
columnTemplate
.
getName
());
columnNames
.
add
(
columnTemplate
.
getName
());
}
}
try
{
try
{
Prepared
withQuery
=
session
.
prepare
(
querySQL
,
false
,
false
);
Prepared
withQuery
=
session
.
prepare
(
querySQL
,
false
,
false
);
if
(
isPersistent
)
{
if
(
isPersistent
)
{
withQuery
.
setSession
(
session
);
withQuery
.
setSession
(
session
);
}
}
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
columnNames
.
toArray
(
new
String
[
1
]),
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
columnNames
.
toArray
(
new
String
[
1
]),
...
@@ -745,11 +745,11 @@ public class TableView extends Table {
...
@@ -745,11 +745,11 @@ public class TableView extends Table {
// build with recursion turned on
// build with recursion turned on
TableView
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
TableView
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
parameters
,
columnTemplateList
.
toArray
(
columnTemplates
),
session
,
parameters
,
columnTemplateList
.
toArray
(
columnTemplates
),
session
,
true
/* try recursive */
,
literalsChecked
,
isTableExpression
,
isPersistent
);
true
/* try recursive */
,
literalsChecked
,
isTableExpression
,
isPersistent
);
// is recursion really detected ? if not - recreate it without recursion flag and no recursive index
// is recursion really detected ? if not - recreate it without recursion flag and no recursive index
if
(!
view
.
isRecursiveQueryDetected
())
{
if
(!
view
.
isRecursiveQueryDetected
())
{
if
(
isPersistent
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
session
,
view
);
db
.
addSchemaObject
(
session
,
view
);
view
.
lock
(
session
,
true
,
true
);
view
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
...
@@ -757,7 +757,7 @@ public class TableView extends Table {
...
@@ -757,7 +757,7 @@ public class TableView extends Table {
// during database startup - this method does not normally get called - and it needs to be
// during database startup - this method does not normally get called - and it needs to be
// to correctly un-register the table which the table expression uses...
// to correctly un-register the table which the table expression uses...
view
.
removeChildrenAndResources
(
session
);
view
.
removeChildrenAndResources
(
session
);
}
else
{
}
else
{
session
.
removeLocalTempTable
(
view
);
session
.
removeLocalTempTable
(
view
);
}
}
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
parameters
,
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
parameters
,
...
@@ -795,7 +795,7 @@ public class TableView extends Table {
...
@@ -795,7 +795,7 @@ public class TableView extends Table {
// use the passed in column name if supplied, otherwise use alias
// use the passed in column name if supplied, otherwise use alias
// (if found) otherwise use column name derived from column
// (if found) otherwise use column name derived from column
// expression
// expression
String
columnName
=
columnNamer
.
getColumnName
(
columnExp
,
i
,
cols
);
String
columnName
=
columnNamer
.
getColumnName
(
columnExp
,
i
,
cols
);
columnTemplateList
.
add
(
new
Column
(
columnName
,
columnTemplateList
.
add
(
new
Column
(
columnName
,
columnExp
.
getType
()));
columnExp
.
getType
()));
...
@@ -820,13 +820,13 @@ public class TableView extends Table {
...
@@ -820,13 +820,13 @@ public class TableView extends Table {
// this gets a meta table lock that is not released
// this gets a meta table lock that is not released
Table
recursiveTable
=
schema
.
createTable
(
recursiveTableData
);
Table
recursiveTable
=
schema
.
createTable
(
recursiveTableData
);
if
(
isPersistent
)
{
if
(
isPersistent
)
{
// this unlock is to prevent lock leak from schema.createTable()
// this unlock is to prevent lock leak from schema.createTable()
db
.
unlockMeta
(
targetSession
);
db
.
unlockMeta
(
targetSession
);
synchronized
(
targetSession
)
{
synchronized
(
targetSession
)
{
db
.
addSchemaObject
(
targetSession
,
recursiveTable
);
db
.
addSchemaObject
(
targetSession
,
recursiveTable
);
}
}
}
else
{
}
else
{
targetSession
.
addLocalTempTable
(
recursiveTable
);
targetSession
.
addLocalTempTable
(
recursiveTable
);
}
}
return
recursiveTable
;
return
recursiveTable
;
...
@@ -834,12 +834,12 @@ public class TableView extends Table {
...
@@ -834,12 +834,12 @@ public class TableView extends Table {
public
static
void
destroyShadowTableForRecursiveExpression
(
boolean
isPersistent
,
Session
targetSession
,
public
static
void
destroyShadowTableForRecursiveExpression
(
boolean
isPersistent
,
Session
targetSession
,
Table
recursiveTable
)
{
Table
recursiveTable
)
{
if
(
recursiveTable
!=
null
)
{
if
(
recursiveTable
!=
null
)
{
if
(
isPersistent
)
{
if
(
isPersistent
)
{
recursiveTable
.
lock
(
targetSession
,
true
,
true
);
recursiveTable
.
lock
(
targetSession
,
true
,
true
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
recursiveTable
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
recursiveTable
);
}
else
{
}
else
{
targetSession
.
removeLocalTempTable
(
recursiveTable
);
targetSession
.
removeLocalTempTable
(
recursiveTable
);
}
}
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
a7b6996b
...
@@ -763,7 +763,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
...
@@ -763,7 +763,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest
(
new
TestReadOnly
());
addTest
(
new
TestReadOnly
());
addTest
(
new
TestRecursiveQueries
());
addTest
(
new
TestRecursiveQueries
());
addTest
(
new
TestGeneralCommonTableQueries
());
addTest
(
new
TestGeneralCommonTableQueries
());
if
(!
memory
)
{
if
(!
memory
)
{
// requires persistent store for reconnection tests
// requires persistent store for reconnection tests
addTest
(
new
TestPersistentCommonTableExpressions
());
addTest
(
new
TestPersistentCommonTableExpressions
());
}
}
...
...
h2/src/test/org/h2/test/db/AbstractBaseForCommonTableExpressions.java
浏览文件 @
a7b6996b
...
@@ -6,11 +6,13 @@ import java.sql.ResultSet;
...
@@ -6,11 +6,13 @@ import java.sql.ResultSet;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
/**
* Base class for common table expression tests
*/
public
abstract
class
AbstractBaseForCommonTableExpressions
extends
TestBase
{
public
abstract
class
AbstractBaseForCommonTableExpressions
extends
TestBase
{
protected
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
int
expectedNumbeOfRows
,
String
SETUP_
SQL
,
protected
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
int
expectedNumbeOfRows
,
String
setup
SQL
,
String
WITH_QUERY
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
String
withQuery
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
deleteDb
(
"commonTableExpressionQueries"
);
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
...
@@ -18,40 +20,40 @@ public abstract class AbstractBaseForCommonTableExpressions extends TestBase {
...
@@ -18,40 +20,40 @@ public abstract class AbstractBaseForCommonTableExpressions extends TestBase {
ResultSet
rs
;
ResultSet
rs
;
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
Statement
stat
=
conn
.
createStatement
();
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
SETUP_
SQL
);
stat
.
execute
(
setup
SQL
);
stat
.
close
();
stat
.
close
();
// close and re-open connection for one iteration to make sure the query work between connections
// close and re-open connection for one iteration to make sure the query work between connections
if
(
queryRunTries
==
closeAndReopenDatabaseConnectionOnIteration
)
{
if
(
queryRunTries
==
closeAndReopenDatabaseConnectionOnIteration
)
{
conn
.
close
();
conn
.
close
();
conn
=
getConnection
(
"commonTableExpressionQueries"
);
conn
=
getConnection
(
"commonTableExpressionQueries"
);
}
}
prep
=
conn
.
prepareStatement
(
WITH_QUERY
);
prep
=
conn
.
prepareStatement
(
withQuery
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
assertTrue
(
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
!=
null
);
assertTrue
(
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
!=
null
);
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
assertEquals
(
"wrongly type column "
+
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)+
" on iteration#"
+
queryRunTries
,
assertEquals
(
"wrongly type column "
+
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)+
" on iteration#"
+
queryRunTries
,
expectedColumnTypes
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnTypeName
(
columnIndex
));
expectedColumnTypes
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnTypeName
(
columnIndex
));
}
}
int
rowNdx
=
0
;
int
rowNdx
=
0
;
while
(
rs
.
next
())
{
while
(
rs
.
next
())
{
StringBuffer
buf
=
new
StringBuffer
();
StringBuffer
buf
=
new
StringBuffer
();
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
buf
.
append
(
"|"
+
rs
.
getString
(
columnIndex
));
buf
.
append
(
"|"
+
rs
.
getString
(
columnIndex
));
}
}
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
rowNdx
++;
rowNdx
++;
}
}
assertEquals
(
expectedNumbeOfRows
,
rowNdx
);
assertEquals
(
expectedNumbeOfRows
,
rowNdx
);
rs
.
close
();
rs
.
close
();
prep
.
close
();
prep
.
close
();
...
...
h2/src/test/org/h2/test/db/TestGeneralCommonTableQueries.java
浏览文件 @
a7b6996b
...
@@ -55,18 +55,18 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -55,18 +55,18 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
ResultSet
rs
;
ResultSet
rs
;
stat
=
conn
.
createStatement
();
stat
=
conn
.
createStatement
();
final
String
simple
_two_column_q
uery
=
"with "
+
final
String
simple
TwoColumnQ
uery
=
"with "
+
"t1(n) as (select 1 as first) "
+
"t1(n) as (select 1 as first) "
+
",t2(n) as (select 2 as first) "
+
",t2(n) as (select 2 as first) "
+
"select * from t1 union all select * from t2"
;
"select * from t1 union all select * from t2"
;
rs
=
stat
.
executeQuery
(
simple
_two_column_q
uery
);
rs
=
stat
.
executeQuery
(
simple
TwoColumnQ
uery
);
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
assertFalse
(
rs
.
next
());
prep
=
conn
.
prepareStatement
(
simple
_two_column_q
uery
);
prep
=
conn
.
prepareStatement
(
simple
TwoColumnQ
uery
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertEquals
(
1
,
rs
.
getInt
(
1
));
...
@@ -78,7 +78,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -78,7 +78,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
"t1(n) as (select 2 as first) "
+
"t1(n) as (select 2 as first) "
+
",t2(n) as (select 3 as first) "
+
",t2(n) as (select 3 as first) "
+
"select * from t1 union all select * from t2 where n<>?"
);
"select * from t1 union all select * from t2 where n<>?"
);
prep
.
setInt
(
1
,
0
);
// omit no lines since zero is not in list
prep
.
setInt
(
1
,
0
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
@@ -91,7 +92,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -91,7 +92,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
",t2(n) as (select 3 as first) "
+
",t2(n) as (select 3 as first) "
+
",t3(n) as (select 4 as first) "
+
",t3(n) as (select 4 as first) "
+
"select * from t1 union all select * from t2 union all select * from t3 where n<>?"
);
"select * from t1 union all select * from t2 union all select * from t3 where n<>?"
);
prep
.
setInt
(
1
,
4
);
// omit 4 line (last)
prep
.
setInt
(
1
,
4
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
@@ -114,15 +116,16 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -114,15 +116,16 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
",t2 as (select first_col+1 from t1) "
+
",t2 as (select first_col+1 from t1) "
+
",t3 as (select 4 as first_col) "
+
",t3 as (select 4 as first_col) "
+
"select * from t1 union all select * from t2 union all select * from t3 where first_col<>?"
);
"select * from t1 union all select * from t2 union all select * from t3 where first_col<>?"
);
prep
.
setInt
(
1
,
4
);
// omit 4 line (last)
prep
.
setInt
(
1
,
4
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
3
,
rs
.
getInt
(
"FIRST_COL"
));
assertEquals
(
3
,
rs
.
getInt
(
"FIRST_COL"
));
assertFalse
(
rs
.
next
());
assertFalse
(
rs
.
next
());
assertEquals
(
rs
.
getMetaData
().
getColumnCount
(),
1
);
assertEquals
(
rs
.
getMetaData
().
getColumnCount
(),
1
);
assertEquals
(
"FIRST_COL"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"FIRST_COL"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
conn
.
close
();
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
deleteDb
(
"commonTableExpressionQueries"
);
...
@@ -174,7 +177,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -174,7 +177,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
prep
.
setInt
(
6
,
6
);
prep
.
setInt
(
6
,
6
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
for
(
int
n:
new
int
[]{
1
,
2
,
3
,
4
,
5
,
6
}
)
{
for
(
int
n:
new
int
[]{
1
,
2
,
3
,
4
,
5
,
6
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
}
...
@@ -183,7 +186,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -183,7 +186,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
// call it twice
// call it twice
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
for
(
int
n:
new
int
[]{
1
,
2
,
3
,
4
,
5
,
6
}
)
{
for
(
int
n:
new
int
[]{
1
,
2
,
3
,
4
,
5
,
6
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
}
...
@@ -220,21 +223,20 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -220,21 +223,20 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
}
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"'T1'"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertEquals
(
"'T1'"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertFalse
(
rs
.
next
());
assertFalse
(
rs
.
next
());
try
{
try
{
prep
=
conn
.
prepareStatement
(
"SELECT * FROM t1 UNION ALL SELECT * FROM t2 "
+
prep
=
conn
.
prepareStatement
(
"SELECT * FROM t1 UNION ALL SELECT * FROM t2 "
+
"UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(5,6)"
);
"UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(5,6)"
);
rs
=
prep
.
executeQuery
();
rs
=
prep
.
executeQuery
();
fail
(
"Temp view T1 was accessible after previous WITH statement finished "
+
fail
(
"Temp view T1 was accessible after previous WITH statement finished "
+
"- but should not have been."
);
"- but should not have been."
);
}
}
catch
(
JdbcSQLException
e
)
{
catch
(
JdbcSQLException
e
){
// ensure the T1 table has been removed even without auto commit
// ensure the T1 table has been removed even without auto commit
assertContains
(
e
.
getMessage
(),
"Table \"T1\" not found;"
);
assertContains
(
e
.
getMessage
(),
"Table \"T1\" not found;"
);
}
}
conn
.
close
();
conn
.
close
();
...
@@ -293,13 +295,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -293,13 +295,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
prep
.
setInt
(
2
,
2
);
prep
.
setInt
(
2
,
2
);
rowCount
=
prep
.
executeUpdate
();
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
})
{
for
(
int
n
:
new
int
[]
{
1
,
2
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"Y1"
,
rs
.
getString
(
3
));
assertEquals
(
"Y1"
,
rs
.
getString
(
3
));
}
}
...
@@ -324,7 +326,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -324,7 +326,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
+
"DELETE FROM T1 WHERE X IN ( SELECT v1.X FROM v1 )"
);
+
"DELETE FROM T1 WHERE X IN ( SELECT v1.X FROM v1 )"
);
rowCount
=
prep
.
executeUpdate
();
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
...
@@ -351,13 +353,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -351,13 +353,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
+
"MERGE INTO T1 KEY(ID) SELECT v1.X AS ID, v1.X, v1.Y FROM v1"
);
+
"MERGE INTO T1 KEY(ID) SELECT v1.X AS ID, v1.X, v1.Y FROM v1"
);
rowCount
=
prep
.
executeUpdate
();
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
3
,
rowCount
);
assertEquals
(
3
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
}
...
@@ -380,13 +382,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -380,13 +382,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
+
"CREATE TABLE IF NOT EXISTS T1 AS SELECT v1.X AS ID, v1.X, v1.Y FROM v1"
);
+
"CREATE TABLE IF NOT EXISTS T1 AS SELECT v1.X AS ID, v1.X, v1.Y FROM v1"
);
success
=
prep
.
execute
();
success
=
prep
.
execute
();
assertEquals
(
false
,
success
);
assertEquals
(
false
,
success
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
}
...
@@ -435,9 +437,9 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -435,9 +437,9 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
for
(
String
keyLetter
:
new
String
[]
{
"a"
,
"b"
})
{
for
(
String
keyLetter
:
new
String
[]
{
"a"
,
"b"
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
next
());
assertContains
(
"ab"
,
rs
.
getString
(
1
));
assertContains
(
"ab"
,
rs
.
getString
(
1
));
assertEquals
(
rs
.
getString
(
1
),
keyLetter
);
assertEquals
(
rs
.
getString
(
1
),
keyLetter
);
assertTrue
(
rs
.
getInt
(
2
)
!=
0
);
assertTrue
(
rs
.
getInt
(
2
)
!=
0
);
}
}
conn
.
close
();
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
deleteDb
(
"commonTableExpressionQueries"
);
...
@@ -462,10 +464,10 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -462,10 +464,10 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
assertEquals
(
n
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
4
));
assertEquals
(
n
,
rs
.
getInt
(
4
));
}
}
assertEquals
(
"ONE"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"ONE"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"TWO"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertEquals
(
"TWO"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertEquals
(
"THREE"
,
rs
.
getMetaData
().
getColumnLabel
(
3
));
assertEquals
(
"THREE"
,
rs
.
getMetaData
().
getColumnLabel
(
3
));
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
4
));
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
4
));
assertFalse
(
rs
.
next
());
assertFalse
(
rs
.
next
());
...
@@ -475,12 +477,12 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -475,12 +477,12 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
private
void
testSimple4RowRecursiveQuery
()
throws
Exception
{
private
void
testSimple4RowRecursiveQuery
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|1"
,
"|2"
,
"|3"
};
String
[]
expectedRowData
=
new
String
[]{
"|1"
,
"|2"
,
"|3"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"N"
};
String
[]
expectedColumnNames
=
new
String
[]{
"N"
};
String
SETUP_
SQL
=
"-- do nothing"
;
String
setup
SQL
=
"-- do nothing"
;
String
WITH_QUERY
=
"with recursive r(n) as (\n"
+
String
withQuery
=
"with recursive r(n) as (\n"
+
"(select 1) union all (select n+1 from r where n < 3)\n"
+
"(select 1) union all (select n+1 from r where n < 3)\n"
+
")\n"
+
")\n"
+
"select n from r"
;
"select n from r"
;
...
@@ -488,19 +490,19 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -488,19 +490,19 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
private
void
testSimple2By4RowRecursiveQuery
()
throws
Exception
{
private
void
testSimple2By4RowRecursiveQuery
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|0|1|10"
,
"|1|2|11"
,
"|2|3|12"
,
"|3|4|13"
};
String
[]
expectedRowData
=
new
String
[]{
"|0|1|10"
,
"|1|2|11"
,
"|2|3|12"
,
"|3|4|13"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"K"
,
"N"
,
"N2"
};
String
[]
expectedColumnNames
=
new
String
[]{
"K"
,
"N"
,
"N2"
};
String
SETUP_
SQL
=
"-- do nothing"
;
String
setup
SQL
=
"-- do nothing"
;
String
WITH_QUERY
=
"with \n"
+
String
withQuery
=
"with \n"
+
"r1(n,k) as ((select 1, 0) union all (select n+1,k+1 from r1 where n <= 3)),"
+
"r1(n,k) as ((select 1, 0) union all (select n+1,k+1 from r1 where n <= 3)),"
+
"r2(n,k) as ((select 10,0) union all (select n+1,k+1 from r2 where n <= 13))"
+
"r2(n,k) as ((select 10,0) union all (select n+1,k+1 from r2 where n <= 13))"
+
"select r1.k, r1.n, r2.n AS n2 from r1 inner join r2 ON r1.k= r2.k "
;
"select r1.k, r1.n, r2.n AS n2 from r1 inner join r2 ON r1.k= r2.k "
;
...
@@ -508,47 +510,22 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -508,47 +510,22 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
/*
Caused by: java.lang.StackOverflowError
at org.h2.result.LazyResult.reset(LazyResult.java:43)
at org.h2.command.dml.Select$LazyResultSelect.reset(Select.java:1464)
at org.h2.index.ViewIndex.findRecursive(ViewIndex.java:187)
at org.h2.index.ViewIndex.find(ViewIndex.java:284)
at org.h2.index.ViewIndex.find(ViewIndex.java:161)
at org.h2.index.BaseIndex.find(BaseIndex.java:127)
at org.h2.index.IndexCursor.find(IndexCursor.java:169)
at org.h2.table.TableFilter.next(TableFilter.java:468)
at org.h2.command.dml.Select$LazyResultQueryFlat.fetchNextRow(Select.java:1487)
at org.h2.result.LazyResult.hasNext(LazyResult.java:79)
at org.h2.result.LazyResult.next(LazyResult.java:59)
at org.h2.index.ViewCursor.next(ViewCursor.java:49)
at org.h2.index.IndexCursor.next(IndexCursor.java:309)
at org.h2.table.TableFilter.next(TableFilter.java:499)
at org.h2.command.dml.Select$LazyResultQueryFlat.fetchNextRow(Select.java:1487)
at org.h2.result.LazyResult.hasNext(LazyResult.java:79)
at org.h2.result.LazyResult.next(LazyResult.java:59)
at org.h2.index.ViewCursor.next(ViewCursor.java:49)
at org.h2.index.IndexCursor.next(IndexCursor.java:309)
at org.h2.table.TableFilter.next(TableFilter.java:499)
at org.h2.command.dml.Select$LazyResultQueryFlat.fetchNextRow(Select.java:1487)
*/
private
void
testSimple3RowRecursiveQueryWithLazyEval
()
throws
Exception
{
private
void
testSimple3RowRecursiveQueryWithLazyEval
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|6"
,
};
String
[]
expectedRowData
=
new
String
[]{
"|6"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"BIGINT"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"BIGINT"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUM(N)"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUM(N)"
};
// back up the config - to restore it after this test
// back up the config - to restore it after this test
TestAll
backupConfig
=
config
;
TestAll
backupConfig
=
config
;
config
=
new
TestAll
();
config
=
new
TestAll
();
try
{
try
{
//Test with settings: lazy mvStore memory mvcc multiThreaded
//Test with settings: lazy mvStore memory mvcc multiThreaded
// connection url is =mem:script;MV_STORE=true;LOG=1;LOCK_TIMEOUT=50;MVCC=TRUE;MULTI_THREADED=TRUE;LAZY_QUERY_EXECUTION=1
// connection url is =mem:script;MV_STORE=true;LOG=1;LOCK_TIMEOUT=50;MVCC=TRUE;MULTI_THREADED=TRUE;LAZY_QUERY_EXECUTION=1
config
.
lazy
=
true
;
config
.
lazy
=
true
;
...
@@ -557,8 +534,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -557,8 +534,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
config
.
mvcc
=
true
;
config
.
mvcc
=
true
;
config
.
multiThreaded
=
true
;
config
.
multiThreaded
=
true
;
String
SETUP_
SQL
=
"--no config set"
;
String
setup
SQL
=
"--no config set"
;
String
WITH_QUERY
=
"select sum(n) from (\n"
String
withQuery
=
"select sum(n) from (\n"
+
" with recursive r(n) as (\n"
+
" with recursive r(n) as (\n"
+
" (select 1) union all (select n+1 from r where n < 3) \n"
+
" (select 1) union all (select n+1 from r where n < 3) \n"
+
" )\n"
+
" )\n"
...
@@ -568,10 +545,9 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -568,10 +545,9 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
10
;
int
maxRetries
=
10
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
finally
{
finally
{
config
=
backupConfig
;
config
=
backupConfig
;
}
}
...
...
h2/src/test/org/h2/test/db/TestPersistentCommonTableExpressions.java
浏览文件 @
a7b6996b
...
@@ -30,9 +30,9 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -30,9 +30,9 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
}
}
private
void
testRecursiveTable
()
throws
Exception
{
private
void
testRecursiveTable
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|meat|null"
,
"|fruit|3"
,
"|veg|2"
};
String
[]
expectedRowData
=
new
String
[]{
"|meat|null"
,
"|fruit|3"
,
"|veg|2"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"VARCHAR"
,
"DECIMAL"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"VARCHAR"
,
"DECIMAL"
};
String
[]
expectedColumnNames
=
new
String
[]{
"VAL"
,
String
[]
expectedColumnNames
=
new
String
[]{
"VAL"
,
"SUM(SELECT\n"
+
"SUM(SELECT\n"
+
" X\n"
+
" X\n"
+
"FROM PUBLIC.\"\" BB\n"
+
"FROM PUBLIC.\"\" BB\n"
+
...
@@ -54,7 +54,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -54,7 +54,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
" /* scanCount: 1 */\n"
+
" /* scanCount: 1 */\n"
+
"WHERE BB.A IS A.VAL)"
};
"WHERE BB.A IS A.VAL)"
};
String
SETUP_
SQL
=
String
setup
SQL
=
"DROP TABLE IF EXISTS A; "
"DROP TABLE IF EXISTS A; "
+
"DROP TABLE IF EXISTS B; "
+
"DROP TABLE IF EXISTS B; "
+
"DROP TABLE IF EXISTS C; "
+
"DROP TABLE IF EXISTS C; "
...
@@ -73,9 +73,9 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -73,9 +73,9 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"INSERT INTO C VALUES('carrot', 'nantes'); "
+
"INSERT INTO C VALUES('carrot', 'nantes'); "
+
"INSERT INTO C VALUES('carrot', 'imperator'); "
+
"INSERT INTO C VALUES('carrot', 'imperator'); "
+
"INSERT INTO C VALUES(null, 'banapple'); "
+
"INSERT INTO C VALUES(null, 'banapple'); "
+
"INSERT INTO A VALUES('meat'); "
+
"INSERT INTO A VALUES('meat'); "
;
;
String
WITH_QUERY
=
"WITH BB as (SELECT \n"
+
String
withQuery
=
"WITH BB as (SELECT \n"
+
"sum(1) as X, \n"
+
"sum(1) as X, \n"
+
"a \n"
+
"a \n"
+
"FROM B \n"
+
"FROM B \n"
+
...
@@ -88,13 +88,13 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -88,13 +88,13 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
int
maxRetries
=
3
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
private
void
testPersistentRecursiveTableInCreateView
()
throws
Exception
{
private
void
testPersistentRecursiveTableInCreateView
()
throws
Exception
{
String
SETUP_
SQL
=
"--SET TRACE_LEVEL_SYSTEM_OUT 3;\n"
String
setuo
SQL
=
"--SET TRACE_LEVEL_SYSTEM_OUT 3;\n"
+
"DROP TABLE IF EXISTS my_tree; \n"
+
"DROP TABLE IF EXISTS my_tree; \n"
+
"DROP VIEW IF EXISTS v_my_tree; \n"
+
"DROP VIEW IF EXISTS v_my_tree; \n"
+
"CREATE TABLE my_tree ( \n"
+
"CREATE TABLE my_tree ( \n"
...
@@ -118,12 +118,11 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -118,12 +118,11 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"INNER JOIN tree_cte mtc ON mtc.child_fk = mt.parent_fk \n"
+
"INNER JOIN tree_cte mtc ON mtc.child_fk = mt.parent_fk \n"
+
"), \n"
+
"), \n"
+
"unused_cte AS ( SELECT 1 AS unUsedColumn ) \n"
+
"unused_cte AS ( SELECT 1 AS unUsedColumn ) \n"
+
"SELECT sub_tree_root_id, tree_level, parent_fk, child_fk FROM tree_cte; \n"
+
"SELECT sub_tree_root_id, tree_level, parent_fk, child_fk FROM tree_cte; \n"
;
;
String
WITH_QUERY
=
"SELECT * FROM v_my_tree"
;
String
withQuery
=
"SELECT * FROM v_my_tree"
;
int
maxRetries
=
4
;
int
maxRetries
=
4
;
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
"|11|0|1|11"
,
"|11|0|1|11"
,
"|111|0|11|111"
,
"|111|0|11|111"
,
"|12|0|1|12"
,
"|12|0|1|12"
,
...
@@ -135,15 +134,15 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -135,15 +134,15 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"|1|2|null|111"
,
"|1|2|null|111"
,
"|1|2|null|121"
"|1|2|null|121"
};
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
int
expectedNumberOfRows
=
11
;
int
expectedNumberOfRows
=
11
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setuo
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
String
SETUP_
SQL
=
""
String
setup
SQL
=
""
+
"DROP VIEW IF EXISTS v_my_nr_tree; \n"
+
"DROP VIEW IF EXISTS v_my_nr_tree; \n"
+
"DROP TABLE IF EXISTS my_table; \n"
+
"DROP TABLE IF EXISTS my_table; \n"
+
"CREATE TABLE my_table ( \n"
+
"CREATE TABLE my_table ( \n"
...
@@ -163,22 +162,21 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -163,22 +162,21 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
" FROM my_table mt \n"
+
" FROM my_table mt \n"
+
"), \n"
+
"), \n"
+
"unused_cte AS ( SELECT 1 AS unUsedColumn ) \n"
+
"unused_cte AS ( SELECT 1 AS unUsedColumn ) \n"
+
"SELECT sub_tree_root_id, tree_level, parent_fk, child_fk FROM tree_cte_nr; \n"
+
"SELECT sub_tree_root_id, tree_level, parent_fk, child_fk FROM tree_cte_nr; \n"
;
;
String
WITH_QUERY
=
"SELECT * FROM v_my_nr_tree"
;
String
withQuery
=
"SELECT * FROM v_my_nr_tree"
;
int
maxRetries
=
6
;
int
maxRetries
=
6
;
String
[]
expectedRowData
=
new
String
[]{
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
"|1|0|null|1"
,
"|11|0|1|11"
,
"|11|0|1|11"
,
"|111|0|11|111"
,
"|111|0|11|111"
,
"|12|0|1|12"
,
"|12|0|1|12"
,
"|121|0|12|121"
,
"|121|0|12|121"
,
};
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
int
expectedNumberOfRows
=
5
;
int
expectedNumberOfRows
=
5
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
}
}
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded2.java
浏览文件 @
a7b6996b
...
@@ -78,34 +78,37 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -78,34 +78,37 @@ public class TestMvccMultiThreaded2 extends TestBase {
// gather stats on threads after they finished
// gather stats on threads after they finished
@SuppressWarnings
(
"unused"
)
@SuppressWarnings
(
"unused"
)
int
minProcessed
=
Integer
.
MAX_VALUE
,
maxProcessed
=
0
,
totalProcessed
=
0
;
int
minProcessed
=
Integer
.
MAX_VALUE
,
maxProcessed
=
0
,
totalProcessed
=
0
;
for
(
SelectForUpdate
sfu
:
threads
)
{
for
(
SelectForUpdate
sfu
:
threads
)
{
// make sure all threads have stopped by joining with them
// make sure all threads have stopped by joining with them
sfu
.
join
();
sfu
.
join
();
totalProcessed
+=
sfu
.
iterationsProcessed
;
totalProcessed
+=
sfu
.
iterationsProcessed
;
if
(
sfu
.
iterationsProcessed
>
maxProcessed
)
{
if
(
sfu
.
iterationsProcessed
>
maxProcessed
)
{
maxProcessed
=
sfu
.
iterationsProcessed
;
maxProcessed
=
sfu
.
iterationsProcessed
;
}
}
if
(
sfu
.
iterationsProcessed
<
minProcessed
)
{
if
(
sfu
.
iterationsProcessed
<
minProcessed
)
{
minProcessed
=
sfu
.
iterationsProcessed
;
minProcessed
=
sfu
.
iterationsProcessed
;
}
}
}
}
if
(
DISPLAY_STATS
)
{
if
(
DISPLAY_STATS
)
{
System
.
out
.
println
(
String
.
format
(
"+ INFO: TestMvccMultiThreaded2 RUN STATS threads=%d, minProcessed=%d, maxProcessed=%d, "
+
System
.
out
.
println
(
String
.
format
(
"+ INFO: TestMvccMultiThreaded2 RUN STATS threads=%d, minProcessed=%d, maxProcessed=%d, "
+
"totalProcessed=%d, averagePerThread=%d, averagePerThreadPerSecond=%d\n"
,
"totalProcessed=%d, averagePerThread=%d, averagePerThreadPerSecond=%d\n"
,
TEST_THREAD_COUNT
,
minProcessed
,
maxProcessed
,
totalProcessed
,
totalProcessed
/
TEST_THREAD_COUNT
,
TEST_THREAD_COUNT
,
minProcessed
,
maxProcessed
,
totalProcessed
,
totalProcessed
/
TEST_THREAD_COUNT
,
totalProcessed
/(
TEST_THREAD_COUNT
*
TEST_TIME_SECONDS
)));
totalProcessed
/(
TEST_THREAD_COUNT
*
TEST_TIME_SECONDS
)));
}
}
IOUtils
.
closeSilently
(
conn
);
IOUtils
.
closeSilently
(
conn
);
deleteDb
(
getTestName
());
deleteDb
(
getTestName
());
}
}
/**
* Worker test thread selecting for update
*/
private
class
SelectForUpdate
extends
Thread
{
private
class
SelectForUpdate
extends
Thread
{
public
int
iterationsProcessed
=
0
;
public
int
iterationsProcessed
;
@Override
@Override
public
void
run
()
{
public
void
run
()
{
...
@@ -133,7 +136,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -133,7 +136,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
iterationsProcessed
++;
iterationsProcessed
++;
long
now
=
System
.
currentTimeMillis
();
long
now
=
System
.
currentTimeMillis
();
if
(
now
-
start
>
1000
*
TEST_TIME_SECONDS
){
if
(
now
-
start
>
1000
*
TEST_TIME_SECONDS
)
{
done
=
true
;
done
=
true
;
}
}
}
catch
(
JdbcSQLException
e1
)
{
}
catch
(
JdbcSQLException
e1
)
{
...
@@ -142,8 +145,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -142,8 +145,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
}
}
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
TestBase
.
logError
(
"SQL error from thread "
+
getName
(),
e
);
TestBase
.
logError
(
"SQL error from thread "
+
getName
(),
e
);
}
}
catch
(
Exception
e
)
{
catch
(
Exception
e
)
{
TestBase
.
logError
(
"General error from thread "
+
getName
(),
e
);
TestBase
.
logError
(
"General error from thread "
+
getName
(),
e
);
throw
e
;
throw
e
;
}
}
...
...
h2/src/test/org/h2/test/unit/TestMathUtils.java
浏览文件 @
a7b6996b
...
@@ -51,11 +51,11 @@ public class TestMathUtils extends TestBase {
...
@@ -51,11 +51,11 @@ public class TestMathUtils extends TestBase {
private
void
testNextPowerOf2Int
()
{
private
void
testNextPowerOf2Int
()
{
// the largest power of two that fits into an integer
// the largest power of two that fits into an integer
final
int
LARGEST_POW
2
=
0x40000000
;
final
int
largestPower
2
=
0x40000000
;
int
[]
testValues
=
{
0
,
1
,
2
,
3
,
4
,
12
,
17
,
500
,
1023
,
int
[]
testValues
=
{
0
,
1
,
2
,
3
,
4
,
12
,
17
,
500
,
1023
,
LARGEST_POW2
-
500
,
LARGEST_POW
2
};
largestPower2
-
500
,
largestPower
2
};
int
[]
resultValues
=
{
1
,
1
,
2
,
4
,
4
,
16
,
32
,
512
,
1024
,
int
[]
resultValues
=
{
1
,
1
,
2
,
4
,
4
,
16
,
32
,
512
,
1024
,
LARGEST_POW2
,
LARGEST_POW
2
};
largestPower2
,
largestPower
2
};
for
(
int
i
=
0
;
i
<
testValues
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
testValues
.
length
;
i
++)
{
assertEquals
(
resultValues
[
i
],
MathUtils
.
nextPowerOf2
(
testValues
[
i
]));
assertEquals
(
resultValues
[
i
],
MathUtils
.
nextPowerOf2
(
testValues
[
i
]));
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论