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 {
return
o1
==
o2
?
0
:
compareTableFilters
(
o1
,
o2
);
}
};
private
final
Database
database
;
private
final
Session
session
;
/**
...
...
@@ -1136,7 +1136,8 @@ public class Parser {
command
.
setQueryAlias
(
readFromAlias
(
null
,
Arrays
.
asList
(
"ON"
)));
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
(
command
.
getQueryAlias
(),
querySQLOutput
[
0
],
columnTemplateList
,
false
/* no recursion */
,
...
...
@@ -5153,24 +5154,24 @@ public class Parser {
private
Prepared
parseWith
()
{
List
<
TableView
>
viewsCreated
=
new
ArrayList
<>();
readIf
(
"RECURSIVE"
);
// this WITH statement might not be a temporary view - allow optional keyword to
tell us that
// this keyword. This feature will not be documented - H2 internal use only.
// this WITH statement might not be a temporary view - allow optional keyword to
// t
ell us that t
his keyword. This feature will not be documented - H2 internal use only.
boolean
isPersistent
=
readIf
(
"PERSISTENT"
);
// 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
())
{
isPersistent
=
true
;
}
do
{
viewsCreated
.
add
(
parseSingleCommonTableExpression
(
isPersistent
));
}
while
(
readIf
(
","
));
Prepared
p
=
null
;
// 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 )
// used in setCteCleanups
Collections
.
reverse
(
viewsCreated
);
...
...
@@ -5220,7 +5221,7 @@ public class Parser {
ArrayList
<
Column
>
columns
=
New
.
arrayList
();
String
[]
cols
=
null
;
Database
db
=
session
.
getDatabase
();
// column names are now optional - they can be inferred from the named
// query, if not supplied by user
if
(
readIf
(
"("
))
{
...
...
@@ -5231,7 +5232,7 @@ public class Parser {
columns
.
add
(
new
Column
(
c
,
Value
.
STRING
));
}
}
Table
oldViewFound
=
null
;
if
(
isPersistent
)
{
oldViewFound
=
getSchema
().
findTableOrView
(
session
,
cteViewName
);
...
...
@@ -5251,8 +5252,8 @@ public class Parser {
}
if
(
isPersistent
)
{
oldViewFound
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
oldViewFound
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
oldViewFound
);
}
else
{
session
.
removeLocalTempTable
(
oldViewFound
);
}
...
...
@@ -5275,7 +5276,7 @@ public class Parser {
Query
withQuery
=
parseSelect
();
if
(
isPersistent
)
{
withQuery
.
session
=
session
;
}
}
read
(
")"
);
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
cols
,
withQuery
,
querySQLOutput
);
...
...
@@ -5285,43 +5286,45 @@ public class Parser {
TableView
view
=
createCTEView
(
cteViewName
,
querySQLOutput
[
0
],
columnTemplateList
,
true
/* allowRecursiveQueryDetection */
,
true
/* add to session */
,
true
/* allowRecursiveQueryDetection */
,
true
/* add to session */
,
isPersistent
,
session
);
return
view
;
}
private
TableView
createCTEView
(
String
cteViewName
,
String
querySQL
,
List
<
Column
>
columnTemplateList
,
boolean
allowRecursiveQueryDetection
,
List
<
Column
>
columnTemplateList
,
boolean
allowRecursiveQueryDetection
,
boolean
addViewToSession
,
boolean
isPersistent
,
Session
targetSession
)
{
Database
db
=
targetSession
.
getDatabase
();
Schema
schema
=
getSchemaWithDefault
();
int
id
=
db
.
allocateObjectId
();
Column
[]
columnTemplateArray
=
columnTemplateList
.
toArray
(
new
Column
[
0
]);
// 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,
// 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
);
allowRecursiveQueryDetection
,
false
/* literalsChecked */
,
true
/* isTableExpression */
,
isPersistent
);
if
(!
view
.
isRecursiveQueryDetected
()
&&
allowRecursiveQueryDetection
)
{
if
(
isPersistent
)
{
db
.
addSchemaObject
(
targetSession
,
view
);
view
.
lock
(
targetSession
,
true
,
true
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
view
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
view
);
}
else
{
session
.
removeLocalTempTable
(
view
);
session
.
removeLocalTempTable
(
view
);
}
view
=
new
TableView
(
schema
,
id
,
cteViewName
,
querySQL
,
parameters
,
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
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
}
view
.
setTableExpression
(
true
);
view
.
setTemporary
(!
isPersistent
);
...
...
@@ -6104,7 +6107,7 @@ public class Parser {
ArrayList
<
Column
>
columnsToRemove
=
New
.
arrayList
();
Table
table
=
tableIfTableExists
(
schema
,
tableName
,
ifTableExists
);
// For Oracle compatibility - open bracket required
boolean
openingBracketDetected
=
readIf
(
"("
);
boolean
openingBracketDetected
=
readIf
(
"("
);
do
{
String
columnName
=
readColumnIdentifier
();
if
(
table
==
null
)
{
...
...
@@ -6118,7 +6121,7 @@ public class Parser {
}
while
(
readIf
(
","
));
if
(
openingBracketDetected
)
{
// For Oracle compatibility - close bracket
read
(
")"
);
read
(
")"
);
}
command
.
setTableName
(
tableName
);
command
.
setIfTableExists
(
ifTableExists
);
...
...
@@ -6145,7 +6148,7 @@ public class Parser {
// MySQL compatibility (optional)
readIf
(
"COLUMN"
);
// Oracle specifies (but will not require) an opening parenthesis
boolean
hasOpeningBracket
=
readIf
(
"("
);
boolean
hasOpeningBracket
=
readIf
(
"("
);
String
columnName
=
readColumnIdentifier
();
AlterTableAlterColumn
command
=
null
;
NullConstraintType
nullConstraint
=
parseNotNullConstraint
();
...
...
@@ -6754,7 +6757,7 @@ public class Parser {
/**
* Enumeration describing null constraints
*/
private
enum
NullConstraintType
{
private
enum
NullConstraintType
{
NULL_IS_ALLOWED
,
NULL_IS_NOT_ALLOWED
,
NO_NULL_CONSTRAINT_FOUND
}
...
...
@@ -6771,19 +6774,19 @@ public class Parser {
if
(
database
.
getMode
().
getEnum
()
==
ModeEnum
.
Oracle
)
{
if
(
readIf
(
"ENABLE"
))
{
// Leave constraint 'as is'
readIf
(
"VALIDATE"
);
readIf
(
"VALIDATE"
);
// Turn off constraint, allow NULLs
if
(
readIf
(
"NOVALIDATE"
))
{
if
(
readIf
(
"NOVALIDATE"
))
{
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
}
}
// Turn off constraint, allow NULLs
if
(
readIf
(
"DISABLE"
))
{
if
(
readIf
(
"DISABLE"
))
{
nullConstraint
=
NullConstraintType
.
NULL_IS_ALLOWED
;
// ignore validate
readIf
(
"VALIDATE"
);
readIf
(
"VALIDATE"
);
// 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 {
public
void
setForce
(
boolean
force
)
{
this
.
force
=
force
;
}
public
void
setTableExpression
(
boolean
isTableExpression
)
{
this
.
isTableExpression
=
isTableExpression
;
}
}
@Override
public
int
update
()
{
...
...
@@ -117,9 +117,12 @@ 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
);
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
);
view
=
new
TableView
(
getSchema
(),
id
,
viewName
,
querySQL
,
null
,
columnTemplatesAsUnknowns
,
session
,
false
/* allow recursive */
,
false
/* literalsChecked */
,
isTableExpression
,
true
);
}
}
else
{
// TODO support isTableExpression in replace function...
...
...
@@ -135,10 +138,10 @@ public class CreateView extends SchemaCommand {
}
else
{
db
.
updateMeta
(
session
,
view
);
}
// 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.
return
0
;
}
...
...
h2/src/main/org/h2/command/ddl/DropView.java
浏览文件 @
3a7253d5
...
...
@@ -68,13 +68,13 @@ public class DropView extends SchemaCommand {
}
}
}
// TODO: Where is the ConstraintReferential.CASCADE style drop processing ? It's
// supported from imported keys - but not for dependent db objects
// TODO: Where is the ConstraintReferential.CASCADE style drop processing ? It's
// supported from imported keys - but not for dependent db objects
TableView
tableView
=
(
TableView
)
view
;
ArrayList
<
Table
>
copyOfDependencies
=
new
ArrayList
<
Table
>(
tableView
.
getTables
());
view
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
...
...
h2/src/main/org/h2/command/dml/MergeUsing.java
浏览文件 @
3a7253d5
...
...
@@ -80,7 +80,7 @@ import org.h2.value.Value;
* 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.
* 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:
* We now generate a "matchSelect" query and use that to always detect
* 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 {
Table
t
=
f
.
getTable
();
TableView
tableView
=
t
.
isView
()
?
(
TableView
)
t
:
null
;
if
(
tableView
!=
null
&&
tableView
.
isRecursive
()
&&
tableView
.
isTableExpression
())
{
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.
// 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
{
buff
.
append
(
"WITH RECURSIVE "
).
append
(
t
.
getName
()).
append
(
'('
);
...
...
@@ -1074,7 +1075,7 @@ public class Select extends Query {
buff
.
appendExceptFirst
(
","
);
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;
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
>();
...
...
@@ -768,7 +768,7 @@ public class Database implements DataHandler {
Collections
.
sort
(
records
);
synchronized
(
systemSession
)
{
for
(
MetaRecord
rec
:
records
)
{
rec
.
execute
(
this
,
systemSession
,
eventListener
);
rec
.
execute
(
this
,
systemSession
,
eventListener
);
}
}
if
(
mvStore
!=
null
)
{
...
...
@@ -902,7 +902,7 @@ public class Database implements DataHandler {
}
}
/**
/**
* Lock the metadata table for updates.
*
* @param session the session
...
...
@@ -933,7 +933,7 @@ public class Database implements DataHandler {
boolean
wasLocked
=
meta
.
lock
(
session
,
true
,
true
);
return
wasLocked
;
}
/**
* Unlock the metadata table.
*
...
...
@@ -1912,7 +1912,7 @@ public class Database implements DataHandler {
t
.
getSQL
());
}
obj
.
removeChildrenAndResources
(
session
);
}
removeMeta
(
session
,
id
);
}
...
...
h2/src/main/org/h2/engine/Session.java
浏览文件 @
3a7253d5
...
...
@@ -123,7 +123,7 @@ public class Session extends SessionWithState {
private
long
modificationMetaID
=
-
1
;
private
SubQueryInfo
subQueryInfo
;
private
int
parsingView
;
private
Deque
<
String
>
viewNameStack
=
new
ArrayDeque
<
String
>();
private
Deque
<
String
>
viewNameStack
=
new
ArrayDeque
<
String
>();
private
int
preparingQueryExpression
;
private
volatile
SmallLRUCache
<
Object
,
ViewIndex
>
viewIndexCache
;
private
HashMap
<
Object
,
ViewIndex
>
subQueryIndexCache
;
...
...
@@ -229,6 +229,16 @@ public class Session extends SessionWithState {
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
)
{
// It can be recursive, thus implemented as counter.
this
.
parsingView
+=
parsingView
?
1
:
-
1
;
...
...
@@ -238,7 +248,7 @@ public class Session extends SessionWithState {
}
else
{
assert
viewName
.
equals
(
viewNameStack
.
peek
());
viewNameStack
.
pop
();
}
}
}
public
String
getParsingCreateViewName
()
{
if
(
viewNameStack
.
size
()
==
0
)
{
...
...
@@ -695,7 +705,7 @@ public class Session extends SessionWithState {
Analyze
.
analyzeTable
(
this
,
table
,
rows
,
false
);
}
// analyze can lock the meta
database
.
unlockMeta
(
this
);
database
.
unlockMeta
(
this
);
}
tablesToAnalyze
=
null
;
}
...
...
h2/src/main/org/h2/jdbc/JdbcStatementBackwardsCompat.java
浏览文件 @
3a7253d5
...
...
@@ -121,7 +121,7 @@ public interface JdbcStatementBackwardsCompat {
/**
* Enquotes the specified identifier.
*
* @param identifier
* @param identifier
* identifier to quote if required
* @param alwaysQuote
* 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 {
* 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"
),
TRACE_LOCK_WAITING_FOR
(
"waiting for"
),
TRACE_LOCK_REQUESTING_FOR
(
"requesting for"
),
...
...
@@ -81,13 +81,13 @@ public class MVTable extends TableBase {
TraceLockEvent
(
String
eventText
)
{
this
.
eventText
=
eventText
;
}
public
String
getEventText
()
{
return
eventText
;
}
}
private
static
final
String
NO_EXTRA_INFO
=
""
;
static
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<>();
...
...
@@ -428,7 +428,7 @@ public class MVTable extends TableBase {
public
boolean
isLockedExclusivelyBy
(
Session
session
)
{
return
lockExclusiveSession
==
session
;
}
@Override
public
void
unlock
(
Session
s
)
{
if
(
database
!=
null
)
{
...
...
h2/src/main/org/h2/store/fs/FilePathDisk.java
浏览文件 @
3a7253d5
...
...
@@ -299,7 +299,7 @@ public class FilePathDisk extends FilePath {
// file name with a colon
if
(
name
.
startsWith
(
CLASSPATH_PREFIX
))
{
String
fileName
=
name
.
substring
(
CLASSPATH_PREFIX
.
length
());
// Force absolute resolution in Class.getResourceAsStream
// Force absolute resolution in Class.getResourceAsStream
if
(!
fileName
.
startsWith
(
"/"
))
{
fileName
=
"/"
+
fileName
;
}
...
...
h2/src/main/org/h2/table/Table.java
浏览文件 @
3a7253d5
...
...
@@ -1239,7 +1239,7 @@ public abstract class Table extends SchemaObjectBase {
public
boolean
isMVStore
()
{
return
false
;
}
public
void
setTableExpression
(
boolean
tableExpression
)
{
this
.
tableExpression
=
tableExpression
;
}
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
3a7253d5
...
...
@@ -67,7 +67,8 @@ public class TableView extends Table {
ArrayList
<
Parameter
>
params
,
Column
[]
columnTemplates
,
Session
session
,
boolean
allowRecursive
,
boolean
literalsChecked
,
boolean
isTableExpression
,
boolean
isPersistent
)
{
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 {
session
,
recursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
DbException
e
=
recompile
(
session
,
force
,
true
);
if
(
e
!=
null
)
{
init
(
oldQuerySQL
,
null
,
oldColumnTemplates
,
session
,
oldRecursive
,
init
(
oldQuerySQL
,
null
,
oldColumnTemplates
,
session
,
oldRecursive
,
literalsChecked
,
isTableExpression
,
isPersistent
);
recompile
(
session
,
true
,
false
);
throw
e
;
...
...
@@ -98,7 +99,7 @@ public class TableView extends Table {
}
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
)
{
this
.
querySQL
=
querySQL
;
this
.
columnTemplates
=
columnTemplates
;
...
...
@@ -555,7 +556,7 @@ public class TableView extends Table {
String
querySQL
=
query
.
getPlanSQL
();
TableView
v
=
new
TableView
(
mainSchema
,
0
,
name
,
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*/
);
if
(
v
.
createException
!=
null
)
{
throw
v
.
createException
;
...
...
@@ -705,7 +706,7 @@ public class TableView extends Table {
}
return
true
;
}
public
List
<
Table
>
getTables
()
{
return
tables
;
}
...
...
@@ -713,11 +714,11 @@ public class TableView extends Table {
public
boolean
isPersistent
()
{
return
isPersistent
;
}
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
)
{
Table
recursiveTable
=
TableView
.
createShadowTableForRecursiveTableExpression
(
isPersistent
,
session
,
name
,
schema
,
Arrays
.
asList
(
columnTemplates
),
db
);
...
...
@@ -728,42 +729,44 @@ public class TableView extends Table {
for
(
Column
columnTemplate:
columnTemplates
)
{
columnNames
.
add
(
columnTemplate
.
getName
());
}
try
{
Prepared
withQuery
=
session
.
prepare
(
querySQL
,
false
,
false
);
if
(
isPersistent
)
{
withQuery
.
setSession
(
session
);
}
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
columnNames
.
toArray
(
new
String
[
1
]),
}
columnTemplateList
=
TableView
.
createQueryColumnTemplateList
(
columnNames
.
toArray
(
new
String
[
1
]),
(
Query
)
withQuery
,
querySQLOutput
);
}
finally
{
TableView
.
destroyShadowTableForRecursiveExpression
(
isPersistent
,
session
,
recursiveTable
);
}
// build with recursion turned on
TableView
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
parameters
,
columnTemplateList
.
toArray
(
columnTemplates
),
session
,
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
(
isPersistent
)
{
db
.
addSchemaObject
(
session
,
view
);
view
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
// 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...
// 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
{
session
.
removeLocalTempTable
(
view
);
session
.
removeLocalTempTable
(
view
);
}
view
=
new
TableView
(
schema
,
id
,
name
,
querySQL
,
parameters
,
columnTemplates
,
session
,
false
/* detected not recursive */
,
literalsChecked
,
isTableExpression
,
isPersistent
);
false
/* detected not recursive */
,
literalsChecked
,
isTableExpression
,
isPersistent
);
}
return
view
;
}
...
...
@@ -797,14 +800,14 @@ public class TableView extends Table {
String
columnName
=
columnNamer
.
getColumnName
(
columnExp
,
i
,
cols
);
columnTemplateList
.
add
(
new
Column
(
columnName
,
columnExp
.
getType
()));
}
return
columnTemplateList
;
}
public
static
Table
createShadowTableForRecursiveTableExpression
(
boolean
isPersistent
,
Session
targetSession
,
String
cteViewName
,
Schema
schema
,
List
<
Column
>
columns
,
Database
db
)
{
// create table data object
CreateTableData
recursiveTableData
=
new
CreateTableData
();
recursiveTableData
.
id
=
db
.
allocateObjectId
();
...
...
@@ -815,10 +818,10 @@ public class TableView extends Table {
recursiveTableData
.
persistIndexes
=
isPersistent
;
recursiveTableData
.
create
=
true
;
recursiveTableData
.
session
=
targetSession
;
// this gets a meta table lock that is not released
Table
recursiveTable
=
schema
.
createTable
(
recursiveTableData
);
if
(
isPersistent
)
{
// this unlock is to prevent lock leak from schema.createTable()
db
.
unlockMeta
(
targetSession
);
...
...
@@ -837,11 +840,11 @@ public class TableView extends Table {
if
(
isPersistent
)
{
recursiveTable
.
lock
(
targetSession
,
true
,
true
);
targetSession
.
getDatabase
().
removeSchemaObject
(
targetSession
,
recursiveTable
);
}
else
{
targetSession
.
removeLocalTempTable
(
recursiveTable
);
}
// both removeSchemaObject and removeLocalTempTable hold meta locks - release them here
targetSession
.
getDatabase
().
unlockMeta
(
targetSession
);
}
...
...
h2/src/main/org/h2/util/SourceCompiler.java
浏览文件 @
3a7253d5
...
...
@@ -190,7 +190,7 @@ public class SourceCompiler {
/**
* Whether the passed source can be compiled using {@link javax.script.ScriptEngineManager}.
*
*
* @param source the source to test.
* @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,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
db
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
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
setupSQL
,
String
withQuery
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
PreparedStatement
prep
;
ResultSet
rs
;
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
setupSQL
);
stat
.
close
();
// close and re-open connection for one iteration to make sure the query work between connections
if
(
queryRunTries
==
closeAndReopenDatabaseConnectionOnIteration
)
{
conn
.
close
();
conn
=
getConnection
(
"commonTableExpressionQueries"
);
}
prep
=
conn
.
prepareStatement
(
withQuery
);
rs
=
prep
.
executeQuery
();
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
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
));
}
int
rowNdx
=
0
;
while
(
rs
.
next
())
{
StringBuffer
buf
=
new
StringBuffer
();
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
buf
.
append
(
"|"
+
rs
.
getString
(
columnIndex
));
}
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
rowNdx
++;
}
assertEquals
(
expectedNumbeOfRows
,
rowNdx
);
rs
.
close
();
prep
.
close
();
}
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
db
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
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
expectedNumberOfRows
,
String
setupSQL
,
String
withQuery
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
PreparedStatement
prep
;
ResultSet
rs
;
for
(
int
queryRunTries
=
1
;
queryRunTries
<=
maxRetries
;
queryRunTries
++)
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
setupSQL
);
stat
.
close
();
// close and re-open connection for one iteration to make sure the query work
// between connections
if
(
queryRunTries
==
closeAndReopenDatabaseConnectionOnIteration
)
{
conn
.
close
();
conn
=
getConnection
(
"commonTableExpressionQueries"
);
}
prep
=
conn
.
prepareStatement
(
withQuery
);
rs
=
prep
.
executeQuery
();
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
assertTrue
(
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
!=
null
);
assertEquals
(
expectedColumnNames
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
));
assertEquals
(
"wrong type of column "
+
rs
.
getMetaData
().
getColumnLabel
(
columnIndex
)
+
" on iteration #"
+
queryRunTries
,
expectedColumnTypes
[
columnIndex
-
1
],
rs
.
getMetaData
().
getColumnTypeName
(
columnIndex
));
}
int
rowNdx
=
0
;
while
(
rs
.
next
())
{
StringBuffer
buf
=
new
StringBuffer
();
for
(
int
columnIndex
=
1
;
columnIndex
<=
rs
.
getMetaData
().
getColumnCount
();
columnIndex
++)
{
buf
.
append
(
"|"
+
rs
.
getString
(
columnIndex
));
}
assertEquals
(
expectedRowData
[
rowNdx
],
buf
.
toString
());
rowNdx
++;
}
assertEquals
(
expectedNumberOfRows
,
rowNdx
);
rs
.
close
();
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 {
throws
SQLException
{
assertThrows
(
expectedDropSuccess
?
0
:
ErrorCode
.
CANNOT_DROP_2
,
stat
)
.
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
)
...
...
h2/src/test/org/h2/test/db/TestFunctions.java
浏览文件 @
3a7253d5
...
...
@@ -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('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
{
stat
.
execute
(
"select signal('AB123', 'some custom error')"
);
fail
(
"Should have thrown"
);
...
...
h2/src/test/org/h2/test/db/TestGeneralCommonTableQueries.java
浏览文件 @
3a7253d5
...
...
@@ -78,8 +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
);
prep
.
setInt
(
1
,
0
);
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
...
@@ -93,7 +93,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
",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
);
prep
.
setInt
(
1
,
4
);
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
...
@@ -116,8 +116,8 @@ 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
);
prep
.
setInt
(
1
,
4
);
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
...
...
@@ -474,13 +474,13 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testSimple4RowRecursiveQuery
()
throws
Exception
{
String
[]
expectedRowData
=
new
String
[]{
"|1"
,
"|2"
,
"|3"
};
String
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
};
String
[]
expectedColumnNames
=
new
String
[]{
"N"
};
String
setupSQL
=
"-- do nothing"
;
String
withQuery
=
"with recursive r(n) as (\n"
+
"(select 1) union all (select n+1 from r where n < 3)\n"
+
...
...
@@ -489,18 +489,18 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
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
setupSQL
=
"-- 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)),"
+
...
...
@@ -509,31 +509,33 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
}
private
void
testSimple3RowRecursiveQueryWithLazyEval
()
throws
Exception
{
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
{
//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
// 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
;
config
.
mvStore
=
true
;
config
.
memory
=
true
;
config
.
mvcc
=
true
;
config
.
multiThreaded
=
true
;
String
setupSQL
=
"--no config set"
;
String
withQuery
=
"select sum(n) from (\n"
+
" with recursive r(n) as (\n"
...
...
@@ -541,15 +543,15 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
+
" )\n"
+
" select n from r \n"
+
")\n"
;
int
maxRetries
=
10
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
finally
{
config
=
backupConfig
;
}
}
}
}
h2/src/test/org/h2/test/db/TestPersistentCommonTableExpressions.java
浏览文件 @
3a7253d5
...
...
@@ -53,7 +53,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
" */\n"
+
" /* scanCount: 1 */\n"
+
"WHERE BB.A IS A.VAL)"
};
String
setupSQL
=
"DROP TABLE IF EXISTS A; "
+
"DROP TABLE IF EXISTS B; "
...
...
@@ -74,7 +74,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"INSERT INTO C VALUES('carrot', 'imperator'); "
+
"INSERT INTO C VALUES(null, 'banapple'); "
+
"INSERT INTO A VALUES('meat'); "
;
String
withQuery
=
"WITH BB as (SELECT \n"
+
"sum(1) as X, \n"
+
"a \n"
+
...
...
@@ -87,14 +87,14 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"FROM A \n"
+
"GROUP BY A.val"
;
int
maxRetries
=
3
;
int
expectedNumberOfRows
=
expectedRowData
.
length
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
private
void
testPersistentRecursiveTableInCreateView
()
throws
Exception
{
String
setu
o
SQL
=
"--SET TRACE_LEVEL_SYSTEM_OUT 3;\n"
private
void
testPersistentRecursiveTableInCreateView
()
throws
Exception
{
String
setu
p
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"
...
...
@@ -119,7 +119,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"), \n"
+
"unused_cte AS ( SELECT 1 AS unUsedColumn ) \n"
+
"SELECT sub_tree_root_id, tree_level, parent_fk, child_fk FROM tree_cte; \n"
;
String
withQuery
=
"SELECT * FROM v_my_tree"
;
int
maxRetries
=
4
;
String
[]
expectedRowData
=
new
String
[]{
"|1|0|null|1"
,
...
...
@@ -135,13 +135,13 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"|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
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
int
expectedNumberOfRows
=
11
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setu
o
SQL
,
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setu
p
SQL
,
withQuery
,
maxRetries
-
1
,
expectedColumnTypes
);
}
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
private
void
testPersistentNonRecursiveTableInCreateView
()
throws
Exception
{
String
setupSQL
=
""
+
"DROP VIEW IF EXISTS v_my_nr_tree; \n"
+
"DROP TABLE IF EXISTS my_table; \n"
...
...
@@ -163,7 +163,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
+
"), \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"
;
String
withQuery
=
"SELECT * FROM v_my_nr_tree"
;
int
maxRetries
=
6
;
String
[]
expectedRowData
=
new
String
[]{
...
...
@@ -174,7 +174,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"|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
[]
expectedColumnTypes
=
new
String
[]{
"INTEGER"
,
"INTEGER"
,
"INTEGER"
,
"INTEGER"
};
int
expectedNumberOfRows
=
5
;
testRepeatedQueryWithSetup
(
maxRetries
,
expectedRowData
,
expectedColumnNames
,
expectedNumberOfRows
,
setupSQL
,
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 {
}
else
if
(
"javascript"
.
equals
(
sourceLang
))
{
String
triggerClassName
=
this
.
getClass
().
getName
()
+
"."
+
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 $$"
+
body
+
" $$"
);
}
else
{
...
...
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded2.java
浏览文件 @
3a7253d5
...
...
@@ -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
Thread
.
yield
();
// gather stats on threads after they finished
@SuppressWarnings
(
"unused"
)
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
();
...
...
@@ -91,12 +91,13 @@ public class TestMvccMultiThreaded2 extends TestBase {
minProcessed
=
sfu
.
iterationsProcessed
;
}
}
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
)));
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
)));
}
IOUtils
.
closeSilently
(
conn
);
...
...
@@ -107,7 +108,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
* Worker test thread selecting for update
*/
private
class
SelectForUpdate
extends
Thread
{
public
int
iterationsProcessed
;
@Override
...
...
@@ -118,10 +119,10 @@ public class TestMvccMultiThreaded2 extends TestBase {
try
{
conn
=
getConnection
(
getTestName
()
+
URL
);
conn
.
setAutoCommit
(
false
);
// give the other threads a chance to start up before going into our work loop
Thread
.
yield
();
while
(!
done
)
{
try
{
PreparedStatement
ps
=
conn
.
prepareStatement
(
...
...
@@ -148,7 +149,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
}
catch
(
Exception
e
)
{
TestBase
.
logError
(
"General error from thread "
+
getName
(),
e
);
throw
e
;
}
}
IOUtils
.
closeSilently
(
conn
);
}
}
...
...
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
3a7253d5
...
...
@@ -135,7 +135,7 @@ public class TestScript extends TestBase {
}
for
(
String
s
:
new
String
[]
{
"with"
,
"mergeUsing"
})
{
testScript
(
"dml/"
+
s
+
".sql"
);
}
}
deleteDb
(
"script"
);
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,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE
TABLE
PARENT
(
ID
INT
,
NAME
VARCHAR
,
PRIMARY
KEY
(
ID
)
);
>
ok
MERGE
INTO
PARENT
AS
P
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
)
WHEN
MATCHED
THEN
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
MATCHED
THEN
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
>
update
count
:
2
SELECT
*
FROM
PARENT
;
>
ID
NAME
>
-- -----
>
1
Coco1
>
2
Coco2
EXPLAIN
PLAN
MERGE
INTO
PARENT
AS
P
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
)
WHEN
MATCHED
THEN
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
MATCHED
THEN
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
>
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 */
\ No newline at end of file
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE
TABLE
PARENT
(
ID
INT
,
NAME
VARCHAR
,
PRIMARY
KEY
(
ID
)
);
>
ok
MERGE
INTO
PARENT
AS
P
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
)
WHEN
MATCHED
THEN
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
MATCHED
THEN
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
>
update
count
:
2
SELECT
*
FROM
PARENT
;
>
ID
NAME
>
-- -----
>
1
Coco1
>
2
Coco2
EXPLAIN
PLAN
MERGE
INTO
PARENT
AS
P
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
)
WHEN
MATCHED
THEN
UPDATE
SET
P
.
NAME
=
S
.
NAME
WHERE
2
=
2
WHEN
NOT
MATCHED
THEN
INSERT
(
ID
,
NAME
)
VALUES
(
S
.
ID
,
S
.
NAME
);
>
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 */
\ 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,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
explain
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
;
>
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 */
>
rows
:
1
select
sum
(
n
)
from
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
);
>
SUM
(
N
)
>
------
>
6
>
rows
:
1
select
sum
(
n
)
from
(
select
0
)
join
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
)
on
1
=
1
;
>
SUM
(
N
)
>
------
>
6
>
rows
:
1
select
0
from
(
select
0
where
0
in
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
)
);
>
0
>
-
>
rows
:
0
with
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
)),
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
;
>
K
N0
N1
N2
>
-
-- -- --
>
0
-
1
1
10
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
explain
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
;
>
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 */
>
rows
:
1
select
sum
(
n
)
from
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
);
>
SUM
(
N
)
>
------
>
6
>
rows
:
1
select
sum
(
n
)
from
(
select
0
)
join
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
)
on
1
=
1
;
>
SUM
(
N
)
>
------
>
6
>
rows
:
1
select
0
from
(
select
0
where
0
in
(
with
recursive
r
(
n
)
as
(
(
select
1
)
union
all
(
select
n
+
1
from
r
where
n
<
3
)
)
select
n
from
r
)
);
>
0
>
-
>
rows
:
0
with
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
)),
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
;
>
K
N0
N1
N2
>
-
-- -- --
>
0
-
1
1
10
>
rows
:
1
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论