Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
3a7253d5
Unverified
提交
3a7253d5
authored
1月 12, 2018
作者:
Noel Grandin
提交者:
GitHub
1月 12, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #749 from katzyn/build_errors
Fix some build checks in sources
上级
08742763
815ce845
隐藏空白字符变更
内嵌
并排
正在显示
23 个修改的文件
包含
336 行增加
和
306 行删除
+336
-306
Parser.java
h2/src/main/org/h2/command/Parser.java
+36
-33
CreateView.java
h2/src/main/org/h2/command/ddl/CreateView.java
+9
-6
DropView.java
h2/src/main/org/h2/command/ddl/DropView.java
+4
-4
MergeUsing.java
h2/src/main/org/h2/command/dml/MergeUsing.java
+1
-1
Select.java
h2/src/main/org/h2/command/dml/Select.java
+5
-4
Database.java
h2/src/main/org/h2/engine/Database.java
+5
-5
Session.java
h2/src/main/org/h2/engine/Session.java
+13
-3
JdbcStatementBackwardsCompat.java
h2/src/main/org/h2/jdbc/JdbcStatementBackwardsCompat.java
+1
-1
MVTable.java
h2/src/main/org/h2/mvstore/db/MVTable.java
+5
-5
FilePathDisk.java
h2/src/main/org/h2/store/fs/FilePathDisk.java
+1
-1
Table.java
h2/src/main/org/h2/table/Table.java
+1
-1
TableView.java
h2/src/main/org/h2/table/TableView.java
+27
-24
SourceCompiler.java
h2/src/main/org/h2/util/SourceCompiler.java
+1
-1
AbstractBaseForCommonTableExpressions.java
...org/h2/test/db/AbstractBaseForCommonTableExpressions.java
+76
-72
TestCases.java
h2/src/test/org/h2/test/db/TestCases.java
+2
-1
TestFunctions.java
h2/src/test/org/h2/test/db/TestFunctions.java
+2
-1
TestGeneralCommonTableQueries.java
...rc/test/org/h2/test/db/TestGeneralCommonTableQueries.java
+32
-30
TestPersistentCommonTableExpressions.java
.../org/h2/test/db/TestPersistentCommonTableExpressions.java
+13
-13
TestTriggersConstraints.java
h2/src/test/org/h2/test/db/TestTriggersConstraints.java
+2
-1
TestMvccMultiThreaded2.java
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded2.java
+12
-11
TestScript.java
h2/src/test/org/h2/test/scripts/TestScript.java
+1
-1
mergeUsing.sql
h2/src/test/org/h2/test/scripts/dml/mergeUsing.sql
+33
-33
with.sql
h2/src/test/org/h2/test/scripts/dml/with.sql
+54
-54
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
3a7253d5
...
@@ -199,7 +199,7 @@ public class Parser {
...
@@ -199,7 +199,7 @@ public class Parser {
return
o1
==
o2
?
0
:
compareTableFilters
(
o1
,
o2
);
return
o1
==
o2
?
0
:
compareTableFilters
(
o1
,
o2
);
}
}
};
};
private
final
Database
database
;
private
final
Database
database
;
private
final
Session
session
;
private
final
Session
session
;
/**
/**
...
@@ -1136,7 +1136,8 @@ public class Parser {
...
@@ -1136,7 +1136,8 @@ public class Parser {
command
.
setQueryAlias
(
readFromAlias
(
null
,
Arrays
.
asList
(
"ON"
)));
command
.
setQueryAlias
(
readFromAlias
(
null
,
Arrays
.
asList
(
"ON"
)));
String
[]
querySQLOutput
=
new
String
[]{
null
};
String
[]
querySQLOutput
=
new
String
[]{
null
};
List
<
Column
>
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
null
,
command
.
getQuery
(),
querySQLOutput
);
List
<
Column
>
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
null
,
command
.
getQuery
(),
querySQLOutput
);
TableView
temporarySourceTableView
=
createCTEView
(
TableView
temporarySourceTableView
=
createCTEView
(
command
.
getQueryAlias
(),
querySQLOutput
[
0
],
command
.
getQueryAlias
(),
querySQLOutput
[
0
],
columnTemplateList
,
false
/* no recursion */
,
columnTemplateList
,
false
/* no recursion */
,
...
@@ -5153,24 +5154,24 @@ public class Parser {
...
@@ -5153,24 +5154,24 @@ public class Parser {
private
Prepared
parseWith
()
{
private
Prepared
parseWith
()
{
List
<
TableView
>
viewsCreated
=
new
ArrayList
<>();
List
<
TableView
>
viewsCreated
=
new
ArrayList
<>();
readIf
(
"RECURSIVE"
);
readIf
(
"RECURSIVE"
);
// this WITH statement might not be a temporary view - allow optional keyword to
tell us that
// this WITH statement might not be a temporary view - allow optional keyword to
// this keyword. This feature will not be documented - H2 internal use only.
// t
ell us that t
his keyword. This feature will not be documented - H2 internal use only.
boolean
isPersistent
=
readIf
(
"PERSISTENT"
);
boolean
isPersistent
=
readIf
(
"PERSISTENT"
);
// 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
;
}
}
do
{
do
{
viewsCreated
.
add
(
parseSingleCommonTableExpression
(
isPersistent
));
viewsCreated
.
add
(
parseSingleCommonTableExpression
(
isPersistent
));
}
while
(
readIf
(
","
));
}
while
(
readIf
(
","
));
Prepared
p
=
null
;
Prepared
p
=
null
;
// reverse the order of constructed CTE views - as the destruction order
// reverse the order of constructed CTE views - as the destruction order
// (since later created view may depend on previously created views -
// (since later created view may depend on previously created views -
// we preserve that dependency order in the destruction sequence )
// we preserve that dependency order in the destruction sequence )
// used in setCteCleanups
// used in setCteCleanups
Collections
.
reverse
(
viewsCreated
);
Collections
.
reverse
(
viewsCreated
);
...
@@ -5220,7 +5221,7 @@ public class Parser {
...
@@ -5220,7 +5221,7 @@ public class Parser {
ArrayList
<
Column
>
columns
=
New
.
arrayList
();
ArrayList
<
Column
>
columns
=
New
.
arrayList
();
String
[]
cols
=
null
;
String
[]
cols
=
null
;
Database
db
=
session
.
getDatabase
();
Database
db
=
session
.
getDatabase
();
// column names are now optional - they can be inferred from the named
// column names are now optional - they can be inferred from the named
// query, if not supplied by user
// query, if not supplied by user
if
(
readIf
(
"("
))
{
if
(
readIf
(
"("
))
{
...
@@ -5231,7 +5232,7 @@ public class Parser {
...
@@ -5231,7 +5232,7 @@ public class Parser {
columns
.
add
(
new
Column
(
c
,
Value
.
STRING
));
columns
.
add
(
new
Column
(
c
,
Value
.
STRING
));
}
}
}
}
Table
oldViewFound
=
null
;
Table
oldViewFound
=
null
;
if
(
isPersistent
)
{
if
(
isPersistent
)
{
oldViewFound
=
getSchema
().
findTableOrView
(
session
,
cteViewName
);
oldViewFound
=
getSchema
().
findTableOrView
(
session
,
cteViewName
);
...
@@ -5251,8 +5252,8 @@ public class Parser {
...
@@ -5251,8 +5252,8 @@ public class Parser {
}
}
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
);
}
}
...
@@ -5275,7 +5276,7 @@ public class Parser {
...
@@ -5275,7 +5276,7 @@ public class Parser {
Query
withQuery
=
parseSelect
();
Query
withQuery
=
parseSelect
();
if
(
isPersistent
)
{
if
(
isPersistent
)
{
withQuery
.
session
=
session
;
withQuery
.
session
=
session
;
}
}
read
(
")"
);
read
(
")"
);
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
cols
,
withQuery
,
querySQLOutput
);
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
cols
,
withQuery
,
querySQLOutput
);
...
@@ -5285,43 +5286,45 @@ public class Parser {
...
@@ -5285,43 +5286,45 @@ public class Parser {
TableView
view
=
createCTEView
(
cteViewName
,
TableView
view
=
createCTEView
(
cteViewName
,
querySQLOutput
[
0
],
columnTemplateList
,
querySQLOutput
[
0
],
columnTemplateList
,
true
/* allowRecursiveQueryDetection */
,
true
/* allowRecursiveQueryDetection */
,
true
/* add to session */
,
true
/* add to session */
,
isPersistent
,
session
);
isPersistent
,
session
);
return
view
;
return
view
;
}
}
private
TableView
createCTEView
(
String
cteViewName
,
String
querySQL
,
private
TableView
createCTEView
(
String
cteViewName
,
String
querySQL
,
List
<
Column
>
columnTemplateList
,
boolean
allowRecursiveQueryDetection
,
List
<
Column
>
columnTemplateList
,
boolean
allowRecursiveQueryDetection
,
boolean
addViewToSession
,
boolean
isPersistent
,
Session
targetSession
)
{
boolean
addViewToSession
,
boolean
isPersistent
,
Session
targetSession
)
{
Database
db
=
targetSession
.
getDatabase
();
Database
db
=
targetSession
.
getDatabase
();
Schema
schema
=
getSchemaWithDefault
();
Schema
schema
=
getSchemaWithDefault
();
int
id
=
db
.
allocateObjectId
();
int
id
=
db
.
allocateObjectId
();
Column
[]
columnTemplateArray
=
columnTemplateList
.
toArray
(
new
Column
[
0
]);
Column
[]
columnTemplateArray
=
columnTemplateList
.
toArray
(
new
Column
[
0
]);
// No easy way to determine if this is a recursive query up front, so we just compile
// No easy way to determine if this is a recursive query up front, so we just compile
// 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
,
columnTemplateArray
,
targetSession
,
columnTemplateArray
,
targetSession
,
false
/* assume recursive */
,
false
/* literalsChecked */
,
true
/* isTableExpression */
,
isPersistent
);
false
/* assume recursive */
,
false
/* literalsChecked */
,
true
/* isTableExpression */
,
isPersistent
);
}
}
// both removeSchemaObject and removeLocalTempTable hold meta locks
// both removeSchemaObject and removeLocalTempTable hold meta locks
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
}
}
view
.
setTableExpression
(
true
);
view
.
setTableExpression
(
true
);
view
.
setTemporary
(!
isPersistent
);
view
.
setTemporary
(!
isPersistent
);
...
@@ -6104,7 +6107,7 @@ public class Parser {
...
@@ -6104,7 +6107,7 @@ public class Parser {
ArrayList
<
Column
>
columnsToRemove
=
New
.
arrayList
();
ArrayList
<
Column
>
columnsToRemove
=
New
.
arrayList
();
Table
table
=
tableIfTableExists
(
schema
,
tableName
,
ifTableExists
);
Table
table
=
tableIfTableExists
(
schema
,
tableName
,
ifTableExists
);
// For Oracle compatibility - open bracket required
// For Oracle compatibility - open bracket required
boolean
openingBracketDetected
=
readIf
(
"("
);
boolean
openingBracketDetected
=
readIf
(
"("
);
do
{
do
{
String
columnName
=
readColumnIdentifier
();
String
columnName
=
readColumnIdentifier
();
if
(
table
==
null
)
{
if
(
table
==
null
)
{
...
@@ -6118,7 +6121,7 @@ public class Parser {
...
@@ -6118,7 +6121,7 @@ public class Parser {
}
while
(
readIf
(
","
));
}
while
(
readIf
(
","
));
if
(
openingBracketDetected
)
{
if
(
openingBracketDetected
)
{
// For Oracle compatibility - close bracket
// For Oracle compatibility - close bracket
read
(
")"
);
read
(
")"
);
}
}
command
.
setTableName
(
tableName
);
command
.
setTableName
(
tableName
);
command
.
setIfTableExists
(
ifTableExists
);
command
.
setIfTableExists
(
ifTableExists
);
...
@@ -6145,7 +6148,7 @@ public class Parser {
...
@@ -6145,7 +6148,7 @@ public class Parser {
// MySQL compatibility (optional)
// MySQL compatibility (optional)
readIf
(
"COLUMN"
);
readIf
(
"COLUMN"
);
// Oracle specifies (but will not require) an opening parenthesis
// Oracle specifies (but will not require) an opening parenthesis
boolean
hasOpeningBracket
=
readIf
(
"("
);
boolean
hasOpeningBracket
=
readIf
(
"("
);
String
columnName
=
readColumnIdentifier
();
String
columnName
=
readColumnIdentifier
();
AlterTableAlterColumn
command
=
null
;
AlterTableAlterColumn
command
=
null
;
NullConstraintType
nullConstraint
=
parseNotNullConstraint
();
NullConstraintType
nullConstraint
=
parseNotNullConstraint
();
...
@@ -6754,7 +6757,7 @@ public class Parser {
...
@@ -6754,7 +6757,7 @@ public class Parser {
/**
/**
* Enumeration describing null constraints
* Enumeration describing null constraints
*/
*/
private
enum
NullConstraintType
{
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
}
}
...
@@ -6771,19 +6774,19 @@ public class Parser {
...
@@ -6771,19 +6774,19 @@ public class Parser {
if
(
database
.
getMode
().
getEnum
()
==
ModeEnum
.
Oracle
)
{
if
(
database
.
getMode
().
getEnum
()
==
ModeEnum
.
Oracle
)
{
if
(
readIf
(
"ENABLE"
))
{
if
(
readIf
(
"ENABLE"
))
{
// Leave constraint 'as is'
// Leave constraint 'as is'
readIf
(
"VALIDATE"
);
readIf
(
"VALIDATE"
);
// Turn off constraint, allow NULLs
// Turn off constraint, allow NULLs
if
(
readIf
(
"NOVALIDATE"
))
{
if
(
readIf
(
"NOVALIDATE"
))
{
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
}
}
}
}
// Turn off constraint, allow NULLs
// Turn off constraint, allow NULLs
if
(
readIf
(
"DISABLE"
))
{
if
(
readIf
(
"DISABLE"
))
{
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
// ignore validate
// ignore validate
readIf
(
"VALIDATE"
);
readIf
(
"VALIDATE"
);
// ignore novalidate
// ignore novalidate
readIf
(
"NOVALIDATE"
);
readIf
(
"NOVALIDATE"
);
}
}
}
}
}
}
...
...
h2/src/main/org/h2/command/ddl/CreateView.java
浏览文件 @
3a7253d5
...
@@ -71,10 +71,10 @@ public class CreateView extends SchemaCommand {
...
@@ -71,10 +71,10 @@ public class CreateView extends SchemaCommand {
public
void
setForce
(
boolean
force
)
{
public
void
setForce
(
boolean
force
)
{
this
.
force
=
force
;
this
.
force
=
force
;
}
}
public
void
setTableExpression
(
boolean
isTableExpression
)
{
public
void
setTableExpression
(
boolean
isTableExpression
)
{
this
.
isTableExpression
=
isTableExpression
;
this
.
isTableExpression
=
isTableExpression
;
}
}
@Override
@Override
public
int
update
()
{
public
int
update
()
{
...
@@ -117,9 +117,12 @@ public class CreateView extends SchemaCommand {
...
@@ -117,9 +117,12 @@ 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
{
// TODO support isTableExpression in replace function...
// TODO support isTableExpression in replace function...
...
@@ -135,10 +138,10 @@ public class CreateView extends SchemaCommand {
...
@@ -135,10 +138,10 @@ public class CreateView extends SchemaCommand {
}
else
{
}
else
{
db
.
updateMeta
(
session
,
view
);
db
.
updateMeta
(
session
,
view
);
}
}
// TODO: if we added any table expressions that aren't used by this view, detect them
// TODO: if we added any table expressions that aren't used by this view, detect them
// and drop them - otherwise they will leak and never get cleaned up.
// and drop them - otherwise they will leak and never get cleaned up.
return
0
;
return
0
;
}
}
...
...
h2/src/main/org/h2/command/ddl/DropView.java
浏览文件 @
3a7253d5
...
@@ -68,13 +68,13 @@ public class DropView extends SchemaCommand {
...
@@ -68,13 +68,13 @@ public class DropView extends SchemaCommand {
}
}
}
}
}
}
// TODO: Where is the ConstraintReferential.CASCADE style drop processing ? It's
// TODO: Where is the ConstraintReferential.CASCADE style drop processing ? It's
// supported from imported keys - but not for dependent db objects
// supported from imported keys - but not for dependent db objects
TableView
tableView
=
(
TableView
)
view
;
TableView
tableView
=
(
TableView
)
view
;
ArrayList
<
Table
>
copyOfDependencies
=
new
ArrayList
<
Table
>(
tableView
.
getTables
());
ArrayList
<
Table
>
copyOfDependencies
=
new
ArrayList
<
Table
>(
tableView
.
getTables
());
view
.
lock
(
session
,
true
,
true
);
view
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
...
...
h2/src/main/org/h2/command/dml/MergeUsing.java
浏览文件 @
3a7253d5
...
@@ -80,7 +80,7 @@ import org.h2.value.Value;
...
@@ -80,7 +80,7 @@ import org.h2.value.Value;
* action is always triggered. This is because the embedded UPDATE and DELETE statement's
* action is always triggered. This is because the embedded UPDATE and DELETE statement's
* returned update row count is used to detect a matching join.
* returned update row count is used to detect a matching join.
* If neither of the two the statements are provided, no matching join is NEVER detected.
* If neither of the two the statements are provided, no matching join is NEVER detected.
*
*
* A fix for this is now implemented as described below:
* A fix for this is now implemented as described below:
* We now generate a "matchSelect" query and use that to always detect
* We now generate a "matchSelect" query and use that to always detect
* a match join - rather than relying on UPDATE or DELETE statements.
* a match join - rather than relying on UPDATE or DELETE statements.
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
3a7253d5
...
@@ -1062,10 +1062,11 @@ public class Select extends Query {
...
@@ -1062,10 +1062,11 @@ public class Select extends Query {
Table
t
=
f
.
getTable
();
Table
t
=
f
.
getTable
();
TableView
tableView
=
t
.
isView
()
?
(
TableView
)
t
:
null
;
TableView
tableView
=
t
.
isView
()
?
(
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,
// statement will re-create the common table expression views.
// since using a with 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
(
'('
);
...
@@ -1074,7 +1075,7 @@ public class Select extends Query {
...
@@ -1074,7 +1075,7 @@ public class Select extends Query {
buff
.
appendExceptFirst
(
","
);
buff
.
appendExceptFirst
(
","
);
buff
.
append
(
c
.
getName
());
buff
.
append
(
c
.
getName
());
}
}
buff
.
append
(
") AS "
).
append
(
t
.
getSQL
()).
append
(
"\n"
);
buff
.
append
(
") AS "
).
append
(
t
.
getSQL
()).
append
(
"\n"
);
}
}
}
}
}
}
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
3a7253d5
...
@@ -90,7 +90,7 @@ import org.h2.value.ValueInt;
...
@@ -90,7 +90,7 @@ 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
<
Session
>
META_LOCK_DEBUGGING
=
new
ThreadLocal
<
Session
>();
private
static
final
ThreadLocal
<
Throwable
>
META_LOCK_DEBUGGING_STACK
=
new
ThreadLocal
<
Throwable
>();
private
static
final
ThreadLocal
<
Throwable
>
META_LOCK_DEBUGGING_STACK
=
new
ThreadLocal
<
Throwable
>();
...
@@ -768,7 +768,7 @@ public class Database implements DataHandler {
...
@@ -768,7 +768,7 @@ public class Database implements DataHandler {
Collections
.
sort
(
records
);
Collections
.
sort
(
records
);
synchronized
(
systemSession
)
{
synchronized
(
systemSession
)
{
for
(
MetaRecord
rec
:
records
)
{
for
(
MetaRecord
rec
:
records
)
{
rec
.
execute
(
this
,
systemSession
,
eventListener
);
rec
.
execute
(
this
,
systemSession
,
eventListener
);
}
}
}
}
if
(
mvStore
!=
null
)
{
if
(
mvStore
!=
null
)
{
...
@@ -902,7 +902,7 @@ public class Database implements DataHandler {
...
@@ -902,7 +902,7 @@ public class Database implements DataHandler {
}
}
}
}
/**
/**
* Lock the metadata table for updates.
* Lock the metadata table for updates.
*
*
* @param session the session
* @param session the session
...
@@ -933,7 +933,7 @@ public class Database implements DataHandler {
...
@@ -933,7 +933,7 @@ public class Database implements DataHandler {
boolean
wasLocked
=
meta
.
lock
(
session
,
true
,
true
);
boolean
wasLocked
=
meta
.
lock
(
session
,
true
,
true
);
return
wasLocked
;
return
wasLocked
;
}
}
/**
/**
* Unlock the metadata table.
* Unlock the metadata table.
*
*
...
@@ -1912,7 +1912,7 @@ public class Database implements DataHandler {
...
@@ -1912,7 +1912,7 @@ public class Database implements DataHandler {
t
.
getSQL
());
t
.
getSQL
());
}
}
obj
.
removeChildrenAndResources
(
session
);
obj
.
removeChildrenAndResources
(
session
);
}
}
removeMeta
(
session
,
id
);
removeMeta
(
session
,
id
);
}
}
...
...
h2/src/main/org/h2/engine/Session.java
浏览文件 @
3a7253d5
...
@@ -123,7 +123,7 @@ public class Session extends SessionWithState {
...
@@ -123,7 +123,7 @@ public class Session extends SessionWithState {
private
long
modificationMetaID
=
-
1
;
private
long
modificationMetaID
=
-
1
;
private
SubQueryInfo
subQueryInfo
;
private
SubQueryInfo
subQueryInfo
;
private
int
parsingView
;
private
int
parsingView
;
private
Deque
<
String
>
viewNameStack
=
new
ArrayDeque
<
String
>();
private
Deque
<
String
>
viewNameStack
=
new
ArrayDeque
<
String
>();
private
int
preparingQueryExpression
;
private
int
preparingQueryExpression
;
private
volatile
SmallLRUCache
<
Object
,
ViewIndex
>
viewIndexCache
;
private
volatile
SmallLRUCache
<
Object
,
ViewIndex
>
viewIndexCache
;
private
HashMap
<
Object
,
ViewIndex
>
subQueryIndexCache
;
private
HashMap
<
Object
,
ViewIndex
>
subQueryIndexCache
;
...
@@ -229,6 +229,16 @@ public class Session extends SessionWithState {
...
@@ -229,6 +229,16 @@ public class Session extends SessionWithState {
return
subQueryInfo
;
return
subQueryInfo
;
}
}
/**
* Stores name of currently parsed view in a stack so it can be determined
* during {@code prepare()}.
*
* @param parsingView
* {@code true} to store one more name, {@code false} to remove it
* from stack
* @param viewName
* name of the view
*/
public
void
setParsingCreateView
(
boolean
parsingView
,
String
viewName
)
{
public
void
setParsingCreateView
(
boolean
parsingView
,
String
viewName
)
{
// 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
;
...
@@ -238,7 +248,7 @@ public class Session extends SessionWithState {
...
@@ -238,7 +248,7 @@ public class Session extends SessionWithState {
}
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
)
{
...
@@ -695,7 +705,7 @@ public class Session extends SessionWithState {
...
@@ -695,7 +705,7 @@ public class Session extends SessionWithState {
Analyze
.
analyzeTable
(
this
,
table
,
rows
,
false
);
Analyze
.
analyzeTable
(
this
,
table
,
rows
,
false
);
}
}
// analyze can lock the meta
// analyze can lock the meta
database
.
unlockMeta
(
this
);
database
.
unlockMeta
(
this
);
}
}
tablesToAnalyze
=
null
;
tablesToAnalyze
=
null
;
}
}
...
...
h2/src/main/org/h2/jdbc/JdbcStatementBackwardsCompat.java
浏览文件 @
3a7253d5
...
@@ -121,7 +121,7 @@ public interface JdbcStatementBackwardsCompat {
...
@@ -121,7 +121,7 @@ public interface JdbcStatementBackwardsCompat {
/**
/**
* Enquotes the specified identifier.
* Enquotes the specified identifier.
*
*
* @param identifier
* @param identifier
* identifier to quote if required
* identifier to quote if required
* @param alwaysQuote
* @param alwaysQuote
* if {@code true} identifier will be quoted unconditionally
* if {@code true} identifier will be quoted unconditionally
...
...
h2/src/main/org/h2/mvstore/db/MVTable.java
浏览文件 @
3a7253d5
...
@@ -62,12 +62,12 @@ public class MVTable extends TableBase {
...
@@ -62,12 +62,12 @@ public class MVTable extends TableBase {
* The tables names this thread has a shared lock on.
* The tables names this thread has a shared lock on.
*/
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
SHARED_LOCKS
;
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
SHARED_LOCKS
;
/**
/**
* The type of trace lock events
* The type of trace lock events
*/
*/
private
enum
TraceLockEvent
{
private
enum
TraceLockEvent
{
TRACE_LOCK_OK
(
"ok"
),
TRACE_LOCK_OK
(
"ok"
),
TRACE_LOCK_WAITING_FOR
(
"waiting for"
),
TRACE_LOCK_WAITING_FOR
(
"waiting for"
),
TRACE_LOCK_REQUESTING_FOR
(
"requesting for"
),
TRACE_LOCK_REQUESTING_FOR
(
"requesting for"
),
...
@@ -81,13 +81,13 @@ public class MVTable extends TableBase {
...
@@ -81,13 +81,13 @@ public class MVTable extends TableBase {
TraceLockEvent
(
String
eventText
)
{
TraceLockEvent
(
String
eventText
)
{
this
.
eventText
=
eventText
;
this
.
eventText
=
eventText
;
}
}
public
String
getEventText
()
{
public
String
getEventText
()
{
return
eventText
;
return
eventText
;
}
}
}
}
private
static
final
String
NO_EXTRA_INFO
=
""
;
private
static
final
String
NO_EXTRA_INFO
=
""
;
static
{
static
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<>();
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<>();
...
@@ -428,7 +428,7 @@ public class MVTable extends TableBase {
...
@@ -428,7 +428,7 @@ public class MVTable extends TableBase {
public
boolean
isLockedExclusivelyBy
(
Session
session
)
{
public
boolean
isLockedExclusivelyBy
(
Session
session
)
{
return
lockExclusiveSession
==
session
;
return
lockExclusiveSession
==
session
;
}
}
@Override
@Override
public
void
unlock
(
Session
s
)
{
public
void
unlock
(
Session
s
)
{
if
(
database
!=
null
)
{
if
(
database
!=
null
)
{
...
...
h2/src/main/org/h2/store/fs/FilePathDisk.java
浏览文件 @
3a7253d5
...
@@ -299,7 +299,7 @@ public class FilePathDisk extends FilePath {
...
@@ -299,7 +299,7 @@ public class FilePathDisk extends FilePath {
// file name with a colon
// file name with a colon
if
(
name
.
startsWith
(
CLASSPATH_PREFIX
))
{
if
(
name
.
startsWith
(
CLASSPATH_PREFIX
))
{
String
fileName
=
name
.
substring
(
CLASSPATH_PREFIX
.
length
());
String
fileName
=
name
.
substring
(
CLASSPATH_PREFIX
.
length
());
// Force absolute resolution in Class.getResourceAsStream
// Force absolute resolution in Class.getResourceAsStream
if
(!
fileName
.
startsWith
(
"/"
))
{
if
(!
fileName
.
startsWith
(
"/"
))
{
fileName
=
"/"
+
fileName
;
fileName
=
"/"
+
fileName
;
}
}
...
...
h2/src/main/org/h2/table/Table.java
浏览文件 @
3a7253d5
...
@@ -1239,7 +1239,7 @@ public abstract class Table extends SchemaObjectBase {
...
@@ -1239,7 +1239,7 @@ public abstract class Table extends SchemaObjectBase {
public
boolean
isMVStore
()
{
public
boolean
isMVStore
()
{
return
false
;
return
false
;
}
}
public
void
setTableExpression
(
boolean
tableExpression
)
{
public
void
setTableExpression
(
boolean
tableExpression
)
{
this
.
tableExpression
=
tableExpression
;
this
.
tableExpression
=
tableExpression
;
}
}
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
3a7253d5
...
@@ -67,7 +67,8 @@ public class TableView extends Table {
...
@@ -67,7 +67,8 @@ public class TableView extends Table {
ArrayList
<
Parameter
>
params
,
Column
[]
columnTemplates
,
Session
session
,
ArrayList
<
Parameter
>
params
,
Column
[]
columnTemplates
,
Session
session
,
boolean
allowRecursive
,
boolean
literalsChecked
,
boolean
isTableExpression
,
boolean
isPersistent
)
{
boolean
allowRecursive
,
boolean
literalsChecked
,
boolean
isTableExpression
,
boolean
isPersistent
)
{
super
(
schema
,
id
,
name
,
false
,
true
);
super
(
schema
,
id
,
name
,
false
,
true
);
init
(
querySQL
,
params
,
columnTemplates
,
session
,
allowRecursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
init
(
querySQL
,
params
,
columnTemplates
,
session
,
allowRecursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
}
}
/**
/**
...
@@ -90,7 +91,7 @@ public class TableView extends Table {
...
@@ -90,7 +91,7 @@ public class TableView extends Table {
session
,
recursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
session
,
recursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
DbException
e
=
recompile
(
session
,
force
,
true
);
DbException
e
=
recompile
(
session
,
force
,
true
);
if
(
e
!=
null
)
{
if
(
e
!=
null
)
{
init
(
oldQuerySQL
,
null
,
oldColumnTemplates
,
session
,
oldRecursive
,
init
(
oldQuerySQL
,
null
,
oldColumnTemplates
,
session
,
oldRecursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
literalsChecked
,
isTableExpression
,
isPersistent
);
recompile
(
session
,
true
,
false
);
recompile
(
session
,
true
,
false
);
throw
e
;
throw
e
;
...
@@ -98,7 +99,7 @@ public class TableView extends Table {
...
@@ -98,7 +99,7 @@ public class TableView extends Table {
}
}
private
synchronized
void
init
(
String
querySQL
,
ArrayList
<
Parameter
>
params
,
private
synchronized
void
init
(
String
querySQL
,
ArrayList
<
Parameter
>
params
,
Column
[]
columnTemplates
,
Session
session
,
boolean
allowRecursive
,
boolean
literalsChecked
,
Column
[]
columnTemplates
,
Session
session
,
boolean
allowRecursive
,
boolean
literalsChecked
,
boolean
isTableExpression
,
boolean
isPersistent
)
{
boolean
isTableExpression
,
boolean
isPersistent
)
{
this
.
querySQL
=
querySQL
;
this
.
querySQL
=
querySQL
;
this
.
columnTemplates
=
columnTemplates
;
this
.
columnTemplates
=
columnTemplates
;
...
@@ -555,7 +556,7 @@ public class TableView extends Table {
...
@@ -555,7 +556,7 @@ public class TableView extends Table {
String
querySQL
=
query
.
getPlanSQL
();
String
querySQL
=
query
.
getPlanSQL
();
TableView
v
=
new
TableView
(
mainSchema
,
0
,
name
,
TableView
v
=
new
TableView
(
mainSchema
,
0
,
name
,
querySQL
,
query
.
getParameters
(),
null
/* column templates */
,
session
,
querySQL
,
query
.
getParameters
(),
null
/* column templates */
,
session
,
false
/* allow recursive */
,
true
/* literals have already been checked when parsing original query */
,
false
/* allow recursive */
,
true
/* literals have already been checked when parsing original query */
,
false
/* is table expression */
,
false
/* is persistent*/
);
false
/* is table expression */
,
false
/* is persistent*/
);
if
(
v
.
createException
!=
null
)
{
if
(
v
.
createException
!=
null
)
{
throw
v
.
createException
;
throw
v
.
createException
;
...
@@ -705,7 +706,7 @@ public class TableView extends Table {
...
@@ -705,7 +706,7 @@ public class TableView extends Table {
}
}
return
true
;
return
true
;
}
}
public
List
<
Table
>
getTables
()
{
public
List
<
Table
>
getTables
()
{
return
tables
;
return
tables
;
}
}
...
@@ -713,11 +714,11 @@ public class TableView extends Table {
...
@@ -713,11 +714,11 @@ public class TableView extends Table {
public
boolean
isPersistent
()
{
public
boolean
isPersistent
()
{
return
isPersistent
;
return
isPersistent
;
}
}
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
,
schema
,
Arrays
.
asList
(
columnTemplates
),
db
);
schema
,
Arrays
.
asList
(
columnTemplates
),
db
);
...
@@ -728,42 +729,44 @@ public class TableView extends Table {
...
@@ -728,42 +729,44 @@ public class TableView extends Table {
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
]),
(
Query
)
withQuery
,
querySQLOutput
);
(
Query
)
withQuery
,
querySQLOutput
);
}
finally
{
}
finally
{
TableView
.
destroyShadowTableForRecursiveExpression
(
isPersistent
,
session
,
recursiveTable
);
TableView
.
destroyShadowTableForRecursiveExpression
(
isPersistent
,
session
,
recursiveTable
);
}
}
// 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
);
// 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
// to correctly un-register the table which the table expression uses...
// needs to be 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
,
columnTemplates
,
session
,
columnTemplates
,
session
,
false
/* detected not recursive */
,
literalsChecked
,
isTableExpression
,
isPersistent
);
false
/* detected not recursive */
,
literalsChecked
,
isTableExpression
,
isPersistent
);
}
}
return
view
;
return
view
;
}
}
...
@@ -797,14 +800,14 @@ public class TableView extends Table {
...
@@ -797,14 +800,14 @@ public class TableView extends Table {
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
()));
}
}
return
columnTemplateList
;
return
columnTemplateList
;
}
}
public
static
Table
createShadowTableForRecursiveTableExpression
(
boolean
isPersistent
,
Session
targetSession
,
public
static
Table
createShadowTableForRecursiveTableExpression
(
boolean
isPersistent
,
Session
targetSession
,
String
cteViewName
,
Schema
schema
,
List
<
Column
>
columns
,
Database
db
)
{
String
cteViewName
,
Schema
schema
,
List
<
Column
>
columns
,
Database
db
)
{
// create table data object
// create table data object
CreateTableData
recursiveTableData
=
new
CreateTableData
();
CreateTableData
recursiveTableData
=
new
CreateTableData
();
recursiveTableData
.
id
=
db
.
allocateObjectId
();
recursiveTableData
.
id
=
db
.
allocateObjectId
();
...
@@ -815,10 +818,10 @@ public class TableView extends Table {
...
@@ -815,10 +818,10 @@ public class TableView extends Table {
recursiveTableData
.
persistIndexes
=
isPersistent
;
recursiveTableData
.
persistIndexes
=
isPersistent
;
recursiveTableData
.
create
=
true
;
recursiveTableData
.
create
=
true
;
recursiveTableData
.
session
=
targetSession
;
recursiveTableData
.
session
=
targetSession
;
// 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
);
...
@@ -837,11 +840,11 @@ public class TableView extends Table {
...
@@ -837,11 +840,11 @@ public class TableView extends Table {
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
);
}
}
// both removeSchemaObject and removeLocalTempTable hold meta locks - release them here
// both removeSchemaObject and removeLocalTempTable hold meta locks - release them here
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
}
}
...
...
h2/src/main/org/h2/util/SourceCompiler.java
浏览文件 @
3a7253d5
...
@@ -190,7 +190,7 @@ public class SourceCompiler {
...
@@ -190,7 +190,7 @@ public class SourceCompiler {
/**
/**
* Whether the passed source can be compiled using {@link javax.script.ScriptEngineManager}.
* Whether the passed source can be compiled using {@link javax.script.ScriptEngineManager}.
*
*
* @param source the source to test.
* @param source the source to test.
* @return <code>true</code> if {@link #getCompiledScript(String)} can be called.
* @return <code>true</code> if {@link #getCompiledScript(String)} can be called.
*/
*/
...
...
h2/src/test/org/h2/test/db/AbstractBaseForCommonTableExpressions.java
浏览文件 @
3a7253d5
/*
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
test
.
db
;
package
org
.
h2
.
test
.
db
;
import
java.sql.Connection
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
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
/**
*/
* 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
setupSQL
,
String
withQuery
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
protected
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
int
expectedNumberOfRows
,
String
setupSQL
,
String
withQuery
,
deleteDb
(
"commonTableExpressionQueries"
);
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
PreparedStatement
prep
;
deleteDb
(
"commonTableExpressionQueries"
);
ResultSet
rs
;
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
PreparedStatement
prep
;
ResultSet
rs
;
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
setupSQL
);
Statement
stat
=
conn
.
createStatement
();
stat
.
close
();
stat
.
execute
(
setupSQL
);
stat
.
close
();
// close and re-open connection for one iteration to make sure the query work between connections
if
(
queryRunTries
==
closeAndReopenDatabaseConnectionOnIteration
)
{
// close and re-open connection for one iteration to make sure the query work
conn
.
close
();
// between connections
if
(
queryRunTries
==
closeAndReopenDatabaseConnectionOnIteration
)
{
conn
=
getConnection
(
"commonTableExpressionQueries"
);
conn
.
close
();
}
prep
=
conn
.
prepareStatement
(
withQuery
);
conn
=
getConnection
(
"commonTableExpressionQueries"
);
}
rs
=
prep
.
executeQuery
();
prep
=
conn
.
prepareStatement
(
withQuery
);
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
!=
null
);
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
assertEquals
(
"wrongly type column "
+
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)+
" on iteration#"
+
queryRunTries
,
assertTrue
(
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
!=
null
);
expectedColumnTypes
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnTypeName
(
columnIndex
));
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
}
assertEquals
(
"wrong type of column "
+
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
+
" on iteration #"
int
rowNdx
=
0
;
+
queryRunTries
,
while
(
rs
.
next
())
{
expectedColumnTypes
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnTypeName
(
columnIndex
));
StringBuffer
buf
=
new
StringBuffer
();
}
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
buf
.
append
(
"|"
+
rs
.
getString
(
columnIndex
));
int
rowNdx
=
0
;
}
while
(
rs
.
next
())
{
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
StringBuffer
buf
=
new
StringBuffer
();
rowNdx
++;
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
}
buf
.
append
(
"|"
+
rs
.
getString
(
columnIndex
));
}
assertEquals
(
expectedNumbeOfRows
,
rowNdx
);
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
rowNdx
++;
rs
.
close
();
}
prep
.
close
();
}
assertEquals
(
expectedNumberOfRows
,
rowNdx
);
conn
.
close
();
rs
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
prep
.
close
();
}
}
conn
.
close
();
}
deleteDb
(
"commonTableExpressionQueries"
);
}
}
h2/src/test/org/h2/test/db/TestCases.java
浏览文件 @
3a7253d5
...
@@ -302,7 +302,8 @@ public class TestCases extends TestBase {
...
@@ -302,7 +302,8 @@ public class TestCases extends TestBase {
throws
SQLException
{
throws
SQLException
{
assertThrows
(
expectedDropSuccess
?
0
:
ErrorCode
.
CANNOT_DROP_2
,
stat
)
assertThrows
(
expectedDropSuccess
?
0
:
ErrorCode
.
CANNOT_DROP_2
,
stat
)
.
execute
(
"drop table test "
+
(
restrict
?
"restrict"
:
"cascade"
));
.
execute
(
"drop table test "
+
(
restrict
?
"restrict"
:
"cascade"
));
assertThrows
(
expectedDropSuccess
?
ErrorCode
.
TABLE_OR_VIEW_NOT_FOUND_1
:
0
,
stat
).
execute
(
"select * from test"
);
assertThrows
(
expectedDropSuccess
?
ErrorCode
.
TABLE_OR_VIEW_NOT_FOUND_1
:
0
,
stat
)
.
execute
(
"select * from test"
);
}
}
private
void
testDropTableNoReference
(
final
boolean
stdDropTableRestrict
,
final
boolean
restrict
)
private
void
testDropTableNoReference
(
final
boolean
stdDropTableRestrict
,
final
boolean
restrict
)
...
...
h2/src/test/org/h2/test/db/TestFunctions.java
浏览文件 @
3a7253d5
...
@@ -2061,7 +2061,8 @@ public class TestFunctions extends TestBase implements AggregateFunction {
...
@@ -2061,7 +2061,8 @@ public class TestFunctions extends TestBase implements AggregateFunction {
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
stat
).
execute
(
"select signal('00145', 'success class is invalid')"
);
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
stat
).
execute
(
"select signal('00145', 'success class is invalid')"
);
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
stat
).
execute
(
"select signal('foo', 'SQLSTATE has 5 chars')"
);
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
stat
).
execute
(
"select signal('foo', 'SQLSTATE has 5 chars')"
);
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
stat
).
execute
(
"select signal('Ab123', 'SQLSTATE has only digits or upper-case letters')"
);
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
stat
)
.
execute
(
"select signal('Ab123', 'SQLSTATE has only digits or upper-case letters')"
);
try
{
try
{
stat
.
execute
(
"select signal('AB123', 'some custom error')"
);
stat
.
execute
(
"select signal('AB123', 'some custom error')"
);
fail
(
"Should have thrown"
);
fail
(
"Should have thrown"
);
...
...
h2/src/test/org/h2/test/db/TestGeneralCommonTableQueries.java
浏览文件 @
3a7253d5
...
@@ -78,8 +78,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -78,8 +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
);
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
));
...
@@ -93,7 +93,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -93,7 +93,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
",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
);
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
));
...
@@ -116,8 +116,8 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -116,8 +116,8 @@ 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
);
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
));
...
@@ -474,13 +474,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -474,13 +474,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
conn
.
close
();
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
deleteDb
(
"commonTableExpressionQueries"
);
}
}
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
setupSQL
=
"-- do nothing"
;
String
setupSQL
=
"-- do nothing"
;
String
withQuery
=
"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"
+
...
@@ -489,18 +489,18 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -489,18 +489,18 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
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
setupSQL
=
"-- do nothing"
;
String
setupSQL
=
"-- do nothing"
;
String
withQuery
=
"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)),"
+
...
@@ -509,31 +509,33 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -509,31 +509,33 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
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
;
config
.
mvStore
=
true
;
config
.
mvStore
=
true
;
config
.
memory
=
true
;
config
.
memory
=
true
;
config
.
mvcc
=
true
;
config
.
mvcc
=
true
;
config
.
multiThreaded
=
true
;
config
.
multiThreaded
=
true
;
String
setupSQL
=
"--no config set"
;
String
setupSQL
=
"--no config set"
;
String
withQuery
=
"select sum(n) from (\n"
String
withQuery
=
"select sum(n) from (\n"
+
" with recursive r(n) as (\n"
+
" with recursive r(n) as (\n"
...
@@ -541,15 +543,15 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
...
@@ -541,15 +543,15 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
+
" )\n"
+
" )\n"
+
" select n from r \n"
+
" select n from r \n"
+
")\n"
;
+
")\n"
;
int
maxRetries
=
10
;
int
maxRetries
=
10
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
finally
{
}
finally
{
config
=
backupConfig
;
config
=
backupConfig
;
}
}
}
}
}
}
h2/src/test/org/h2/test/db/TestPersistentCommonTableExpressions.java
浏览文件 @
3a7253d5
...
@@ -53,7 +53,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -53,7 +53,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
" */\n"
+
" */\n"
+
" /* scanCount: 1 */\n"
+
" /* scanCount: 1 */\n"
+
"WHERE BB.A IS A.VAL)"
};
"WHERE BB.A IS A.VAL)"
};
String
setupSQL
=
String
setupSQL
=
"DROP TABLE IF EXISTS A; "
"DROP TABLE IF EXISTS A; "
+
"DROP TABLE IF EXISTS B; "
+
"DROP TABLE IF EXISTS B; "
...
@@ -74,7 +74,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -74,7 +74,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"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
withQuery
=
"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"
+
...
@@ -87,14 +87,14 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -87,14 +87,14 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"FROM A \n"
+
"GROUP BY A.val"
;
"FROM A \n"
+
"GROUP BY A.val"
;
int
maxRetries
=
3
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
private
void
testPersistentRecursiveTableInCreateView
()
throws
Exception
{
private
void
testPersistentRecursiveTableInCreateView
()
throws
Exception
{
String
setu
o
SQL
=
"--SET TRACE_LEVEL_SYSTEM_OUT 3;\n"
String
setu
p
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"
...
@@ -119,7 +119,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -119,7 +119,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"), \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
withQuery
=
"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"
,
...
@@ -135,13 +135,13 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -135,13 +135,13 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"|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
,
setu
o
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setu
p
SQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
String
setupSQL
=
""
String
setupSQL
=
""
+
"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"
...
@@ -163,7 +163,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -163,7 +163,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"), \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
withQuery
=
"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
[]{
...
@@ -174,7 +174,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
...
@@ -174,7 +174,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"|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
,
setupSQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
...
...
h2/src/test/org/h2/test/db/TestTriggersConstraints.java
浏览文件 @
3a7253d5
...
@@ -506,7 +506,8 @@ public class TestTriggersConstraints extends TestBase implements Trigger {
...
@@ -506,7 +506,8 @@ public class TestTriggersConstraints extends TestBase implements Trigger {
}
else
if
(
"javascript"
.
equals
(
sourceLang
))
{
}
else
if
(
"javascript"
.
equals
(
sourceLang
))
{
String
triggerClassName
=
this
.
getClass
().
getName
()
+
"."
String
triggerClassName
=
this
.
getClass
().
getName
()
+
"."
+
TestTriggerAlterTable
.
class
.
getSimpleName
();
+
TestTriggerAlterTable
.
class
.
getSimpleName
();
final
String
body
=
"//javascript\nnew Packages."
+
triggerClassName
+
"();"
;
final
String
body
=
"//javascript\n"
+
"new Packages."
+
triggerClassName
+
"();"
;
stat
.
execute
(
"create trigger test_upd before insert on test as $$"
stat
.
execute
(
"create trigger test_upd before insert on test as $$"
+
body
+
" $$"
);
+
body
+
" $$"
);
}
else
{
}
else
{
...
...
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded2.java
浏览文件 @
3a7253d5
...
@@ -75,11 +75,11 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -75,11 +75,11 @@ public class TestMvccMultiThreaded2 extends TestBase {
// give any of the 100 threads a chance to start by yielding the processor to them
// give any of the 100 threads a chance to start by yielding the processor to them
Thread
.
yield
();
Thread
.
yield
();
// 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
();
...
@@ -91,12 +91,13 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -91,12 +91,13 @@ public class TestMvccMultiThreaded2 extends TestBase {
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
(
"totalProcessed=%d, averagePerThread=%d, averagePerThreadPerSecond=%d\n"
,
"+ INFO: TestMvccMultiThreaded2 RUN STATS threads=%d, minProcessed=%d, maxProcessed=%d, "
TEST_THREAD_COUNT
,
minProcessed
,
maxProcessed
,
totalProcessed
,
totalProcessed
/
TEST_THREAD_COUNT
,
+
"totalProcessed=%d, averagePerThread=%d, averagePerThreadPerSecond=%d\n"
,
totalProcessed
/(
TEST_THREAD_COUNT
*
TEST_TIME_SECONDS
)));
TEST_THREAD_COUNT
,
minProcessed
,
maxProcessed
,
totalProcessed
,
totalProcessed
/
TEST_THREAD_COUNT
,
totalProcessed
/
(
TEST_THREAD_COUNT
*
TEST_TIME_SECONDS
)));
}
}
IOUtils
.
closeSilently
(
conn
);
IOUtils
.
closeSilently
(
conn
);
...
@@ -107,7 +108,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -107,7 +108,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
* Worker test thread selecting for update
* Worker test thread selecting for update
*/
*/
private
class
SelectForUpdate
extends
Thread
{
private
class
SelectForUpdate
extends
Thread
{
public
int
iterationsProcessed
;
public
int
iterationsProcessed
;
@Override
@Override
...
@@ -118,10 +119,10 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -118,10 +119,10 @@ public class TestMvccMultiThreaded2 extends TestBase {
try
{
try
{
conn
=
getConnection
(
getTestName
()
+
URL
);
conn
=
getConnection
(
getTestName
()
+
URL
);
conn
.
setAutoCommit
(
false
);
conn
.
setAutoCommit
(
false
);
// give the other threads a chance to start up before going into our work loop
// give the other threads a chance to start up before going into our work loop
Thread
.
yield
();
Thread
.
yield
();
while
(!
done
)
{
while
(!
done
)
{
try
{
try
{
PreparedStatement
ps
=
conn
.
prepareStatement
(
PreparedStatement
ps
=
conn
.
prepareStatement
(
...
@@ -148,7 +149,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
...
@@ -148,7 +149,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
}
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
;
}
}
IOUtils
.
closeSilently
(
conn
);
IOUtils
.
closeSilently
(
conn
);
}
}
}
}
...
...
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
3a7253d5
...
@@ -135,7 +135,7 @@ public class TestScript extends TestBase {
...
@@ -135,7 +135,7 @@ public class TestScript extends TestBase {
}
}
for
(
String
s
:
new
String
[]
{
"with"
,
"mergeUsing"
})
{
for
(
String
s
:
new
String
[]
{
"with"
,
"mergeUsing"
})
{
testScript
(
"dml/"
+
s
+
".sql"
);
testScript
(
"dml/"
+
s
+
".sql"
);
}
}
deleteDb
(
"script"
);
deleteDb
(
"script"
);
System
.
out
.
flush
();
System
.
out
.
flush
();
}
}
...
...
h2/src/test/org/h2/test/scripts/dml/mergeUsing.sql
浏览文件 @
3a7253d5
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
-- Initial Developer: H2 Group
--
--
CREATE
TABLE
PARENT
(
ID
INT
,
NAME
VARCHAR
,
PRIMARY
KEY
(
ID
)
);
CREATE
TABLE
PARENT
(
ID
INT
,
NAME
VARCHAR
,
PRIMARY
KEY
(
ID
)
);
>
ok
>
ok
MERGE
INTO
PARENT
AS
P
MERGE
INTO
PARENT
AS
P
USING
(
SELECT
X
AS
ID
,
'Coco'
||
X
AS
NAME
FROM
SYSTEM_RANGE
(
1
,
2
)
)
AS
S
USING
(
SELECT
X
AS
ID
,
'Coco'
||
X
AS
NAME
FROM
SYSTEM_RANGE
(
1
,
2
)
)
AS
S
ON
(
P
.
ID
=
S
.
ID
AND
1
=
1
AND
S
.
ID
=
P
.
ID
)
ON
(
P
.
ID
=
S
.
ID
AND
1
=
1
AND
S
.
ID
=
P
.
ID
)
WHEN
MATCHED
THEN
WHEN
MATCHED
THEN
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
MATCHED
THEN
MATCHED
THEN
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
>
update
count
:
2
>
update
count
:
2
SELECT
*
FROM
PARENT
;
SELECT
*
FROM
PARENT
;
>
ID
NAME
>
ID
NAME
>
-- -----
>
-- -----
>
1
Coco1
>
1
Coco1
>
2
Coco2
>
2
Coco2
EXPLAIN
PLAN
EXPLAIN
PLAN
MERGE
INTO
PARENT
AS
P
MERGE
INTO
PARENT
AS
P
USING
(
SELECT
X
AS
ID
,
'Coco'
||
X
AS
NAME
FROM
SYSTEM_RANGE
(
1
,
2
)
)
AS
S
USING
(
SELECT
X
AS
ID
,
'Coco'
||
X
AS
NAME
FROM
SYSTEM_RANGE
(
1
,
2
)
)
AS
S
ON
(
P
.
ID
=
S
.
ID
AND
1
=
1
AND
S
.
ID
=
P
.
ID
)
ON
(
P
.
ID
=
S
.
ID
AND
1
=
1
AND
S
.
ID
=
P
.
ID
)
WHEN
MATCHED
THEN
WHEN
MATCHED
THEN
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
MATCHED
THEN
MATCHED
THEN
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
>
PLAN
>
PLAN
>
---------------------------------------------------------------------------------------------------------------------------------
>
---------------------------------------------------------------------------------------------------------------------------------
>
MERGE
INTO
PUBLIC
.
PARENT
(
ID
,
NAME
)
KEY
(
ID
)
SELECT
X
AS
ID
,
(
'Coco'
||
X
)
AS
NAME
FROM
SYSTEM_RANGE
(
1
,
2
)
/* PUBLIC.RANGE_INDEX */
>
MERGE
INTO
PUBLIC
.
PARENT
(
ID
,
NAME
)
KEY
(
ID
)
SELECT
X
AS
ID
,
(
'Coco'
||
X
)
AS
NAME
FROM
SYSTEM_RANGE
(
1
,
2
)
/* PUBLIC.RANGE_INDEX */
\ No newline at end of file
\ No newline at end of file
h2/src/test/org/h2/test/scripts/dml/with.sql
浏览文件 @
3a7253d5
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
-- Initial Developer: H2 Group
--
--
explain
with
recursive
r
(
n
)
as
(
explain
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
)
select
n
from
r
;
select
n
from
r
;
>
PLAN
>
PLAN
>
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
WITH
RECURSIVE
R
(
N
)
AS
(
(
SELECT
1
FROM
SYSTEM_RANGE
(
1
,
1
)
/* PUBLIC.RANGE_INDEX */
)
UNION
ALL
(
SELECT
(
N
+
1
)
FROM
PUBLIC
.
R
/* PUBLIC.R.tableScan */
WHERE
N
<
3
)
)
SELECT
N
FROM
R
R
/* null */
>
WITH
RECURSIVE
R
(
N
)
AS
(
(
SELECT
1
FROM
SYSTEM_RANGE
(
1
,
1
)
/* PUBLIC.RANGE_INDEX */
)
UNION
ALL
(
SELECT
(
N
+
1
)
FROM
PUBLIC
.
R
/* PUBLIC.R.tableScan */
WHERE
N
<
3
)
)
SELECT
N
FROM
R
R
/* null */
>
rows
:
1
>
rows
:
1
select
sum
(
n
)
from
(
select
sum
(
n
)
from
(
with
recursive
r
(
n
)
as
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
)
select
n
from
r
select
n
from
r
);
);
>
SUM
(
N
)
>
SUM
(
N
)
>
------
>
------
>
6
>
6
>
rows
:
1
>
rows
:
1
select
sum
(
n
)
from
(
select
0
)
join
(
select
sum
(
n
)
from
(
select
0
)
join
(
with
recursive
r
(
n
)
as
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
)
select
n
from
r
select
n
from
r
)
on
1
=
1
;
)
on
1
=
1
;
>
SUM
(
N
)
>
SUM
(
N
)
>
------
>
------
>
6
>
6
>
rows
:
1
>
rows
:
1
select
0
from
(
select
0
from
(
select
0
where
0
in
(
select
0
where
0
in
(
with
recursive
r
(
n
)
as
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
)
select
n
from
r
select
n
from
r
)
)
);
);
>
0
>
0
>
-
>
-
>
rows
:
0
>
rows
:
0
with
with
r0
(
n
,
k
)
as
(
select
-
1
,
0
),
r0
(
n
,
k
)
as
(
select
-
1
,
0
),
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
,
r0
.
n
as
N0
,
r1
.
n
AS
N1
,
r2
.
n
AS
n2
from
r0
inner
join
r1
ON
r1
.
k
=
r0
.
k
inner
join
r2
ON
r1
.
k
=
r2
.
k
;
select
r1
.
k
,
r0
.
n
as
N0
,
r1
.
n
AS
N1
,
r2
.
n
AS
n2
from
r0
inner
join
r1
ON
r1
.
k
=
r0
.
k
inner
join
r2
ON
r1
.
k
=
r2
.
k
;
>
K
N0
N1
N2
>
K
N0
N1
N2
>
-
-- -- --
>
-
-- -- --
>
0
-
1
1
10
>
0
-
1
1
10
>
rows
:
1
>
rows
:
1
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论