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;
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
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
private
static
final
int
CHAR_END
=
1
,
CHAR_VALUE
=
2
,
CHAR_QUOTED
=
3
;
...
...
@@ -197,9 +199,7 @@ public class Parser {
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
Session
session
;
/**
...
...
@@ -722,7 +722,7 @@ public class Parser {
*
*/
private
Schema
getSchemaWithDefault
()
{
if
(
schemaName
==
null
)
{
if
(
schemaName
==
null
)
{
schemaName
=
session
.
getCurrentSchemaName
();
}
return
getSchema
(
schemaName
);
...
...
@@ -845,13 +845,13 @@ public class Parser {
currentSelect
,
orderInFrom
,
null
);
}
private
TableFilter
readSimpleTableFilterWithAliasExcludes
(
int
orderInFrom
,
Collection
<
String
>
excludeTokens
)
{
private
TableFilter
readSimpleTableFilterWithAliasExcludes
(
int
orderInFrom
,
Collection
<
String
>
excludeTokens
)
{
Table
table
=
readTableOrView
();
String
alias
=
null
;
if
(
readIf
(
"AS"
))
{
alias
=
readAliasIdentifier
();
}
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)
alias
=
readAliasIdentifier
();
}
...
...
@@ -1080,13 +1080,13 @@ public class Parser {
currentPrepared
=
command
;
int
start
=
lastParseIndex
;
read
(
"INTO"
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"USING"
,
"KEY"
,
"VALUES"
);
TableFilter
targetTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"USING"
,
"KEY"
,
"VALUES"
);
TableFilter
targetTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
command
.
setTargetTableFilter
(
targetTableFilter
);
Table
table
=
command
.
getTargetTable
();
if
(
readIf
(
"USING"
)){
return
parseMergeUsing
(
command
,
start
);
if
(
readIf
(
"USING"
))
{
return
parseMergeUsing
(
command
,
start
);
}
if
(
readIf
(
"("
))
{
if
(
isSelect
())
{
...
...
@@ -1147,20 +1147,19 @@ public class Parser {
temporarySourceTableView
,
command
.
getQueryAlias
(),
rightsChecked
,
(
Select
)
command
.
getQuery
(),
0
,
null
);
command
.
setSourceTableFilter
(
sourceTableFilter
);
}
else
{
}
else
{
/* Its a table name, simulate a query by building a select query for the table */
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"ON"
);
TableFilter
sourceTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
TableFilter
sourceTableFilter
=
readSimpleTableFilterWithAliasExcludes
(
0
,
excludeIdentifiers
);
command
.
setSourceTableFilter
(
sourceTableFilter
);
StringBuilder
buff
=
new
StringBuilder
(
"SELECT * FROM "
+
sourceTableFilter
.
getTable
().
getName
());
if
(
sourceTableFilter
.
getTableAlias
()!=
null
)
{
if
(
sourceTableFilter
.
getTableAlias
()
!=
null
)
{
buff
.
append
(
" AS "
+
sourceTableFilter
.
getTableAlias
());
}
Prepared
preparedQuery
=
prepare
(
session
,
buff
.
toString
(),
null
/*paramValues*/
);
command
.
setQuery
((
Select
)
preparedQuery
);
command
.
setQuery
((
Select
)
preparedQuery
);
}
read
(
"ON"
);
...
...
@@ -1169,27 +1168,27 @@ public class Parser {
command
.
setOnCondition
(
condition
);
read
(
")"
);
if
(
readIfAll
(
"WHEN"
,
"MATCHED"
,
"THEN"
))
{
if
(
readIfAll
(
"WHEN"
,
"MATCHED"
,
"THEN"
))
{
int
startMatched
=
lastParseIndex
;
if
(
readIf
(
"UPDATE"
)){
if
(
readIf
(
"UPDATE"
))
{
Update
updateCommand
=
new
Update
(
session
);
//currentPrepared = updateCommand;
TableFilter
filter
=
command
.
getTargetTableFilter
();
updateCommand
.
setTableFilter
(
filter
);
parseUpdateSetClause
(
updateCommand
,
filter
,
startMatched
);
parseUpdateSetClause
(
updateCommand
,
filter
,
startMatched
);
command
.
setUpdateCommand
(
updateCommand
);
}
startMatched
=
lastParseIndex
;
if
(
readIf
(
"DELETE"
)){
if
(
readIf
(
"DELETE"
))
{
Delete
deleteCommand
=
new
Delete
(
session
);
TableFilter
filter
=
command
.
getTargetTableFilter
();
deleteCommand
.
setTableFilter
(
filter
);
parseDeleteGivenTable
(
deleteCommand
,
null
,
startMatched
);
parseDeleteGivenTable
(
deleteCommand
,
null
,
startMatched
);
command
.
setDeleteCommand
(
deleteCommand
);
}
}
if
(
readIfAll
(
"WHEN"
,
"NOT"
,
"MATCHED"
,
"THEN"
))
{
if
(
readIf
(
"INSERT"
)){
if
(
readIfAll
(
"WHEN"
,
"NOT"
,
"MATCHED"
,
"THEN"
))
{
if
(
readIf
(
"INSERT"
))
{
Insert
insertCommand
=
new
Insert
(
session
);
insertCommand
.
setTable
(
command
.
getTargetTable
());
parseInsertGivenTable
(
insertCommand
,
command
.
getTargetTable
());
...
...
@@ -1222,7 +1221,7 @@ public class Parser {
Table
table
=
readTableOrView
();
command
.
setTable
(
table
);
Insert
returnedCommand
=
parseInsertGivenTable
(
command
,
table
);
if
(
returnedCommand
!=
null
)
{
if
(
returnedCommand
!=
null
)
{
return
returnedCommand
;
}
if
(
database
.
getMode
().
onDuplicateKeyUpdate
)
{
...
...
@@ -1453,7 +1452,7 @@ public class Parser {
}
}
// 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
();
}
return
new
TableFilter
(
session
,
table
,
alias
,
rightsChecked
,
...
...
@@ -1489,7 +1488,7 @@ public class Parser {
private
String
readFromAlias
(
String
alias
)
{
// left and right are not keywords (because they are functions as
// well)
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"LEFT"
,
"RIGHT"
,
"FULL"
);
List
<
String
>
excludeIdentifiers
=
Arrays
.
asList
(
"LEFT"
,
"RIGHT"
,
"FULL"
);
return
readFromAlias
(
alias
,
excludeIdentifiers
);
}
...
...
@@ -1942,7 +1941,7 @@ public class Parser {
params
.
add
(
parameters
.
get
(
i
));
}
command
.
setParameterList
(
params
);
if
(
command
instanceof
Query
)
{
if
(
command
instanceof
Query
)
{
Query
query
=
(
Query
)
command
;
query
.
init
();
}
...
...
@@ -2134,8 +2133,7 @@ public class Parser {
Query
query
=
null
;
try
{
query
=
(
Query
)
parseWith
();
}
catch
(
ClassCastException
e
){
}
catch
(
ClassCastException
e
)
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
"WITH statement supports only SELECT (query) in this context"
);
}
...
...
@@ -3493,8 +3491,8 @@ public class Parser {
* Reads passed token in list, in order and returns true on first match.
* If none of the token matches returns false
*/
private
boolean
readIfOr
(
String
...
tokens
)
{
for
(
String
token:
tokens
)
{
private
boolean
readIfOr
(
String
...
tokens
)
{
for
(
String
token:
tokens
)
{
if
(
readIf
(
token
))
{
return
true
;
}
...
...
@@ -3506,14 +3504,13 @@ public class Parser {
* 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.
*/
private
boolean
readIfAll
(
String
...
tokens
)
{
private
boolean
readIfAll
(
String
...
tokens
)
{
// save parse location in case we have to fail this test
int
start
=
lastParseIndex
;
for
(
String
token:
tokens
)
{
for
(
String
token:
tokens
)
{
if
(!
currentTokenQuoted
&&
equalsToken
(
token
,
currentToken
))
{
read
();
}
else
{
}
else
{
// read failed - revert parse location to before when called
parseIndex
=
start
;
read
();
...
...
@@ -3555,7 +3552,7 @@ public class Parser {
return
false
;
}
private
boolean
isTokenInList
(
Collection
<
String
>
upperCaseTokenList
){
private
boolean
isTokenInList
(
Collection
<
String
>
upperCaseTokenList
)
{
String
upperCaseCurrentToken
=
currentToken
.
toUpperCase
();
return
upperCaseTokenList
.
contains
(
upperCaseCurrentToken
);
}
...
...
@@ -4515,7 +4512,7 @@ public class Parser {
String
enumerator0
=
readString
();
enumeratorList
.
add
(
enumerator0
);
original
+=
"'"
+
enumerator0
+
"'"
;
while
(
readIf
(
","
))
{
while
(
readIf
(
","
))
{
original
+=
','
;
String
enumeratorN
=
readString
();
original
+=
"'"
+
enumeratorN
+
"'"
;
...
...
@@ -4527,7 +4524,7 @@ public class Parser {
}
try
{
ValueEnum
.
check
(
enumerators
);
}
catch
(
DbException
e
)
{
}
catch
(
DbException
e
)
{
throw
e
.
addSQL
(
original
);
}
}
else
if
(
readIf
(
"("
))
{
...
...
@@ -5165,7 +5162,7 @@ public class Parser {
// 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
if
(
session
.
isParsingCreateView
())
{
if
(
session
.
isParsingCreateView
())
{
isPersistent
=
true
;
}
...
...
@@ -5180,45 +5177,39 @@ public class Parser {
// used in setCteCleanups
Collections
.
reverse
(
viewsCreated
);
if
(
isToken
(
"SELECT"
))
{
if
(
isToken
(
"SELECT"
))
{
Query
query
=
parseSelectUnion
();
query
.
setPrepareAlways
(
true
);
query
.
setNeverLazy
(
true
);
p
=
query
;
}
else
if
(
readIf
(
"INSERT"
))
{
}
else
if
(
readIf
(
"INSERT"
))
{
p
=
parseInsert
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"UPDATE"
))
{
}
else
if
(
readIf
(
"UPDATE"
))
{
p
=
parseUpdate
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"MERGE"
))
{
}
else
if
(
readIf
(
"MERGE"
))
{
p
=
parseMerge
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"DELETE"
))
{
}
else
if
(
readIf
(
"DELETE"
))
{
p
=
parseDelete
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"CREATE"
))
{
if
(!
isToken
(
"TABLE"
)){
}
else
if
(
readIf
(
"CREATE"
))
{
if
(!
isToken
(
"TABLE"
))
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
);
}
p
=
parseCreate
();
p
.
setPrepareAlways
(
true
);
}
else
{
}
else
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS
);
}
// clean up temporary views starting with last to first (in case of
// dependencies) - but only if they are not persistent
if
(!
isPersistent
)
{
if
(!
isPersistent
)
{
p
.
setCteCleanups
(
viewsCreated
);
}
return
p
;
...
...
@@ -5227,7 +5218,7 @@ public class Parser {
private
TableView
parseSingleCommonTableExpression
(
boolean
isPersistent
)
{
String
cteViewName
=
readIdentifierWithSchema
();
Schema
schema
=
getSchema
();
Table
recursiveTable
=
null
;
Table
recursiveTable
=
null
;
ArrayList
<
Column
>
columns
=
New
.
arrayList
();
String
[]
cols
=
null
;
Database
db
=
session
.
getDatabase
();
...
...
@@ -5244,10 +5235,9 @@ public class Parser {
}
Table
oldViewFound
=
null
;
if
(
isPersistent
)
{
if
(
isPersistent
)
{
oldViewFound
=
getSchema
().
findTableOrView
(
session
,
cteViewName
);
}
else
{
}
else
{
oldViewFound
=
session
.
findLocalTempTable
(
cteViewName
);
}
// this persistent check conflicts with check 10 lines down
...
...
@@ -5261,21 +5251,21 @@ public class Parser {
throw
DbException
.
get
(
ErrorCode
.
TABLE_OR_VIEW_ALREADY_EXISTS_1
,
cteViewName
);
}
if
(
isPersistent
)
{
if
(
isPersistent
)
{
oldViewFound
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
oldViewFound
);
}
else
{
}
else
{
session
.
removeLocalTempTable
(
oldViewFound
);
}
oldViewFound
=
null
;
oldViewFound
=
null
;
}
// this table is created as a work around because recursive
// table expressions need to reference something that look like
// themselves
// to work (its removed after creation in this method)
// 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
,
schema
,
columns
,
db
);
}
...
...
@@ -5285,7 +5275,7 @@ public class Parser {
read
(
"AS"
);
read
(
"("
);
Query
withQuery
=
parseSelect
();
if
(
isPersistent
)
{
if
(
isPersistent
)
{
withQuery
.
session
=
session
;
}
read
(
")"
);
...
...
@@ -5316,16 +5306,16 @@ public class Parser {
// it twice - once without the flag set, and if we didn't see a recursive term,
// then we just compile it again.
TableView
view
;
synchronized
(
targetSession
)
{
synchronized
(
targetSession
)
{
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
parameters
,
columnTemplateArray
,
targetSession
,
allowRecursiveQueryDetection
,
false
/* literalsChecked */
,
true
/* isTableExpression */
,
isPersistent
);
if
(!
view
.
isRecursiveQueryDetected
()
&&
allowRecursiveQueryDetection
)
{
if
(
isPersistent
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
targetSession
,
view
);
view
.
lock
(
targetSession
,
true
,
true
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
view
);
}
else
{
}
else
{
session
.
removeLocalTempTable
(
view
);
}
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
parameters
,
...
...
@@ -5339,13 +5329,12 @@ public class Parser {
view
.
setTemporary
(!
isPersistent
);
view
.
setHidden
(
true
);
view
.
setOnCommitDrop
(
false
);
if
(
addViewToSession
)
{
if
(
isPersistent
)
{
if
(
addViewToSession
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
targetSession
,
view
);
view
.
unlock
(
targetSession
);
db
.
unlockMeta
(
targetSession
);
}
else
{
}
else
{
targetSession
.
addLocalTempTable
(
view
);
}
}
...
...
@@ -5373,12 +5362,12 @@ public class Parser {
read
(
"AS"
);
try
{
Query
query
;
session
.
setParsingCreateView
(
true
,
viewName
);
session
.
setParsingCreateView
(
true
,
viewName
);
try
{
query
=
parseSelect
();
query
.
prepare
();
}
finally
{
session
.
setParsingCreateView
(
false
,
viewName
);
session
.
setParsingCreateView
(
false
,
viewName
);
}
command
.
setSelect
(
query
);
}
catch
(
DbException
e
)
{
...
...
@@ -6118,7 +6107,8 @@ public class Parser {
command
.
setType
(
CommandInterface
.
ALTER_TABLE_DROP_COLUMN
);
ArrayList
<
Column
>
columnsToRemove
=
New
.
arrayList
();
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
{
String
columnName
=
readColumnIdentifier
();
if
(
table
==
null
)
{
...
...
@@ -6131,7 +6121,8 @@ public class Parser {
columnsToRemove
.
add
(
column
);
}
while
(
readIf
(
","
));
if
(
openingBracketDetected
)
{
read
(
")"
);
// For Oracle compatibility - close bracket
// For Oracle compatibility - close bracket
read
(
")"
);
}
command
.
setTableName
(
tableName
);
command
.
setIfTableExists
(
ifTableExists
);
...
...
@@ -6155,8 +6146,8 @@ public class Parser {
command
.
setNewColumnName
(
newColumnName
);
return
command
;
}
else
if
(
readIf
(
"MODIFY"
))
{
// MySQL compatibility
readIf
(
"COLUMN"
);
// optional
// MySQL compatibility
(optional)
readIf
(
"COLUMN"
);
String
columnName
=
readColumnIdentifier
();
AlterTableAlterColumn
command
=
null
;
NullConstraintType
nullConstraint
=
parseNotNullConstraint
();
...
...
@@ -6759,13 +6750,16 @@ public class Parser {
return
command
;
}
private
enum
NullConstraintType
{
/**
* Enumeration describing null constraints
*/
private
enum
NullConstraintType
{
NULL_IS_ALLOWED
,
NULL_IS_NOT_ALLOWED
,
NO_NULL_CONSTRAINT_FOUND
}
private
NullConstraintType
parseNotNullConstraint
()
{
NullConstraintType
nullConstraint
=
NullConstraintType
.
NO_NULL_CONSTRAINT_FOUND
;
if
(
(
isToken
(
"NOT"
)
||
isToken
(
"NULL"
)
))
{
if
(
isToken
(
"NOT"
)
||
isToken
(
"NULL"
))
{
if
(
readIf
(
"NOT"
))
{
read
(
"NULL"
);
nullConstraint
=
NullConstraintType
.
NULL_IS_NOT_ALLOWED
;
...
...
@@ -6775,15 +6769,20 @@ public class Parser {
}
if
(
database
.
getMode
().
getEnum
()
==
ModeEnum
.
Oracle
)
{
if
(
readIf
(
"ENABLE"
))
{
readIf
(
"VALIDATE"
);
// Leave constraint 'as is'
if
(
readIf
(
"NOVALIDATE"
))
{
// Turn off constraint, allow NULLs
// Leave constraint 'as is'
readIf
(
"VALIDATE"
);
// Turn off constraint, allow NULLs
if
(
readIf
(
"NOVALIDATE"
))
{
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
;
readIf
(
"VALIDATE"
);
// ignore validate
readIf
(
"NOVALIDATE"
);
// ignore novalidate
// ignore validate
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 {
}
public
void
setTableExpression
(
boolean
isTableExpression
)
{
this
.
isTableExpression
=
isTableExpression
;
this
.
isTableExpression
=
isTableExpression
;
}
@Override
...
...
@@ -116,11 +116,9 @@ public class CreateView extends SchemaCommand {
}
}
if
(
view
==
null
)
{
if
(
isTableExpression
){
view
=
TableView
.
createTableViewMaybeRecursive
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsStrings
,
session
,
false
/* literalsChecked */
,
isTableExpression
,
true
/*isPersistent*/
,
db
);
}
else
{
if
(
isTableExpression
)
{
view
=
TableView
.
createTableViewMaybeRecursive
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsStrings
,
session
,
false
/* literalsChecked */
,
isTableExpression
,
true
/*isPersistent*/
,
db
);
}
else
{
view
=
new
TableView
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsUnknowns
,
session
,
false
/* allow recursive */
,
false
/* literalsChecked */
,
isTableExpression
,
true
);
}
}
else
{
...
...
h2/src/main/org/h2/command/ddl/DropView.java
浏览文件 @
a7b6996b
...
...
@@ -79,10 +79,10 @@ public class DropView extends SchemaCommand {
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
// remove dependent table expressions
for
(
Table
childTable:
copyOfDependencies
)
{
if
(
TableType
.
VIEW
==
childTable
.
getTableType
())
{
for
(
Table
childTable:
copyOfDependencies
)
{
if
(
TableType
.
VIEW
==
childTable
.
getTableType
())
{
TableView
childTableView
=
(
TableView
)
childTable
;
if
(
childTableView
.
isTableExpression
()
&&
childTableView
.
getName
()!=
null
)
{
if
(
childTableView
.
isTableExpression
()
&&
childTableView
.
getName
()
!=
null
)
{
session
.
getDatabase
().
removeSchemaObject
(
session
,
childTableView
);
}
}
...
...
h2/src/main/org/h2/command/dml/Delete.java
浏览文件 @
a7b6996b
...
...
@@ -53,7 +53,7 @@ public class Delete extends Prepared {
this
.
condition
=
condition
;
}
public
Expression
getCondition
(
)
{
public
Expression
getCondition
()
{
return
this
.
condition
;
}
...
...
@@ -136,17 +136,16 @@ public class Delete extends Prepared {
public
void
prepare
()
{
if
(
condition
!=
null
)
{
condition
.
mapColumns
(
targetTableFilter
,
0
);
if
(
sourceTableFilter
!=
null
)
{
if
(
sourceTableFilter
!=
null
)
{
condition
.
mapColumns
(
sourceTableFilter
,
0
);
}
condition
=
condition
.
optimize
(
session
);
condition
.
createIndexConditions
(
session
,
targetTableFilter
);
}
TableFilter
[]
filters
;
if
(
sourceTableFilter
==
null
)
{
if
(
sourceTableFilter
==
null
)
{
filters
=
new
TableFilter
[]
{
targetTableFilter
};
}
else
{
}
else
{
filters
=
new
TableFilter
[]
{
targetTableFilter
,
sourceTableFilter
};
}
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 {
private
Delete
deleteCommand
;
private
Insert
insertCommand
;
private
String
queryAlias
;
private
int
countUpdatedRows
=
0
;
private
int
countUpdatedRows
;
private
Column
[]
sourceKeys
;
private
Select
targetMatchQuery
;
private
HashMap
<
Value
,
Integer
>
targetRowidsRemembered
=
new
HashMap
<>();
private
int
sourceQueryRowNumber
=
0
;
private
int
sourceQueryRowNumber
;
public
MergeUsing
(
Merge
merge
)
{
super
(
merge
.
getSession
());
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
a7b6996b
...
...
@@ -840,14 +840,14 @@ public class Select extends Query {
sort
=
prepareOrder
(
orderList
,
expressions
.
size
());
orderList
=
null
;
}
ColumnNamer
columnNamer
=
new
ColumnNamer
(
session
);
ColumnNamer
columnNamer
=
new
ColumnNamer
(
session
);
for
(
int
i
=
0
;
i
<
expressions
.
size
();
i
++)
{
Expression
e
=
expressions
.
get
(
i
);
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
(!
columnName
.
equals
(
proposedColumnName
))
{
e
=
new
Alias
(
e
,
columnName
,
true
);
if
(!
columnName
.
equals
(
proposedColumnName
))
{
e
=
new
Alias
(
e
,
columnName
,
true
);
}
expressions
.
set
(
i
,
e
.
optimize
(
session
));
}
...
...
@@ -1087,14 +1087,13 @@ public class Select extends Query {
for
(
TableFilter
f
:
topFilters
)
{
Table
t
=
f
.
getTable
();
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
// statement will re-create the common table expression views.
continue
;
}
else
{
}
else
{
buff
.
append
(
"WITH RECURSIVE "
).
append
(
t
.
getName
()).
append
(
'('
);
buff
.
resetCount
();
for
(
Column
c
:
t
.
getColumns
())
{
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
a7b6996b
...
...
@@ -90,6 +90,9 @@ import org.h2.value.ValueInt;
public
class
Database
implements
DataHandler
{
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
...
...
@@ -296,7 +299,7 @@ public class Database implements DataHandler {
e
.
fillInStackTrace
();
}
boolean
alreadyOpen
=
e
instanceof
DbException
&&
((
DbException
)
e
).
getErrorCode
()
==
ErrorCode
.
DATABASE_ALREADY_OPEN_1
;
&&
((
DbException
)
e
).
getErrorCode
()
==
ErrorCode
.
DATABASE_ALREADY_OPEN_1
;
if
(
alreadyOpen
)
{
stopServer
();
}
...
...
@@ -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.
*
* @param session the session
...
...
@@ -917,13 +917,13 @@ public class Database implements DataHandler {
return
true
;
}
if
(
SysProperties
.
CHECK2
)
{
final
Session
prev
=
metaLockDebugging
.
get
();
final
Session
prev
=
META_LOCK_DEBUGGING
.
get
();
if
(
prev
==
null
)
{
metaLockDebugging
.
set
(
session
);
metaLockDebuggingStack
.
set
(
new
Throwable
(
"Last meta lock granted in this stack trace, "
+
META_LOCK_DEBUGGING
.
set
(
session
);
META_LOCK_DEBUGGING_STACK
.
set
(
new
Throwable
(
"Last meta lock granted in this stack trace, "
+
"this is debug information for following IllegalStateException"
));
}
else
if
(
prev
!=
session
)
{
metaLockDebuggingStack
.
get
().
printStackTrace
();
META_LOCK_DEBUGGING_STACK
.
get
().
printStackTrace
();
throw
new
IllegalStateException
(
"meta currently locked by "
+
prev
+
", sessionid="
+
prev
.
getId
()
+
" and trying to be locked by different session, "
...
...
@@ -953,9 +953,9 @@ public class Database implements DataHandler {
*/
public
void
unlockMetaDebug
(
Session
session
)
{
if
(
SysProperties
.
CHECK2
)
{
if
(
metaLockDebugging
.
get
()
==
session
)
{
metaLockDebugging
.
set
(
null
);
metaLockDebuggingStack
.
set
(
null
);
if
(
META_LOCK_DEBUGGING
.
get
()
==
session
)
{
META_LOCK_DEBUGGING
.
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 {
// It can be recursive, thus implemented as counter.
this
.
parsingView
+=
parsingView
?
1
:
-
1
;
assert
this
.
parsingView
>=
0
;
if
(
parsingView
)
{
if
(
parsingView
)
{
viewNameStack
.
push
(
viewName
);
}
else
{
}
else
{
assert
viewName
.
equals
(
viewNameStack
.
peek
());
viewNameStack
.
pop
();
}
}
public
String
getParsingCreateViewName
()
{
if
(
viewNameStack
.
size
()==
0
)
{
if
(
viewNameStack
.
size
()
==
0
)
{
return
null
;
}
return
viewNameStack
.
peek
();
...
...
@@ -694,7 +693,8 @@ public class Session extends SessionWithState {
for
(
Table
table
:
tablesToAnalyze
)
{
Analyze
.
analyzeTable
(
this
,
table
,
rows
,
false
);
}
database
.
unlockMeta
(
this
);
// analyze can lock the meta
// analyze can lock the meta
database
.
unlockMeta
(
this
);
}
tablesToAnalyze
=
null
;
}
...
...
h2/src/main/org/h2/index/ViewIndex.java
浏览文件 @
a7b6996b
...
...
@@ -6,7 +6,6 @@
package
org
.
h2
.
index
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.concurrent.TimeUnit
;
import
org.h2.api.ErrorCode
;
...
...
h2/src/main/org/h2/mvstore/db/MVTable.java
浏览文件 @
a7b6996b
...
...
@@ -48,11 +48,24 @@ import org.h2.value.Value;
* A table stored in a MVStore.
*/
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
{
TRACE_LOCK_OK
(
"ok"
),
...
...
@@ -62,33 +75,19 @@ public class MVTable extends TableBase {
TRACE_LOCK_UNLOCK
(
"unlock"
),
TRACE_LOCK_ADDED_FOR
(
"added for"
),
TRACE_LOCK_ADD_UPGRADED_FOR
(
"add (upgraded) for "
);
private
TraceLockEvent
(
String
eventText
){
private
final
String
eventText
;
TraceLockEvent
(
String
eventText
)
{
this
.
eventText
=
eventText
;
}
private
final
String
eventText
;
public
String
getEventText
(){
public
String
getEventText
()
{
return
eventText
;
}
}
/**
* 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
;
private
static
final
String
NO_EXTRA_INFO
=
""
;
static
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<>();
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
a7b6996b
...
...
@@ -112,18 +112,18 @@ public class TableView extends Table {
private
Query
compileViewQuery
(
Session
session
,
String
sql
,
boolean
literalsChecked
,
String
viewName
)
{
Prepared
p
;
session
.
setParsingCreateView
(
true
,
viewName
);
session
.
setParsingCreateView
(
true
,
viewName
);
try
{
p
=
session
.
prepare
(
sql
,
false
,
literalsChecked
);
}
finally
{
session
.
setParsingCreateView
(
false
,
viewName
);
session
.
setParsingCreateView
(
false
,
viewName
);
}
if
(!(
p
instanceof
Query
))
{
throw
DbException
.
getSyntaxError
(
sql
,
0
);
}
Query
q
=
(
Query
)
p
;
// only potentially recursive cte queries need to be non-lazy
if
(
isTableExpression
&&
allowRecursive
)
{
if
(
isTableExpression
&&
allowRecursive
)
{
q
.
setNeverLazy
(
true
);
}
return
q
;
...
...
@@ -183,7 +183,7 @@ public class TableView extends Table {
if
(
name
==
null
)
{
name
=
expr
.
getAlias
();
}
name
=
columnNamer
.
getColumnName
(
expr
,
i
,
name
);
name
=
columnNamer
.
getColumnName
(
expr
,
i
,
name
);
if
(
type
==
Value
.
UNKNOWN
)
{
type
=
expr
.
getType
();
}
...
...
@@ -455,7 +455,7 @@ public class TableView extends Table {
@Override
public
String
getSQL
()
{
if
(
isTemporary
()
&&
querySQL
!=
null
)
{
if
(
isTemporary
()
&&
querySQL
!=
null
)
{
return
"(\n"
+
StringUtils
.
indent
(
querySQL
)
+
")"
;
}
return
super
.
getSQL
();
...
...
@@ -707,7 +707,7 @@ public class TableView extends Table {
return
true
;
}
public
List
<
Table
>
getTables
(){
public
List
<
Table
>
getTables
()
{
return
tables
;
}
...
...
@@ -717,7 +717,7 @@ public class TableView extends Table {
public
static
TableView
createTableViewMaybeRecursive
(
Schema
schema
,
int
id
,
String
name
,
String
querySQL
,
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
,
...
...
@@ -726,13 +726,13 @@ public class TableView extends Table {
List
<
Column
>
columnTemplateList
;
String
[]
querySQLOutput
=
new
String
[]{
null
};
ArrayList
<
String
>
columnNames
=
new
ArrayList
<
String
>();
for
(
Column
columnTemplate:
columnTemplates
)
{
for
(
Column
columnTemplate:
columnTemplates
)
{
columnNames
.
add
(
columnTemplate
.
getName
());
}
try
{
Prepared
withQuery
=
session
.
prepare
(
querySQL
,
false
,
false
);
if
(
isPersistent
)
{
if
(
isPersistent
)
{
withQuery
.
setSession
(
session
);
}
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
columnNames
.
toArray
(
new
String
[
1
]),
...
...
@@ -745,11 +745,11 @@ public class TableView extends Table {
// build with recursion turned on
TableView
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
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
if
(!
view
.
isRecursiveQueryDetected
())
{
if
(
isPersistent
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
session
,
view
);
view
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
...
...
@@ -757,7 +757,7 @@ public class TableView extends Table {
// 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...
view
.
removeChildrenAndResources
(
session
);
}
else
{
}
else
{
session
.
removeLocalTempTable
(
view
);
}
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
parameters
,
...
...
@@ -795,7 +795,7 @@ public class TableView extends Table {
// use the passed in column name if supplied, otherwise use alias
// (if found) otherwise use column name derived from column
// expression
String
columnName
=
columnNamer
.
getColumnName
(
columnExp
,
i
,
cols
);
String
columnName
=
columnNamer
.
getColumnName
(
columnExp
,
i
,
cols
);
columnTemplateList
.
add
(
new
Column
(
columnName
,
columnExp
.
getType
()));
...
...
@@ -820,13 +820,13 @@ public class TableView extends Table {
// this gets a meta table lock that is not released
Table
recursiveTable
=
schema
.
createTable
(
recursiveTableData
);
if
(
isPersistent
)
{
if
(
isPersistent
)
{
// this unlock is to prevent lock leak from schema.createTable()
db
.
unlockMeta
(
targetSession
);
synchronized
(
targetSession
)
{
db
.
addSchemaObject
(
targetSession
,
recursiveTable
);
}
}
else
{
}
else
{
targetSession
.
addLocalTempTable
(
recursiveTable
);
}
return
recursiveTable
;
...
...
@@ -834,12 +834,12 @@ public class TableView extends Table {
public
static
void
destroyShadowTableForRecursiveExpression
(
boolean
isPersistent
,
Session
targetSession
,
Table
recursiveTable
)
{
if
(
recursiveTable
!=
null
)
{
if
(
isPersistent
)
{
if
(
recursiveTable
!=
null
)
{
if
(
isPersistent
)
{
recursiveTable
.
lock
(
targetSession
,
true
,
true
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
recursiveTable
);
}
else
{
}
else
{
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`
addTest
(
new
TestReadOnly
());
addTest
(
new
TestRecursiveQueries
());
addTest
(
new
TestGeneralCommonTableQueries
());
if
(!
memory
)
{
if
(!
memory
)
{
// requires persistent store for reconnection tests
addTest
(
new
TestPersistentCommonTableExpressions
());
}
...
...
h2/src/test/org/h2/test/db/AbstractBaseForCommonTableExpressions.java
浏览文件 @
a7b6996b
...
...
@@ -6,11 +6,13 @@ import java.sql.ResultSet;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
org.h2.test.TestBase
;
/**
* Base class for common table expression tests
*/
public
abstract
class
AbstractBaseForCommonTableExpressions
extends
TestBase
{
protected
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
int
expectedNumbeOfRows
,
String
SETUP_
SQL
,
String
WITH_QUERY
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
protected
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
int
expectedNumbeOfRows
,
String
setup
SQL
,
String
withQuery
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
...
...
@@ -18,40 +20,40 @@ public abstract class AbstractBaseForCommonTableExpressions extends TestBase {
ResultSet
rs
;
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
SETUP_
SQL
);
stat
.
execute
(
setup
SQL
);
stat
.
close
();
// 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
=
getConnection
(
"commonTableExpressionQueries"
);
}
prep
=
conn
.
prepareStatement
(
WITH_QUERY
);
prep
=
conn
.
prepareStatement
(
withQuery
);
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
);
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
assertTrue
(
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
!=
null
);
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
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
())
{
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
));
}
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
rowNdx
++;
}
assertEquals
(
expectedNumbeOfRows
,
rowNdx
);
assertEquals
(
expectedNumbeOfRows
,
rowNdx
);
rs
.
close
();
prep
.
close
();
...
...
h2/src/test/org/h2/test/db/TestGeneralCommonTableQueries.java
浏览文件 @
a7b6996b
...
...
@@ -55,18 +55,18 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
ResultSet
rs
;
stat
=
conn
.
createStatement
();
final
String
simple
_two_column_q
uery
=
"with "
+
final
String
simple
TwoColumnQ
uery
=
"with "
+
"t1(n) as (select 1 as first) "
+
",t2(n) as (select 2 as first) "
+
"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
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
prep
=
conn
.
prepareStatement
(
simple
_two_column_q
uery
);
prep
=
conn
.
prepareStatement
(
simple
TwoColumnQ
uery
);
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
...
...
@@ -78,7 +78,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
"t1(n) as (select 2 as first) "
+
",t2(n) as (select 3 as first) "
+
"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
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
...
@@ -91,7 +92,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
",t2(n) as (select 3 as first) "
+
",t3(n) as (select 4 as first) "
+
"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
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
...
@@ -114,15 +116,16 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
",t2 as (select first_col+1 from t1) "
+
",t3 as (select 4 as 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
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertEquals
(
3
,
rs
.
getInt
(
"FIRST_COL"
));
assertFalse
(
rs
.
next
());
assertEquals
(
rs
.
getMetaData
().
getColumnCount
(),
1
);
assertEquals
(
"FIRST_COL"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
rs
.
getMetaData
().
getColumnCount
(),
1
);
assertEquals
(
"FIRST_COL"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
...
...
@@ -174,7 +177,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
prep
.
setInt
(
6
,
6
);
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
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
...
...
@@ -183,7 +186,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
// call it twice
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
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
...
...
@@ -220,21 +223,20 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
assertTrue
(
rs
.
next
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"'T1'"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"'T1'"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertFalse
(
rs
.
next
());
try
{
try
{
prep
=
conn
.
prepareStatement
(
"SELECT * FROM t1 UNION ALL SELECT * FROM t2 "
+
"UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(5,6)"
);
rs
=
prep
.
executeQuery
();
fail
(
"Temp view T1 was accessible after previous WITH statement finished "
+
"- but should not have been."
);
}
catch
(
JdbcSQLException
e
){
}
catch
(
JdbcSQLException
e
)
{
// 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
();
...
...
@@ -293,13 +295,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
prep
.
setInt
(
2
,
2
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"Y1"
,
rs
.
getString
(
3
));
}
...
...
@@ -324,7 +326,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
+
"DELETE FROM T1 WHERE X IN ( SELECT v1.X FROM v1 )"
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
...
...
@@ -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"
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
3
,
rowCount
);
assertEquals
(
3
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
...
...
@@ -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"
);
success
=
prep
.
execute
();
assertEquals
(
false
,
success
);
assertEquals
(
false
,
success
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
...
...
@@ -435,9 +437,9 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
for
(
String
keyLetter
:
new
String
[]
{
"a"
,
"b"
})
{
assertTrue
(
rs
.
next
());
assertContains
(
"ab"
,
rs
.
getString
(
1
));
assertEquals
(
rs
.
getString
(
1
),
keyLetter
);
assertTrue
(
rs
.
getInt
(
2
)
!=
0
);
assertContains
(
"ab"
,
rs
.
getString
(
1
));
assertEquals
(
rs
.
getString
(
1
),
keyLetter
);
assertTrue
(
rs
.
getInt
(
2
)
!=
0
);
}
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
...
...
@@ -462,10 +464,10 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
assertEquals
(
n
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
4
));
}
assertEquals
(
"ONE"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"TWO"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertEquals
(
"THREE"
,
rs
.
getMetaData
().
getColumnLabel
(
3
));
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
4
));
assertEquals
(
"ONE"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"TWO"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertEquals
(
"THREE"
,
rs
.
getMetaData
().
getColumnLabel
(
3
));
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
4
));
assertFalse
(
rs
.
next
());
...
...
@@ -475,12 +477,12 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
private
void
testSimple4RowRecursiveQuery
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|1"
,
"|2"
,
"|3"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"N"
};
String
[]
expectedRowData
=
new
String
[]{
"|1"
,
"|2"
,
"|3"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"N"
};
String
SETUP_
SQL
=
"-- do nothing"
;
String
WITH_QUERY
=
"with recursive r(n) as (\n"
+
String
setup
SQL
=
"-- do nothing"
;
String
withQuery
=
"with recursive r(n) as (\n"
+
"(select 1) union all (select n+1 from r where n < 3)\n"
+
")\n"
+
"select n from r"
;
...
...
@@ -488,19 +490,19 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
private
void
testSimple2By4RowRecursiveQuery
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|0|1|10"
,
"|1|2|11"
,
"|2|3|12"
,
"|3|4|13"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"K"
,
"N"
,
"N2"
};
String
[]
expectedRowData
=
new
String
[]{
"|0|1|10"
,
"|1|2|11"
,
"|2|3|12"
,
"|3|4|13"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"K"
,
"N"
,
"N2"
};
String
SETUP_
SQL
=
"-- do nothing"
;
String
WITH_QUERY
=
"with \n"
+
String
setup
SQL
=
"-- do nothing"
;
String
withQuery
=
"with \n"
+
"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))"
+
"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
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
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
{
String
[]
expectedRowData
=
new
String
[]{
"|6"
,
};
String
[]
expectedColumnTypes
=
new
String
[]{
"BIGINT"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUM(N)"
};
String
[]
expectedRowData
=
new
String
[]{
"|6"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"BIGINT"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUM(N)"
};
// back up the config - to restore it after this test
TestAll
backupConfig
=
config
;
config
=
new
TestAll
();
try
{
try
{
//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
config
.
lazy
=
true
;
...
...
@@ -557,8 +534,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
config
.
mvcc
=
true
;
config
.
multiThreaded
=
true
;
String
SETUP_
SQL
=
"--no config set"
;
String
WITH_QUERY
=
"select sum(n) from (\n"
String
setup
SQL
=
"--no config set"
;
String
withQuery
=
"select sum(n) from (\n"
+
" with recursive r(n) as (\n"
+
" (select 1) union all (select n+1 from r where n < 3) \n"
+
" )\n"
...
...
@@ -568,10 +545,9 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
10
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
}
finally
{
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
finally
{
config
=
backupConfig
;
}
...
...
h2/src/test/org/h2/test/db/TestPersistentCommonTableExpressions.java
浏览文件 @
a7b6996b
...
...
@@ -30,9 +30,9 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
}
private
void
testRecursiveTable
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|meat|null"
,
"|fruit|3"
,
"|veg|2"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"VARCHAR"
,
"DECIMAL"
};
String
[]
expectedColumnNames
=
new
String
[]{
"VAL"
,
String
[]
expectedRowData
=
new
String
[]{
"|meat|null"
,
"|fruit|3"
,
"|veg|2"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"VARCHAR"
,
"DECIMAL"
};
String
[]
expectedColumnNames
=
new
String
[]{
"VAL"
,
"SUM(SELECT\n"
+
" X\n"
+
"FROM PUBLIC.\"\" BB\n"
+
...
...
@@ -54,7 +54,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
" /* scanCount: 1 */\n"
+
"WHERE BB.A IS A.VAL)"
};
String
SETUP_
SQL
=
String
setup
SQL
=
"DROP TABLE IF EXISTS A; "
+
"DROP TABLE IF EXISTS B; "
+
"DROP TABLE IF EXISTS C; "
...
...
@@ -73,9 +73,9 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"INSERT INTO C VALUES('carrot', 'nantes'); "
+
"INSERT INTO C VALUES('carrot', 'imperator'); "
+
"INSERT INTO C VALUES(null, 'banapple'); "
+
"INSERT INTO A VALUES('meat'); "
;
String
WITH_QUERY
=
"WITH BB as (SELECT \n"
+
+
"INSERT INTO A VALUES('meat'); "
;
String
withQuery
=
"WITH BB as (SELECT \n"
+
"sum(1) as X, \n"
+
"a \n"
+
"FROM B \n"
+
...
...
@@ -88,13 +88,13 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
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 VIEW IF EXISTS v_my_tree; \n"
+
"CREATE TABLE my_tree ( \n"
...
...
@@ -118,12 +118,11 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"INNER JOIN tree_cte mtc ON mtc.child_fk = mt.parent_fk \n"
+
"), \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
;
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
"|11|0|1|11"
,
"|111|0|11|111"
,
"|12|0|1|12"
,
...
...
@@ -135,15 +134,15 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"|1|2|null|111"
,
"|1|2|null|121"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
int
expectedNumberOfRows
=
11
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setuo
SQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
String
SETUP_
SQL
=
""
String
setup
SQL
=
""
+
"DROP VIEW IF EXISTS v_my_nr_tree; \n"
+
"DROP TABLE IF EXISTS my_table; \n"
+
"CREATE TABLE my_table ( \n"
...
...
@@ -163,22 +162,21 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
" FROM my_table mt \n"
+
"), \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
;
String
[]
expectedRowData
=
new
String
[]{
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
"|11|0|1|11"
,
"|111|0|11|111"
,
"|12|0|1|12"
,
"|121|0|12|121"
,
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"SUB_TREE_ROOT_ID"
,
"TREE_LEVEL"
,
"PARENT_FK"
,
"CHILD_FK"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
int
expectedNumberOfRows
=
5
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
SETUP_
SQL
,
WITH_QUERY
,
maxRetries
-
1
,
expectedColumnTypes
);
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setup
SQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded2.java
浏览文件 @
a7b6996b
...
...
@@ -78,34 +78,37 @@ public class TestMvccMultiThreaded2 extends TestBase {
// gather stats on threads after they finished
@SuppressWarnings
(
"unused"
)
int
minProcessed
=
Integer
.
MAX_VALUE
,
maxProcessed
=
0
,
totalProcessed
=
0
;
int
minProcessed
=
Integer
.
MAX_VALUE
,
maxProcessed
=
0
,
totalProcessed
=
0
;
for
(
SelectForUpdate
sfu
:
threads
)
{
// make sure all threads have stopped by joining with them
sfu
.
join
();
totalProcessed
+=
sfu
.
iterationsProcessed
;
if
(
sfu
.
iterationsProcessed
>
maxProcessed
)
{
totalProcessed
+=
sfu
.
iterationsProcessed
;
if
(
sfu
.
iterationsProcessed
>
maxProcessed
)
{
maxProcessed
=
sfu
.
iterationsProcessed
;
}
if
(
sfu
.
iterationsProcessed
<
minProcessed
)
{
if
(
sfu
.
iterationsProcessed
<
minProcessed
)
{
minProcessed
=
sfu
.
iterationsProcessed
;
}
}
if
(
DISPLAY_STATS
)
{
if
(
DISPLAY_STATS
)
{
System
.
out
.
println
(
String
.
format
(
"+ INFO: TestMvccMultiThreaded2 RUN STATS threads=%d, minProcessed=%d, maxProcessed=%d, "
+
"totalProcessed=%d, averagePerThread=%d, averagePerThreadPerSecond=%d\n"
,
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
);
deleteDb
(
getTestName
());
}
/**
* Worker test thread selecting for update
*/
private
class
SelectForUpdate
extends
Thread
{
public
int
iterationsProcessed
=
0
;
public
int
iterationsProcessed
;
@Override
public
void
run
()
{
...
...
@@ -133,7 +136,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
iterationsProcessed
++;
long
now
=
System
.
currentTimeMillis
();
if
(
now
-
start
>
1000
*
TEST_TIME_SECONDS
){
if
(
now
-
start
>
1000
*
TEST_TIME_SECONDS
)
{
done
=
true
;
}
}
catch
(
JdbcSQLException
e1
)
{
...
...
@@ -142,8 +145,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
}
}
catch
(
SQLException
e
)
{
TestBase
.
logError
(
"SQL error from thread "
+
getName
(),
e
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
TestBase
.
logError
(
"General error from thread "
+
getName
(),
e
);
throw
e
;
}
...
...
h2/src/test/org/h2/test/unit/TestMathUtils.java
浏览文件 @
a7b6996b
...
...
@@ -51,11 +51,11 @@ public class TestMathUtils extends TestBase {
private
void
testNextPowerOf2Int
()
{
// 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
,
LARGEST_POW2
-
500
,
LARGEST_POW
2
};
largestPower2
-
500
,
largestPower
2
};
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
++)
{
assertEquals
(
resultValues
[
i
],
MathUtils
.
nextPowerOf2
(
testValues
[
i
]));
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论