Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0bedabe6
提交
0bedabe6
authored
2月 19, 2011
作者:
james.moger@gmail.com
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
JaQu annotations, model generation, model validation, extended syntax (issue #286)
上级
e0228642
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
35 个修改的文件
包含
4293 行增加
和
108 行删除
+4293
-108
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+4
-0
AnnotationsTest.java
h2/src/test/org/h2/test/jaqu/AnnotationsTest.java
+157
-0
ModelsTest.java
h2/src/test/org/h2/test/jaqu/ModelsTest.java
+156
-0
ProductAnnotationOnly.java
h2/src/test/org/h2/test/jaqu/ProductAnnotationOnly.java
+83
-0
ProductInheritedAnnotation.java
h2/src/test/org/h2/test/jaqu/ProductInheritedAnnotation.java
+46
-0
ProductMixedAnnotation.java
h2/src/test/org/h2/test/jaqu/ProductMixedAnnotation.java
+83
-0
ProductNoCreateTable.java
h2/src/test/org/h2/test/jaqu/ProductNoCreateTable.java
+48
-0
SamplesTest.java
h2/src/test/org/h2/test/jaqu/SamplesTest.java
+30
-1
SupportedTypes.java
h2/src/test/org/h2/test/jaqu/SupportedTypes.java
+112
-0
UpdateTest.java
h2/src/test/org/h2/test/jaqu/UpdateTest.java
+39
-2
Db.java
h2/src/tools/org/h2/jaqu/Db.java
+148
-12
DbInspector.java
h2/src/tools/org/h2/jaqu/DbInspector.java
+174
-0
DbUpgrader.java
h2/src/tools/org/h2/jaqu/DbUpgrader.java
+68
-0
DbVersion.java
h2/src/tools/org/h2/jaqu/DbVersion.java
+42
-0
Declaration.java
h2/src/tools/org/h2/jaqu/Declaration.java
+21
-0
Define.java
h2/src/tools/org/h2/jaqu/Define.java
+18
-1
IncrementColumn.java
h2/src/tools/org/h2/jaqu/IncrementColumn.java
+46
-0
ModelUtils.java
h2/src/tools/org/h2/jaqu/ModelUtils.java
+343
-0
Query.java
h2/src/tools/org/h2/jaqu/Query.java
+72
-8
QueryWhere.java
h2/src/tools/org/h2/jaqu/QueryWhere.java
+14
-0
SQLDialect.java
h2/src/tools/org/h2/jaqu/SQLDialect.java
+80
-0
SQLStatement.java
h2/src/tools/org/h2/jaqu/SQLStatement.java
+32
-5
SelectTable.java
h2/src/tools/org/h2/jaqu/SelectTable.java
+2
-2
SetColumn.java
h2/src/tools/org/h2/jaqu/SetColumn.java
+39
-0
Table.java
h2/src/tools/org/h2/jaqu/Table.java
+435
-5
TableDefinition.java
h2/src/tools/org/h2/jaqu/TableDefinition.java
+298
-51
TableInspector.java
h2/src/tools/org/h2/jaqu/TableInspector.java
+695
-0
Validation.java
h2/src/tools/org/h2/jaqu/Validation.java
+113
-0
ConstantString.java
h2/src/tools/org/h2/jaqu/bytecode/ConstantString.java
+1
-1
GenerateModels.java
h2/src/tools/org/h2/jaqu/util/GenerateModels.java
+167
-0
JdbcUtils.java
h2/src/tools/org/h2/jaqu/util/JdbcUtils.java
+241
-0
StatementBuilder.java
h2/src/tools/org/h2/jaqu/util/StatementBuilder.java
+137
-0
StatementLogger.java
h2/src/tools/org/h2/jaqu/util/StatementLogger.java
+91
-0
StringUtils.java
h2/src/tools/org/h2/jaqu/util/StringUtils.java
+180
-0
Utils.java
h2/src/tools/org/h2/jaqu/util/Utils.java
+78
-20
没有找到文件。
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
0bedabe6
...
...
@@ -65,7 +65,9 @@ import org.h2.test.db.TestView;
import
org.h2.test.db.TestViewAlterTable
;
import
org.h2.test.db.TestViewDropView
;
import
org.h2.test.jaqu.AliasMapTest
;
import
org.h2.test.jaqu.AnnotationsTest
;
import
org.h2.test.jaqu.ClobTest
;
import
org.h2.test.jaqu.ModelsTest
;
import
org.h2.test.jaqu.SamplesTest
;
import
org.h2.test.jaqu.UpdateTest
;
import
org.h2.test.jdbc.TestBatchUpdates
;
...
...
@@ -588,6 +590,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
ClobTest
().
runTest
(
this
);
new
SamplesTest
().
runTest
(
this
);
new
UpdateTest
().
runTest
(
this
);
new
AnnotationsTest
().
runTest
(
this
);
new
ModelsTest
().
runTest
(
this
);
// jdbc
new
TestBatchUpdates
().
runTest
(
this
);
...
...
h2/src/test/org/h2/test/jaqu/AnnotationsTest.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
test
.
jaqu
;
import
java.util.List
;
import
org.h2.constant.ErrorCode
;
import
org.h2.jaqu.Db
;
import
org.h2.jdbc.JdbcSQLException
;
import
org.h2.test.TestBase
;
public
class
AnnotationsTest
extends
TestBase
{
/**
* This object represents a database (actually a connection to the database).
*/
//## Java 1.5 begin ##
Db
db
;
//## Java 1.5 end ##
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public
static
void
main
(
String
...
args
)
{
new
AnnotationsTest
().
test
();
}
public
void
test
()
{
//## Java 1.5 begin ##
// EventLogger.activateConsoleLogger();
db
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
db
.
insertAll
(
Product
.
getList
());
db
.
insertAll
(
ProductAnnotationOnly
.
getList
());
db
.
insertAll
(
ProductMixedAnnotation
.
getList
());
testProductAnnotationOnly
();
testProductMixedAnnotation
();
testTrimStringAnnotation
();
testCreateTableIfRequiredAnnotation
();
testColumnInheritanceAnnotation
();
db
.
close
();
// EventLogger.deactivateConsoleLogger();
//## Java 1.5 end ##
}
private
void
testProductAnnotationOnly
()
{
ProductAnnotationOnly
p
=
new
ProductAnnotationOnly
();
assertEquals
(
10
,
db
.
from
(
p
).
selectCount
());
// Test JQColumn.name="cat"
assertEquals
(
2
,
db
.
from
(
p
).
where
(
p
.
category
).
is
(
"Beverages"
).
selectCount
());
// Test JQTable.annotationsOnly=true
// public String unmappedField is ignored by JaQu
assertEquals
(
0
,
db
.
from
(
p
).
where
(
p
.
unmappedField
).
is
(
"unmapped"
).
selectCount
());
// Test JQColumn.autoIncrement=true
// 10 objects, 10 autoIncremented unique values
assertEquals
(
10
,
db
.
from
(
p
).
selectDistinct
(
p
.
autoIncrement
).
size
());
// Test JQTable.primaryKey=id
int
errorCode
=
0
;
try
{
db
.
insertAll
(
ProductAnnotationOnly
.
getList
());
}
catch
(
Throwable
t
)
{
if
(
t
.
getCause
()
instanceof
JdbcSQLException
)
{
JdbcSQLException
s
=
(
JdbcSQLException
)
t
.
getCause
();
errorCode
=
s
.
getErrorCode
();
}
}
assertEquals
(
errorCode
,
ErrorCode
.
DUPLICATE_KEY_1
);
}
private
void
testProductMixedAnnotation
()
{
ProductMixedAnnotation
p
=
new
ProductMixedAnnotation
();
// Test JQColumn.name="cat"
assertEquals
(
2
,
db
.
from
(
p
).
where
(
p
.
category
).
is
(
"Beverages"
).
selectCount
());
// Test JQTable.annotationsOnly=false
// public String mappedField is reflectively mapped by JaQu
assertEquals
(
10
,
db
.
from
(
p
).
where
(
p
.
mappedField
).
is
(
"mapped"
).
selectCount
());
// Test JQColumn.primaryKey=true
int
errorCode
=
0
;
try
{
db
.
insertAll
(
ProductMixedAnnotation
.
getList
());
}
catch
(
Throwable
t
)
{
if
(
t
.
getCause
()
instanceof
JdbcSQLException
)
{
JdbcSQLException
s
=
(
JdbcSQLException
)
t
.
getCause
();
errorCode
=
s
.
getErrorCode
();
}
}
assertEquals
(
errorCode
,
ErrorCode
.
DUPLICATE_KEY_1
);
}
private
void
testTrimStringAnnotation
()
{
ProductAnnotationOnly
p
=
new
ProductAnnotationOnly
();
ProductAnnotationOnly
prod
=
db
.
from
(
p
).
selectFirst
();
String
oldValue
=
prod
.
category
;
String
newValue
=
"01234567890123456789"
;
prod
.
category
=
newValue
;
// 2 chars exceeds field max
db
.
update
(
prod
);
ProductAnnotationOnly
newProd
=
db
.
from
(
p
)
.
where
(
p
.
productId
)
.
is
(
prod
.
productId
)
.
selectFirst
();
assertEquals
(
newValue
.
substring
(
0
,
15
),
newProd
.
category
);
newProd
.
category
=
oldValue
;
db
.
update
(
newProd
);
}
private
void
testColumnInheritanceAnnotation
()
{
ProductInheritedAnnotation
table
=
new
ProductInheritedAnnotation
();
Db
db
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
List
<
ProductInheritedAnnotation
>
inserted
=
ProductInheritedAnnotation
.
getData
();
db
.
insertAll
(
inserted
);
List
<
ProductInheritedAnnotation
>
retrieved
=
db
.
from
(
table
).
select
();
for
(
int
j
=
0
;
j
<
retrieved
.
size
();
j
++)
{
ProductInheritedAnnotation
i
=
inserted
.
get
(
j
);
ProductInheritedAnnotation
r
=
retrieved
.
get
(
j
);
assertEquals
(
i
.
category
,
r
.
category
);
assertEquals
(
i
.
mappedField
,
r
.
mappedField
);
assertEquals
(
i
.
unitsInStock
,
r
.
unitsInStock
);
assertEquals
(
i
.
unitPrice
,
r
.
unitPrice
);
assertEquals
(
i
.
name
(),
r
.
name
());
assertEquals
(
i
.
id
(),
r
.
id
());
}
db
.
close
();
}
private
void
testCreateTableIfRequiredAnnotation
()
{
// Tests JQTable.createTableIfRequired=false
int
errorCode
=
0
;
try
{
Db
noCreateDb
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
noCreateDb
.
insertAll
(
ProductNoCreateTable
.
getList
());
noCreateDb
.
close
();
}
catch
(
Throwable
e
)
{
if
(
e
.
getCause
()
instanceof
JdbcSQLException
)
{
JdbcSQLException
error
=
(
JdbcSQLException
)
e
.
getCause
();
errorCode
=
error
.
getErrorCode
();
}
}
assertTrue
(
errorCode
==
ErrorCode
.
TABLE_OR_VIEW_NOT_FOUND_1
);
}
}
h2/src/test/org/h2/test/jaqu/ModelsTest.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
test
.
jaqu
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
org.h2.jaqu.Db
;
import
org.h2.jaqu.DbInspector
;
import
org.h2.jaqu.DbUpgrader
;
import
org.h2.jaqu.DbVersion
;
import
org.h2.jaqu.Table.JQDatabase
;
import
org.h2.jaqu.Validation
;
import
org.h2.test.TestBase
;
import
org.h2.test.jaqu.SupportedTypes.SupportedTypes2
;
public
class
ModelsTest
extends
TestBase
{
/**
* This object represents a database (actually a connection to the database).
*/
//## Java 1.5 begin ##
Db
db
;
//## Java 1.5 end ##
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public
static
void
main
(
String
...
args
)
{
new
ModelsTest
().
test
();
}
public
void
test
()
{
//## Java 1.5 begin ##
db
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
db
.
insertAll
(
Product
.
getList
());
db
.
insertAll
(
ProductAnnotationOnly
.
getList
());
db
.
insertAll
(
ProductMixedAnnotation
.
getList
());
testValidateModels
();
testSupportedTypes
();
testModelGeneration
();
testDatabaseUpgrade
();
testTableUpgrade
();
db
.
close
();
//## Java 1.5 end ##
}
private
void
testValidateModels
()
{
boolean
verbose
=
false
;
DbInspector
inspector
=
new
DbInspector
(
db
);
validateModel
(
inspector
,
new
Product
(),
verbose
);
validateModel
(
inspector
,
new
ProductAnnotationOnly
(),
verbose
);
validateModel
(
inspector
,
new
ProductMixedAnnotation
(),
verbose
);
}
private
void
validateModel
(
DbInspector
inspector
,
Object
o
,
boolean
verbose
)
{
List
<
Validation
>
remarks
=
inspector
.
validateModel
(
o
,
false
);
if
(
verbose
&&
remarks
.
size
()
>
0
)
{
System
.
out
.
println
(
"Validation Remarks for "
+
o
.
getClass
().
getName
());
System
.
out
.
println
(
"============================================="
);
for
(
Validation
remark:
remarks
)
System
.
out
.
println
(
remark
);
System
.
out
.
println
();
}
for
(
Validation
remark:
remarks
)
assertFalse
(
remark
.
toString
(),
remark
.
isError
());
}
private
void
testSupportedTypes
()
{
List
<
SupportedTypes
>
original
=
SupportedTypes
.
createList
();
db
.
insertAll
(
original
);
List
<
SupportedTypes
>
retrieved
=
db
.
from
(
SupportedTypes
.
SAMPLE
).
select
();
assertEquals
(
original
.
size
(),
retrieved
.
size
());
for
(
int
i
=
0
;
i
<
original
.
size
();
i
++)
{
SupportedTypes
o
=
original
.
get
(
i
);
SupportedTypes
r
=
retrieved
.
get
(
i
);
assertTrue
(
o
.
equivalentTo
(
r
));
}
}
private
void
testModelGeneration
()
{
DbInspector
inspector
=
new
DbInspector
(
db
);
List
<
String
>
models
=
inspector
.
generateModel
(
null
,
"SupportedTypes"
,
"org.h2.test.jaqu"
,
true
,
true
);
assertEquals
(
1
,
models
.
size
());
// a poor test, but a start
assertEquals
(
1364
,
models
.
get
(
0
).
length
());
}
private
void
testDatabaseUpgrade
()
{
Db
db
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
// Insert a Database version record
db
.
insert
(
new
DbVersion
(
1
));
TestDbUpgrader
dbUpgrader
=
new
TestDbUpgrader
();
db
.
setDbUpgrader
(
dbUpgrader
);
List
<
SupportedTypes
>
original
=
SupportedTypes
.
createList
();
db
.
insertAll
(
original
);
assertEquals
(
1
,
dbUpgrader
.
oldVersion
.
get
());
assertEquals
(
2
,
dbUpgrader
.
newVersion
.
get
());
db
.
close
();
}
private
void
testTableUpgrade
()
{
Db
db
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
// Insert first, this will create version record automatically
List
<
SupportedTypes
>
original
=
SupportedTypes
.
createList
();
db
.
insertAll
(
original
);
// Reset the dbUpgrader (clears updatecheck cache)
TestDbUpgrader
dbUpgrader
=
new
TestDbUpgrader
();
db
.
setDbUpgrader
(
dbUpgrader
);
SupportedTypes2
s2
=
new
SupportedTypes2
();
List
<
SupportedTypes2
>
types
=
db
.
from
(
s2
).
select
();
assertEquals
(
10
,
types
.
size
());
assertEquals
(
1
,
dbUpgrader
.
oldVersion
.
get
());
assertEquals
(
2
,
dbUpgrader
.
newVersion
.
get
());
db
.
close
();
}
@JQDatabase
(
version
=
2
)
private
class
TestDbUpgrader
implements
DbUpgrader
{
final
AtomicInteger
oldVersion
=
new
AtomicInteger
(
0
);
final
AtomicInteger
newVersion
=
new
AtomicInteger
(
0
);
@Override
public
boolean
upgradeTable
(
Db
db
,
String
schema
,
String
table
,
int
fromVersion
,
int
toVersion
)
{
// Sample DbUpgrader just claims success on upgrade request
oldVersion
.
set
(
fromVersion
);
newVersion
.
set
(
toVersion
);
return
true
;
}
@Override
public
boolean
upgradeDatabase
(
Db
db
,
int
fromVersion
,
int
toVersion
)
{
// Sample DbUpgrader just claims success on upgrade request
oldVersion
.
set
(
fromVersion
);
newVersion
.
set
(
toVersion
);
return
true
;
}
};
}
h2/src/test/org/h2/test/jaqu/ProductAnnotationOnly.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
jaqu
;
// ## Java 1.5 begin ##
import
java.util.Arrays
;
import
java.util.List
;
import
org.h2.jaqu.Table.JQColumn
;
import
org.h2.jaqu.Table.JQIndex
;
import
org.h2.jaqu.Table.JQTable
;
/**
* A table containing product data.
*/
// ## Java 1.5 begin ##
@JQTable
(
name
=
"AnnotatedProduct"
,
primaryKey
=
"id"
)
@JQIndex
(
standard
=
"name, cat"
)
public
class
ProductAnnotationOnly
{
@JQColumn
(
name
=
"id"
)
Integer
productId
;
@JQColumn
(
name
=
"name"
)
private
String
productName
;
@JQColumn
(
name
=
"cat"
,
maxLength
=
15
,
trimString
=
true
)
String
category
;
@SuppressWarnings
(
"unused"
)
@JQColumn
private
Double
unitPrice
;
@JQColumn
private
Integer
unitsInStock
;
@JQColumn
(
autoIncrement
=
true
)
public
Integer
autoIncrement
;
public
String
unmappedField
;
public
ProductAnnotationOnly
()
{
// public constructor
}
private
ProductAnnotationOnly
(
int
productId
,
String
productName
,
String
category
,
double
unitPrice
,
int
unitsInStock
,
String
unmappedField
)
{
this
.
productId
=
productId
;
this
.
productName
=
productName
;
this
.
category
=
category
;
this
.
unitPrice
=
unitPrice
;
this
.
unitsInStock
=
unitsInStock
;
this
.
unmappedField
=
unmappedField
;
}
private
static
ProductAnnotationOnly
create
(
int
productId
,
String
productName
,
String
category
,
double
unitPrice
,
int
unitsInStock
,
String
unmappedField
)
{
return
new
ProductAnnotationOnly
(
productId
,
productName
,
category
,
unitPrice
,
unitsInStock
,
unmappedField
);
}
public
static
List
<
ProductAnnotationOnly
>
getList
()
{
String
unmappedField
=
"unmapped"
;
ProductAnnotationOnly
[]
list
=
{
create
(
1
,
"Chai"
,
"Beverages"
,
18
,
39
,
unmappedField
),
create
(
2
,
"Chang"
,
"Beverages"
,
19.0
,
17
,
unmappedField
),
create
(
3
,
"Aniseed Syrup"
,
"Condiments"
,
10.0
,
13
,
unmappedField
),
create
(
4
,
"Chef Anton's Cajun Seasoning"
,
"Condiments"
,
22.0
,
53
,
unmappedField
),
create
(
5
,
"Chef Anton's Gumbo Mix"
,
"Condiments"
,
21.3500
,
0
,
unmappedField
),
create
(
6
,
"Grandma's Boysenberry Spread"
,
"Condiments"
,
25.0
,
120
,
unmappedField
),
create
(
7
,
"Uncle Bob's Organic Dried Pears"
,
"Produce"
,
30.0
,
15
,
unmappedField
),
create
(
8
,
"Northwoods Cranberry Sauce"
,
"Condiments"
,
40.0
,
6
,
unmappedField
),
create
(
9
,
"Mishi Kobe Niku"
,
"Meat/Poultry"
,
97.0
,
29
,
unmappedField
),
create
(
10
,
"Ikura"
,
"Seafood"
,
31.0
,
31
,
unmappedField
),
};
return
Arrays
.
asList
(
list
);
}
public
String
toString
()
{
return
productName
+
": "
+
unitsInStock
;
}
}
// ## Java 1.5 end ##
h2/src/test/org/h2/test/jaqu/ProductInheritedAnnotation.java
0 → 100644
浏览文件 @
0bedabe6
package
org
.
h2
.
test
.
jaqu
;
import
java.util.Arrays
;
import
java.util.List
;
import
org.h2.jaqu.Table.JQTable
;
/**
* This class inherits all its fields from a parent class which has annotated
* columns. The JQTable annotation of the parent class is ignored and only
* the JQTable annotation of this class matters.
* <p>
* However, this table inherits JQColumns from its super class.
*/
@JQTable
(
inheritColumns
=
true
,
annotationsOnly
=
false
)
public
class
ProductInheritedAnnotation
extends
ProductMixedAnnotation
{
public
ProductInheritedAnnotation
()
{
// public constructor
}
private
ProductInheritedAnnotation
(
int
productId
,
String
productName
,
String
category
,
double
unitPrice
,
int
unitsInStock
,
String
mappedField
)
{
super
(
productId
,
productName
,
category
,
unitPrice
,
unitsInStock
,
mappedField
);
}
private
static
ProductInheritedAnnotation
create
(
int
productId
,
String
productName
,
String
category
,
double
unitPrice
,
int
unitsInStock
,
String
mappedField
)
{
return
new
ProductInheritedAnnotation
(
productId
,
productName
,
category
,
unitPrice
,
unitsInStock
,
mappedField
);
}
public
static
List
<
ProductInheritedAnnotation
>
getData
()
{
String
mappedField
=
"mapped"
;
ProductInheritedAnnotation
[]
list
=
{
create
(
1
,
"Chai"
,
"Beverages"
,
18
,
39
,
mappedField
),
create
(
2
,
"Chang"
,
"Beverages"
,
19.0
,
17
,
mappedField
),
create
(
3
,
"Aniseed Syrup"
,
"Condiments"
,
10.0
,
13
,
mappedField
),
create
(
4
,
"Chef Anton's Cajun Seasoning"
,
"Condiments"
,
22.0
,
53
,
mappedField
),
create
(
5
,
"Chef Anton's Gumbo Mix"
,
"Condiments"
,
21.3500
,
0
,
mappedField
),
create
(
6
,
"Grandma's Boysenberry Spread"
,
"Condiments"
,
25.0
,
120
,
mappedField
),
create
(
7
,
"Uncle Bob's Organic Dried Pears"
,
"Produce"
,
30.0
,
15
,
mappedField
),
create
(
8
,
"Northwoods Cranberry Sauce"
,
"Condiments"
,
40.0
,
6
,
mappedField
),
create
(
9
,
"Mishi Kobe Niku"
,
"Meat/Poultry"
,
97.0
,
29
,
mappedField
),
create
(
10
,
"Ikura"
,
"Seafood"
,
31.0
,
31
,
mappedField
),
};
return
Arrays
.
asList
(
list
);
}
}
h2/src/test/org/h2/test/jaqu/ProductMixedAnnotation.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
jaqu
;
// ## Java 1.5 begin ##
import
java.util.Arrays
;
import
java.util.List
;
import
org.h2.jaqu.Table.JQColumn
;
import
org.h2.jaqu.Table.JQIndex
;
import
org.h2.jaqu.Table.JQTable
;
/**
* A table containing product data.
*/
// ## Java 1.5 begin ##
@JQTable
(
annotationsOnly
=
false
)
@JQIndex
(
standard
=
"name,cat"
)
public
class
ProductMixedAnnotation
{
@JQColumn
(
name
=
"id"
,
primaryKey
=
true
)
private
Integer
productId
;
@JQColumn
(
name
=
"name"
)
private
String
productName
;
@JQColumn
(
name
=
"cat"
,
maxLength
=
255
)
String
category
;
public
Double
unitPrice
;
public
Integer
unitsInStock
;
public
String
mappedField
;
public
ProductMixedAnnotation
()
{
// public constructor
}
protected
ProductMixedAnnotation
(
int
productId
,
String
productName
,
String
category
,
double
unitPrice
,
int
unitsInStock
,
String
mappedField
)
{
this
.
productId
=
productId
;
this
.
productName
=
productName
;
this
.
category
=
category
;
this
.
unitPrice
=
unitPrice
;
this
.
unitsInStock
=
unitsInStock
;
this
.
mappedField
=
mappedField
;
}
private
static
ProductMixedAnnotation
create
(
int
productId
,
String
productName
,
String
category
,
double
unitPrice
,
int
unitsInStock
,
String
mappedField
)
{
return
new
ProductMixedAnnotation
(
productId
,
productName
,
category
,
unitPrice
,
unitsInStock
,
mappedField
);
}
public
static
List
<
ProductMixedAnnotation
>
getList
()
{
String
mappedField
=
"mapped"
;
ProductMixedAnnotation
[]
list
=
{
create
(
1
,
"Chai"
,
"Beverages"
,
18
,
39
,
mappedField
),
create
(
2
,
"Chang"
,
"Beverages"
,
19.0
,
17
,
mappedField
),
create
(
3
,
"Aniseed Syrup"
,
"Condiments"
,
10.0
,
13
,
mappedField
),
create
(
4
,
"Chef Anton's Cajun Seasoning"
,
"Condiments"
,
22.0
,
53
,
mappedField
),
create
(
5
,
"Chef Anton's Gumbo Mix"
,
"Condiments"
,
21.3500
,
0
,
mappedField
),
create
(
6
,
"Grandma's Boysenberry Spread"
,
"Condiments"
,
25.0
,
120
,
mappedField
),
create
(
7
,
"Uncle Bob's Organic Dried Pears"
,
"Produce"
,
30.0
,
15
,
mappedField
),
create
(
8
,
"Northwoods Cranberry Sauce"
,
"Condiments"
,
40.0
,
6
,
mappedField
),
create
(
9
,
"Mishi Kobe Niku"
,
"Meat/Poultry"
,
97.0
,
29
,
mappedField
),
create
(
10
,
"Ikura"
,
"Seafood"
,
31.0
,
31
,
mappedField
),
};
return
Arrays
.
asList
(
list
);
}
public
String
toString
()
{
return
productName
+
": "
+
unitsInStock
;
}
public
int
id
()
{
return
productId
;
}
public
String
name
()
{
return
productName
;
}
}
// ## Java 1.5 end ##
h2/src/test/org/h2/test/jaqu/ProductNoCreateTable.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
jaqu
;
// ## Java 1.5 begin ##
import
java.util.Arrays
;
import
java.util.List
;
import
org.h2.jaqu.Table.JQColumn
;
import
org.h2.jaqu.Table.JQTable
;
/**
* A table containing product data.
*/
// ## Java 1.5 begin ##
@JQTable
(
createIfRequired
=
false
)
public
class
ProductNoCreateTable
{
@SuppressWarnings
(
"unused"
)
@JQColumn
(
name
=
"id"
)
private
Integer
productId
;
@SuppressWarnings
(
"unused"
)
@JQColumn
(
name
=
"name"
)
private
String
productName
;
public
ProductNoCreateTable
()
{
// public constructor
}
private
ProductNoCreateTable
(
int
productId
,
String
productName
)
{
this
.
productId
=
productId
;
this
.
productName
=
productName
;
}
private
static
ProductNoCreateTable
create
(
int
productId
,
String
productName
)
{
return
new
ProductNoCreateTable
(
productId
,
productName
);
}
public
static
List
<
ProductNoCreateTable
>
getList
()
{
ProductNoCreateTable
[]
list
=
{
create
(
1
,
"Chai"
),
create
(
2
,
"Chang"
)
};
return
Arrays
.
asList
(
list
);
}
}
// ## Java 1.5 end ##
h2/src/test/org/h2/test/jaqu/SamplesTest.java
浏览文件 @
0bedabe6
...
...
@@ -9,9 +9,14 @@ package org.h2.test.jaqu;
import
static
org
.
h2
.
jaqu
.
Function
.
count
;
import
static
org
.
h2
.
jaqu
.
Function
.
isNull
;
import
static
org
.
h2
.
jaqu
.
Function
.
length
;
import
static
org
.
h2
.
jaqu
.
Function
.*;
import
static
org
.
h2
.
jaqu
.
Function
.
max
;
import
static
org
.
h2
.
jaqu
.
Function
.
min
;
import
static
org
.
h2
.
jaqu
.
Function
.
not
;
import
static
org
.
h2
.
jaqu
.
Function
.
sum
;
import
java.math.BigDecimal
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
org.h2.jaqu.Db
;
import
org.h2.jaqu.Filter
;
import
org.h2.test.TestBase
;
...
...
@@ -73,6 +78,8 @@ public class SamplesTest extends TestBase {
testWhereSimple2
();
testWhereSimple3
();
testReverseColumns
();
testLimitOffset
();
testKeyRetrieval
();
db
.
close
();
//## Java 1.5 end ##
}
...
...
@@ -265,6 +272,9 @@ public class SamplesTest extends TestBase {
deleted
=
db
.
from
(
p
).
delete
();
assertEquals
(
9
,
deleted
);
db
.
insertAll
(
Product
.
getList
());
db
.
deleteAll
(
Product
.
getList
());
assertEquals
(
0
,
db
.
from
(
p
).
selectCount
());
db
.
insertAll
(
Product
.
getList
());
}
private
void
testOrAndNot
()
{
...
...
@@ -376,6 +386,25 @@ public class SamplesTest extends TestBase {
assertEquals
(
1
,
count
);
}
private
void
testLimitOffset
()
{
Set
<
Integer
>
ids
=
new
HashSet
<
Integer
>();
Product
p
=
new
Product
();
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
List
<
Product
>
products
=
db
.
from
(
p
).
limit
(
2
).
offset
(
2
*
i
).
select
();
assertTrue
(
products
.
size
()
==
2
);
for
(
Product
prod:
products
)
assertTrue
(
"Failed to add product id. Duplicate?"
,
ids
.
add
(
prod
.
productId
));
}
}
private
void
testKeyRetrieval
()
{
List
<
SupportedTypes
>
list
=
SupportedTypes
.
createList
();
List
<
Long
>
keys
=
db
.
insertAllAndGetKeys
(
list
);
Set
<
Long
>
uniqueKeys
=
new
HashSet
<
Long
>();
for
(
Long
l:
keys
)
assertTrue
(
"Failed to add key. Duplicate?"
,
uniqueKeys
.
add
(
l
));
}
//## Java 1.5 end ##
/**
...
...
h2/src/test/org/h2/test/jaqu/SupportedTypes.java
0 → 100644
浏览文件 @
0bedabe6
package
org
.
h2
.
test
.
jaqu
;
import
java.math.BigDecimal
;
import
java.util.List
;
import
java.util.Random
;
import
org.h2.jaqu.Table.JQColumn
;
import
org.h2.jaqu.Table.JQTable
;
import
org.h2.util.New
;
@JQTable
(
strictTypeMapping
=
true
,
version
=
1
)
public
class
SupportedTypes
{
@JQColumn
(
primaryKey
=
true
,
autoIncrement
=
true
)
public
Integer
id
;
@JQColumn
private
Boolean
myBool
=
false
;
@JQColumn
private
Byte
myByte
=
2
;
@JQColumn
private
Short
myShort
;
@JQColumn
private
Integer
myInteger
;
@JQColumn
private
Long
myLong
;
@JQColumn
private
Float
myFloat
=
1.0f
;
@JQColumn
private
Double
myDouble
;
@JQColumn
private
BigDecimal
myBigDecimal
;
@JQColumn
private
String
myString
;
@JQColumn
private
java
.
util
.
Date
myUtilDate
;
@JQColumn
private
java
.
sql
.
Date
mySqlDate
;
@JQColumn
private
java
.
sql
.
Time
mySqlTime
;
@JQColumn
private
java
.
sql
.
Timestamp
mySqlTimestamp
;
static
SupportedTypes
SAMPLE
=
new
SupportedTypes
();
static
List
<
SupportedTypes
>
createList
()
{
List
<
SupportedTypes
>
list
=
New
.
arrayList
();
for
(
int
i
=
0
;
i
<
10
;
i
++)
list
.
add
(
randomValue
());
return
list
;
}
static
SupportedTypes
randomValue
()
{
Random
rand
=
new
Random
();
SupportedTypes
s
=
new
SupportedTypes
();
s
.
myBool
=
new
Boolean
(
rand
.
nextBoolean
());
s
.
myByte
=
new
Byte
((
byte
)
rand
.
nextInt
(
Byte
.
MAX_VALUE
));
s
.
myShort
=
new
Short
((
short
)
rand
.
nextInt
(
Short
.
MAX_VALUE
));
s
.
myInteger
=
new
Integer
(
rand
.
nextInt
());
s
.
myLong
=
new
Long
(
rand
.
nextLong
());
s
.
myFloat
=
new
Float
(
rand
.
nextFloat
());
s
.
myDouble
=
new
Double
(
rand
.
nextDouble
());
s
.
myBigDecimal
=
new
BigDecimal
(
rand
.
nextDouble
());
s
.
myString
=
Long
.
toHexString
(
rand
.
nextLong
());
s
.
myUtilDate
=
new
java
.
util
.
Date
(
rand
.
nextLong
());
s
.
mySqlDate
=
new
java
.
sql
.
Date
(
rand
.
nextLong
());
s
.
mySqlTime
=
new
java
.
sql
.
Time
(
rand
.
nextLong
());
s
.
mySqlTimestamp
=
new
java
.
sql
.
Timestamp
(
rand
.
nextLong
());
return
s
;
}
public
boolean
equivalentTo
(
SupportedTypes
s
)
{
boolean
same
=
true
;
same
&=
myBool
.
equals
(
s
.
myBool
);
same
&=
myByte
.
equals
(
s
.
myByte
);
same
&=
myShort
.
equals
(
s
.
myShort
);
same
&=
myInteger
.
equals
(
s
.
myInteger
);
same
&=
myLong
.
equals
(
s
.
myLong
);
same
&=
myFloat
.
equals
(
s
.
myFloat
);
same
&=
myDouble
.
equals
(
s
.
myDouble
);
same
&=
myBigDecimal
.
equals
(
s
.
myBigDecimal
);
same
&=
myUtilDate
.
getTime
()
==
s
.
myUtilDate
.
getTime
();
same
&=
mySqlTimestamp
.
getTime
()
==
s
.
mySqlTimestamp
.
getTime
();
same
&=
mySqlDate
.
toString
().
equals
(
s
.
mySqlDate
.
toString
());
same
&=
mySqlTime
.
toString
().
equals
(
s
.
mySqlTime
.
toString
());
return
same
;
}
/**
* Class to demonstrate TableUpdater
*
*/
@JQTable
(
name
=
"SupportedTypes"
,
version
=
2
,
inheritColumns
=
true
,
strictTypeMapping
=
true
)
public
static
class
SupportedTypes2
extends
SupportedTypes
{
public
SupportedTypes2
()
{
}
}
}
h2/src/test/org/h2/test/jaqu/UpdateTest.java
浏览文件 @
0bedabe6
...
...
@@ -6,11 +6,11 @@
*/
package
org
.
h2
.
test
.
jaqu
;
import
static
java
.
sql
.
Date
.
valueOf
;
import
org.h2.jaqu.Db
;
import
org.h2.jaqu.util.StatementLogger
;
import
org.h2.test.TestBase
;
import
static
java
.
sql
.
Date
.
valueOf
;
/**
* Tests the Db.update() function.
*
...
...
@@ -31,6 +31,8 @@ public class UpdateTest extends TestBase {
}
public
void
test
()
throws
Exception
{
// EventLogger.activateConsoleLogger();
db
=
Db
.
open
(
"jdbc:h2:mem:"
,
"sa"
,
"sa"
);
db
.
insertAll
(
Product
.
getList
());
db
.
insertAll
(
Customer
.
getList
());
...
...
@@ -40,8 +42,10 @@ public class UpdateTest extends TestBase {
testSimpleUpdateWithCombinedPrimaryKey
();
testSimpleMerge
();
testSimpleMergeWithCombinedPrimaryKey
();
testSetColumns
();
db
.
close
();
// EventLogger.deactivateConsoleLogger();
}
private
void
testSimpleUpdate
()
{
...
...
@@ -111,5 +115,38 @@ public class UpdateTest extends TestBase {
ourOrder
.
orderDate
=
valueOf
(
"2007-01-02"
);
db
.
merge
(
ourOrder
);
}
private
void
testSetColumns
()
{
Product
p
=
new
Product
();
Product
original
=
db
.
from
(
p
).
where
(
p
.
productId
).
is
(
1
).
selectFirst
();
// SetColumn on String and Double
db
.
from
(
p
)
.
set
(
p
.
productName
).
to
(
"updated"
)
.
increment
(
p
.
unitPrice
).
by
(
3.14
)
.
increment
(
p
.
unitsInStock
).
by
(
2
)
.
where
(
p
.
productId
)
.
is
(
1
).
update
();
// Confirm fields were properly updated
Product
revised
=
db
.
from
(
p
).
where
(
p
.
productId
).
is
(
1
).
selectFirst
();
assertEquals
(
"updated"
,
revised
.
productName
);
assertEquals
(
original
.
unitPrice
+
3.14
,
revised
.
unitPrice
);
assertEquals
(
original
.
unitsInStock
+
2
,
revised
.
unitsInStock
.
intValue
());
// Restore fields
db
.
from
(
p
)
.
set
(
p
.
productName
).
to
(
original
.
productName
)
.
set
(
p
.
unitPrice
).
to
(
original
.
unitPrice
)
.
increment
(
p
.
unitsInStock
).
by
(-
2
)
.
where
(
p
.
productId
).
is
(
1
).
update
();
// Confirm fields were properly restored
Product
restored
=
db
.
from
(
p
).
where
(
p
.
productId
).
is
(
1
).
selectFirst
();
assertEquals
(
original
.
productName
,
restored
.
productName
);
assertEquals
(
original
.
unitPrice
,
restored
.
unitPrice
);
assertEquals
(
original
.
unitsInStock
,
restored
.
unitsInStock
);
}
}
h2/src/tools/org/h2/jaqu/Db.java
浏览文件 @
0bedabe6
...
...
@@ -12,16 +12,21 @@ import java.sql.PreparedStatement;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.Set
;
import
javax.sql.DataSource
;
import
org.h2.jaqu.DbUpgrader.DefaultDbUpgrader
;
import
org.h2.jaqu.SQLDialect.DefaultSQLDialect
;
import
org.h2.jaqu.Table.JQDatabase
;
import
org.h2.jaqu.Table.JQTable
;
import
org.h2.jaqu.util.JdbcUtils
;
import
org.h2.jaqu.util.StringUtils
;
import
org.h2.jaqu.util.Utils
;
import
org.h2.jaqu.util.WeakIdentityHashMap
;
import
org.h2.util.JdbcUtils
;
//## Java 1.5 end ##
/**
* This class represents a connection to a database.
...
...
@@ -41,9 +46,18 @@ public class Db {
private
final
Connection
conn
;
private
final
Map
<
Class
<?>,
TableDefinition
<?>>
classMap
=
Utils
.
newHashMap
();
Db
(
Connection
conn
)
{
private
final
SQLDialect
dialect
;
private
DbUpgrader
dbUpgrader
=
new
DefaultDbUpgrader
();
private
final
Set
<
Class
<?>>
upgradeChecked
=
Utils
.
newConcurrentHashSet
();
public
Db
(
Connection
conn
)
{
this
.
conn
=
conn
;
dialect
=
getDialect
(
conn
.
getClass
().
getCanonicalName
());
}
SQLDialect
getDialect
(
String
clazz
)
{
// TODO add special cases here
return
new
DefaultSQLDialect
();
}
static
<
X
>
X
registerToken
(
X
x
,
Token
token
)
{
...
...
@@ -105,27 +119,105 @@ public class Db {
public
<
T
>
void
insert
(
T
t
)
{
Class
<?>
clazz
=
t
.
getClass
();
define
(
clazz
).
createTableIfRequired
(
this
).
insert
(
this
,
t
);
upgradeDb
().
define
(
clazz
).
createTableIfRequired
(
this
).
insert
(
this
,
t
,
false
);
}
public
<
T
>
long
insertAndGetKey
(
T
t
)
{
Class
<?>
clazz
=
t
.
getClass
();
return
upgradeDb
().
define
(
clazz
).
createTableIfRequired
(
this
).
insert
(
this
,
t
,
true
);
}
public
<
T
>
void
merge
(
T
t
)
{
Class
<?>
clazz
=
t
.
getClass
();
define
(
clazz
).
createTableIfRequired
(
this
).
merge
(
this
,
t
);
upgradeDb
().
define
(
clazz
).
createTableIfRequired
(
this
).
merge
(
this
,
t
);
}
public
<
T
>
void
update
(
T
t
)
{
Class
<?>
clazz
=
t
.
getClass
();
define
(
clazz
).
createTableIfRequired
(
this
).
update
(
this
,
t
);
upgradeDb
().
define
(
clazz
).
createTableIfRequired
(
this
).
update
(
this
,
t
);
}
public
<
T
>
void
delete
(
T
t
)
{
Class
<?>
clazz
=
t
.
getClass
();
upgradeDb
().
define
(
clazz
).
createTableIfRequired
(
this
).
delete
(
this
,
t
);
}
public
<
T
extends
Object
>
Query
<
T
>
from
(
T
alias
)
{
Class
<?>
clazz
=
alias
.
getClass
();
define
(
clazz
).
createTableIfRequired
(
this
);
upgradeDb
().
define
(
clazz
).
createTableIfRequired
(
this
);
return
Query
.
from
(
this
,
alias
);
}
Db
upgradeDb
()
{
if
(!
upgradeChecked
.
contains
(
dbUpgrader
.
getClass
()))
{
// Flag as checked immediately because calls are nested.
upgradeChecked
.
add
(
dbUpgrader
.
getClass
());
JQDatabase
model
=
dbUpgrader
.
getClass
().
getAnnotation
(
JQDatabase
.
class
);
if
(
model
.
version
()
>
0
)
{
DbVersion
v
=
new
DbVersion
();
DbVersion
dbVersion
=
// (SCHEMA="" && TABLE="") == DATABASE
from
(
v
).
where
(
v
.
schema
).
is
(
""
).
and
(
v
.
table
).
is
(
""
).
selectFirst
();
if
(
dbVersion
==
null
)
{
// Database has no version registration, but model specifies
// version. Insert DbVersion entry and return.
DbVersion
newDb
=
new
DbVersion
(
model
.
version
());
insert
(
newDb
);
}
else
{
// Database has a version registration,
// check to see if upgrade is required.
if
((
model
.
version
()
>
dbVersion
.
version
)
&&
(
dbUpgrader
!=
null
))
{
// Database is an older version than model.
boolean
success
=
dbUpgrader
.
upgradeDatabase
(
this
,
dbVersion
.
version
,
model
.
version
());
if
(
success
)
{
dbVersion
.
version
=
model
.
version
();
update
(
dbVersion
);
}
}
}
}
}
return
this
;
}
<
T
>
void
upgradeTable
(
TableDefinition
<
T
>
model
)
{
if
(!
upgradeChecked
.
contains
(
model
.
getModelClass
()))
{
// Flag as checked immediately because calls are nested.
upgradeChecked
.
add
(
model
.
getModelClass
());
<
T
>
void
createTable
(
Class
<
T
>
clazz
)
{
define
(
clazz
).
createTableIfRequired
(
this
);
if
(
model
.
tableVersion
>
0
)
{
// Table is using JaQu version tracking.
DbVersion
v
=
new
DbVersion
();
String
schema
=
StringUtils
.
isNullOrEmpty
(
model
.
schemaName
)
?
""
:
model
.
schemaName
;
DbVersion
dbVersion
=
from
(
v
).
where
(
v
.
schema
).
like
(
schema
).
and
(
v
.
table
)
.
like
(
model
.
tableName
).
selectFirst
();
if
(
dbVersion
==
null
)
{
// Table has no version registration, but model specifies
// version. Insert DbVersion entry and return.
DbVersion
newTable
=
new
DbVersion
(
model
.
tableVersion
);
newTable
.
schema
=
schema
;
newTable
.
table
=
model
.
tableName
;
insert
(
newTable
);
}
else
{
// Table has a version registration.
// Check to see if upgrade is required.
if
((
model
.
tableVersion
>
dbVersion
.
version
)
&&
(
dbUpgrader
!=
null
))
{
// Table is an older version than model.
boolean
success
=
dbUpgrader
.
upgradeTable
(
this
,
schema
,
model
.
tableName
,
dbVersion
.
version
,
model
.
tableVersion
);
if
(
success
)
{
dbVersion
.
version
=
model
.
tableVersion
;
update
(
dbVersion
);
}
}
}
}
}
}
<
T
>
TableDefinition
<
T
>
define
(
Class
<
T
>
clazz
)
{
...
...
@@ -138,10 +230,32 @@ public class Db {
T
t
=
instance
(
clazz
);
Table
table
=
(
Table
)
t
;
Define
.
define
(
def
,
table
);
}
else
if
(
clazz
.
isAnnotationPresent
(
JQTable
.
class
))
{
// Annotated Class skips Define().define() static initializer
T
t
=
instance
(
clazz
);
def
.
mapObject
(
t
);
}
}
return
def
;
}
public
synchronized
void
setDbUpgrader
(
DbUpgrader
upgrader
)
{
if
(
upgrader
==
null
)
throw
new
RuntimeException
(
"DbUpgrader may not be NULL!"
);
if
(!
upgrader
.
getClass
().
isAnnotationPresent
(
JQDatabase
.
class
))
throw
new
RuntimeException
(
"DbUpgrader must be annotated with "
+
JQDatabase
.
class
.
getSimpleName
()
+
"!"
);
this
.
dbUpgrader
=
upgrader
;
upgradeChecked
.
clear
();
}
SQLDialect
getDialect
()
{
return
dialect
;
}
public
Connection
getConnection
()
{
return
conn
;
}
public
void
close
()
{
try
{
...
...
@@ -161,8 +275,30 @@ public class Db {
}
}
PreparedStatement
prepare
(
String
sql
)
{
public
<
T
>
List
<
Long
>
insertAllAndGetKeys
(
List
<
T
>
list
)
{
List
<
Long
>
identities
=
new
ArrayList
<
Long
>();
for
(
T
t
:
list
)
{
identities
.
add
(
insertAndGetKey
(
t
));
}
return
identities
;
}
public
<
T
>
void
updateAll
(
List
<
T
>
list
)
{
for
(
T
t
:
list
)
{
update
(
t
);
}
}
public
<
T
>
void
deleteAll
(
List
<
T
>
list
)
{
for
(
T
t
:
list
)
{
delete
(
t
);
}
}
PreparedStatement
prepare
(
String
sql
,
boolean
returnKey
)
{
try
{
if
(
returnKey
)
return
conn
.
prepareStatement
(
sql
,
PreparedStatement
.
RETURN_GENERATED_KEYS
);
return
conn
.
prepareStatement
(
sql
);
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
...
...
h2/src/tools/org/h2/jaqu/DbInspector.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
import
java.sql.DatabaseMetaData
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.text.MessageFormat
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.h2.jaqu.Table.JQTable
;
import
org.h2.jaqu.util.JdbcUtils
;
import
org.h2.jaqu.util.StringUtils
;
import
org.h2.jaqu.util.Utils
;
/**
* Class to inspect a model and a database for the purposes of model validation
* and automatic model generation. This class finds the svailable schemas and
* tables and serves as the entry point for model generation and validation.
*
*/
public
class
DbInspector
{
Db
db
;
DatabaseMetaData
metadata
;
Class
<?
extends
java
.
util
.
Date
>
dateClazz
=
java
.
util
.
Date
.
class
;
public
DbInspector
(
Db
db
)
{
this
.
db
=
db
;
}
/**
* Set the preferred Date class.
* java.util.Date (default)
* java.sql.Timestamp
*
* @param dateClazz
*/
public
void
setPreferredDateClass
(
Class
<?
extends
java
.
util
.
Date
>
dateClazz
)
{
this
.
dateClazz
=
dateClazz
;
}
/**
* Generates models class skeletons for schemas and tables.
*
* @param schema (optional)
* @param table (required)
* @param packageName (optional)
* @param annotateSchema (includes schema name in annotation)
* @param trimStrings (trims strings to maxLength of column)
* @return List<String> source code models as strings
*/
public
List
<
String
>
generateModel
(
String
schema
,
String
table
,
String
packageName
,
boolean
annotateSchema
,
boolean
trimStrings
)
{
try
{
List
<
String
>
models
=
Utils
.
newArrayList
();
List
<
TableInspector
>
tables
=
findTables
(
schema
,
table
);
for
(
TableInspector
t
:
tables
)
{
t
.
read
(
metadata
);
String
model
=
t
.
generateModel
(
packageName
,
annotateSchema
,
trimStrings
);
models
.
add
(
model
);
}
return
models
;
}
catch
(
SQLException
s
)
{
throw
new
RuntimeException
(
s
);
}
}
/**
* Validates a model.
*
* @param <T> type of model
* @param model class
* @param throwOnError
* @return
*/
public
<
T
>
List
<
Validation
>
validateModel
(
T
model
,
boolean
throwOnError
)
{
try
{
TableInspector
inspector
=
findTable
(
model
);
inspector
.
read
(
metadata
);
Class
clazz
=
model
.
getClass
();
TableDefinition
<
T
>
def
=
db
.
define
(
clazz
);
return
inspector
.
validate
(
def
,
throwOnError
);
}
catch
(
SQLException
s
)
{
throw
new
RuntimeException
(
s
);
}
}
private
DatabaseMetaData
metadata
()
throws
SQLException
{
if
(
metadata
==
null
)
metadata
=
db
.
getConnection
().
getMetaData
();
return
metadata
;
}
/**
* Attempts to find a table in the database based on the model definition.
*
* @param <T>
* @param model
* @return
* @throws SQLException
*/
private
<
T
>
TableInspector
findTable
(
T
model
)
throws
SQLException
{
Class
clazz
=
model
.
getClass
();
TableDefinition
<
T
>
def
=
db
.
define
(
clazz
);
boolean
forceUpperCase
=
metadata
().
storesUpperCaseIdentifiers
();
String
sname
=
(
forceUpperCase
&&
def
.
schemaName
!=
null
)
?
def
.
schemaName
.
toUpperCase
()
:
def
.
schemaName
;
String
tname
=
forceUpperCase
?
def
.
tableName
.
toUpperCase
()
:
def
.
tableName
;
List
<
TableInspector
>
tables
=
findTables
(
sname
,
tname
);
return
tables
.
get
(
0
);
}
/**
* Returns a list of tables
*
* @param schema
* @param table
* @return
* @throws SQLException
*/
private
List
<
TableInspector
>
findTables
(
String
schema
,
String
table
)
throws
SQLException
{
ResultSet
rs
=
null
;
try
{
rs
=
metadata
().
getSchemas
();
ArrayList
<
String
>
schemaList
=
Utils
.
newArrayList
();
while
(
rs
.
next
())
schemaList
.
add
(
rs
.
getString
(
"TABLE_SCHEM"
));
JdbcUtils
.
closeSilently
(
rs
);
// Get JaQu Tables table name.
String
jaquTables
=
DbVersion
.
class
.
getAnnotation
(
JQTable
.
class
).
name
();
List
<
TableInspector
>
tables
=
Utils
.
newArrayList
();
if
(
schemaList
.
size
()
==
0
)
schemaList
.
add
(
null
);
for
(
String
s
:
schemaList
)
{
rs
=
metadata
().
getTables
(
null
,
s
,
null
,
new
String
[]
{
"TABLE"
});
while
(
rs
.
next
())
{
String
t
=
rs
.
getString
(
"TABLE_NAME"
);
if
(!
t
.
equalsIgnoreCase
(
jaquTables
))
// Ignore JaQu versions table
tables
.
add
(
new
TableInspector
(
s
,
t
,
metadata
().
storesUpperCaseIdentifiers
(),
dateClazz
));
}
}
if
(
StringUtils
.
isNullOrEmpty
(
schema
)
&&
StringUtils
.
isNullOrEmpty
(
table
))
{
// All schemas and tables
return
tables
;
}
else
{
// schema subset OR table subset OR exact match
List
<
TableInspector
>
matches
=
Utils
.
newArrayList
();
for
(
TableInspector
t
:
tables
)
{
if
(
t
.
matches
(
schema
,
table
))
matches
.
add
(
t
);
}
if
(
matches
.
size
()
==
0
)
throw
new
RuntimeException
(
MessageFormat
.
format
(
"Failed to find schema={0} table={1}"
,
schema
==
null
?
""
:
schema
,
table
==
null
?
""
:
table
));
return
matches
;
}
}
finally
{
JdbcUtils
.
closeSilently
(
rs
);
}
}
}
h2/src/tools/org/h2/jaqu/DbUpgrader.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
import
org.h2.jaqu.Table.JQDatabase
;
/**
* Interface which defines a class to handle table changes based on model
* versions.
* <p>
* An implementation of <i>DbUpgrader</i> <b>MUST</b> be annotated with the
* <i>JQDatabase</i> annotation. This annotation defines the expected database
* version number.
*
*/
public
interface
DbUpgrader
{
/**
* Defines method interface to handle database upgrades. This method is only
* called if your <i>DbUpgrader</i> implementation is annotated with
* JQDatabase.
*
* @param db
* @param fromVersion
* @param toVersion
* @return Returns <b>true</b> for successful upgrade.<br>
* If update is successful, JaQu automatically updates its version
* registry.
*/
public
boolean
upgradeDatabase
(
Db
db
,
int
fromVersion
,
int
toVersion
);
/**
* Defines method interface to handle table upgrades.
*
* @param db
* @param schema
* @param table
* @param fromVersion
* @param toVersion
* @return Returns <b>true</b> for successful upgrade.<br>
* If update is successful, JaQu automatically updates its version
* registry.
*/
public
boolean
upgradeTable
(
Db
db
,
String
schema
,
String
table
,
int
fromVersion
,
int
toVersion
);
/**
* Default Db Upgrader.
* <p>
* Does <b>NOT</b> handle upgrade requests. Instead, this throws
* RuntimeExceptions.
*/
@JQDatabase
(
version
=
0
)
public
static
class
DefaultDbUpgrader
implements
DbUpgrader
{
@Override
public
boolean
upgradeDatabase
(
Db
db
,
int
fromVersion
,
int
toVersion
)
{
throw
new
RuntimeException
(
"Please provide your own DbUpgrader implementation."
);
}
@Override
public
boolean
upgradeTable
(
Db
db
,
String
schema
,
String
table
,
int
fromVersion
,
int
toVersion
)
{
throw
new
RuntimeException
(
"Please provide your own DbUpgrader implementation."
);
}
}
}
h2/src/tools/org/h2/jaqu/DbVersion.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
import
org.h2.jaqu.Table.JQColumn
;
import
org.h2.jaqu.Table.JQTable
;
/**
* Model class for JaQu to track db and table versions.
*
*/
@JQTable
(
name
=
"_jq_versions"
,
primaryKey
=
"schemaName tableName"
,
memoryTable
=
true
)
public
class
DbVersion
{
@JQColumn
(
name
=
"schemaName"
,
allowNull
=
false
)
String
schema
=
""
;
@JQColumn
(
name
=
"tableName"
,
allowNull
=
false
)
String
table
=
""
;
@JQColumn
(
name
=
"version"
)
Integer
version
;
public
DbVersion
()
{
}
/**
* Constructor for defining a version entry.
* (SCHEMA="" && TABLE="") == DATABASE
*
* @param version
*/
public
DbVersion
(
int
version
)
{
this
.
schema
=
""
;
this
.
table
=
""
;
this
.
version
=
version
;
}
}
h2/src/tools/org/h2/jaqu/Declaration.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
/**
* Classes implementing this interface can be used as a declaration in a statement.
*/
public
interface
Declaration
{
/**
* Append the SQL to the given statement using the given query.
*
* @param stat the statement to append the SQL to
*/
//## Java 1.5 begin ##
void
appendSQL
(
SQLStatement
stat
);
//## Java 1.5 end ##
}
h2/src/tools/org/h2/jaqu/Define.java
浏览文件 @
0bedabe6
...
...
@@ -6,6 +6,8 @@
*/
package
org
.
h2
.
jaqu
;
import
org.h2.jaqu.Table.IndexType
;
/**
* This class provides utility methods to define primary keys, indexes, and set
* the name of the table.
...
...
@@ -23,7 +25,22 @@ public class Define {
public
static
void
index
(
Object
...
columns
)
{
checkInDefine
();
currentTableDefinition
.
addIndex
(
columns
);
currentTableDefinition
.
addIndex
(
IndexType
.
STANDARD
,
columns
);
}
public
static
void
uniqueIndex
(
Object
...
columns
)
{
checkInDefine
();
currentTableDefinition
.
addIndex
(
IndexType
.
UNIQUE
,
columns
);
}
public
static
void
hashIndex
(
Object
column
)
{
checkInDefine
();
currentTableDefinition
.
addIndex
(
IndexType
.
HASH
,
new
Object
[]
{
column
});
}
public
static
void
uniqueHashIndex
(
Object
column
)
{
checkInDefine
();
currentTableDefinition
.
addIndex
(
IndexType
.
UNIQUE_HASH
,
new
Object
[]
{
column
});
}
public
static
void
maxLength
(
Object
column
,
int
length
)
{
...
...
h2/src/tools/org/h2/jaqu/IncrementColumn.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
/**
* This class represents a "column=(column + 1)" token for a SET statement.
*
* @param <A> the new value data type
*/
//## Java 1.5 begin ##
public
class
IncrementColumn
<
T
,
A
>
implements
Declaration
{
private
Query
<
T
>
query
;
private
A
x
;
private
A
y
;
IncrementColumn
(
Query
<
T
>
query
,
A
x
)
{
this
.
query
=
query
;
this
.
x
=
x
;
}
public
Query
<
T
>
by
(
A
y
)
{
query
.
addDeclarationToken
(
this
);
this
.
y
=
y
;
return
query
;
}
@Override
public
void
appendSQL
(
SQLStatement
stat
)
{
query
.
appendSQL
(
stat
,
x
);
stat
.
appendSQL
(
"=("
);
query
.
appendSQL
(
stat
,
x
);
if
(
y
instanceof
Number
)
{
Number
n
=
(
Number
)
y
;
if
(
n
.
doubleValue
()
>
0
)
stat
.
appendSQL
(
"+"
);
}
stat
.
appendSQL
(
y
.
toString
());
stat
.
appendSQL
(
")"
);
}
}
//## Java 1.5 end ##
h2/src/tools/org/h2/jaqu/ModelUtils.java
0 → 100644
浏览文件 @
0bedabe6
差异被折叠。
点击展开。
h2/src/tools/org/h2/jaqu/Query.java
浏览文件 @
0bedabe6
...
...
@@ -8,6 +8,7 @@ package org.h2.jaqu;
//## Java 1.5 begin ##
import
java.lang.reflect.Field
;
import
java.sql.Clob
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
...
...
@@ -15,9 +16,10 @@ import java.util.HashMap;
import
java.util.IdentityHashMap
;
import
java.util.List
;
import
org.h2.jaqu.bytecode.ClassReader
;
import
org.h2.jaqu.util.StatementLogger
;
import
org.h2.jaqu.util.JdbcUtils
;
import
org.h2.jaqu.util.Utils
;
import
org.h2.util.JdbcUtils
;
import
org.h2.util.New
;
//import org.h2.util.JdbcUtils;
//## Java 1.5 end ##
/**
...
...
@@ -31,10 +33,13 @@ public class Query<T> {
private
Db
db
;
private
SelectTable
<
T
>
from
;
private
ArrayList
<
Token
>
conditions
=
Utils
.
newArrayList
();
private
ArrayList
<
Declaration
>
declarations
=
Utils
.
newArrayList
();
private
ArrayList
<
SelectTable
<?>>
joins
=
Utils
.
newArrayList
();
private
final
IdentityHashMap
<
Object
,
SelectColumn
<
T
>>
aliasMap
=
Utils
.
newIdentityHashMap
();
private
ArrayList
<
OrderExpression
<
T
>>
orderByList
=
Utils
.
newArrayList
();
private
Object
[]
groupByExpressions
;
private
long
limit
=
0
;
private
long
offset
=
0
;
Query
(
Db
db
)
{
this
.
db
=
db
;
...
...
@@ -60,7 +65,7 @@ public class Query<T> {
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
JdbcUtils
.
closeSilently
(
rs
);
JdbcUtils
.
closeSilently
(
rs
,
true
);
}
}
...
...
@@ -102,7 +107,7 @@ public class Query<T> {
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
JdbcUtils
.
closeSilently
(
rs
);
JdbcUtils
.
closeSilently
(
rs
,
true
);
}
return
result
;
}
...
...
@@ -112,8 +117,36 @@ public class Query<T> {
stat
.
appendSQL
(
"DELETE FROM "
);
from
.
appendSQL
(
stat
);
appendWhere
(
stat
);
StatementLogger
.
delete
(
stat
.
getSQL
());
return
stat
.
executeUpdate
();
}
public
<
A
>
SetColumn
<
T
,
A
>
set
(
A
field
)
{
return
new
SetColumn
<
T
,
A
>(
this
,
field
);
}
public
<
A
>
IncrementColumn
<
T
,
A
>
increment
(
A
field
)
{
return
new
IncrementColumn
<
T
,
A
>(
this
,
field
);
}
public
int
update
()
{
if
(
declarations
.
size
()
==
0
)
throw
new
RuntimeException
(
"Please specify SET or INCREMENT before calling Update!"
);
SQLStatement
stat
=
new
SQLStatement
(
db
);
stat
.
appendSQL
(
"UPDATE "
);
from
.
appendSQL
(
stat
);
stat
.
appendSQL
(
" SET "
);
int
i
=
0
;
for
(
Declaration
declaration:
declarations
)
{
if
(
i
++
>
0
)
{
stat
.
appendSQL
(
", "
);
}
declaration
.
appendSQL
(
stat
);
}
appendWhere
(
stat
);
StatementLogger
.
update
(
stat
.
getSQL
());
return
stat
.
executeUpdate
();
}
public
<
X
,
Z
>
List
<
X
>
selectDistinct
(
Z
x
)
{
return
select
(
x
,
true
);
...
...
@@ -147,7 +180,7 @@ public class Query<T> {
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
JdbcUtils
.
closeSilently
(
rs
);
JdbcUtils
.
closeSilently
(
rs
,
true
);
}
return
result
;
}
...
...
@@ -161,7 +194,12 @@ public class Query<T> {
try
{
while
(
rs
.
next
())
{
try
{
X
value
=
(
X
)
rs
.
getObject
(
1
);
X
value
;
Object
o
=
rs
.
getObject
(
1
);
if
(
Clob
.
class
.
isAssignableFrom
(
o
.
getClass
()))
{
value
=
(
X
)
Utils
.
convert
(
o
,
String
.
class
);
}
else
value
=
(
X
)
o
;
result
.
add
(
value
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
...
...
@@ -170,7 +208,7 @@ public class Query<T> {
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
JdbcUtils
.
closeSilently
(
rs
);
JdbcUtils
.
closeSilently
(
rs
,
true
);
}
return
result
;
}
...
...
@@ -180,7 +218,7 @@ public class Query<T> {
}
public
<
A
>
QueryWhere
<
T
>
where
(
Filter
filter
)
{
HashMap
<
String
,
Object
>
fieldMap
=
New
.
h
ashMap
();
HashMap
<
String
,
Object
>
fieldMap
=
Utils
.
newH
ashMap
();
for
(
Field
f
:
filter
.
getClass
().
getDeclaredFields
())
{
f
.
setAccessible
(
true
);
try
{
...
...
@@ -212,6 +250,23 @@ public class Query<T> {
}
//## Java 1.5 end ##
/**
* Sets the Limit and Offset of a query.
*
* @return the query
*/
//## Java 1.5 begin ##
public
Query
<
T
>
limit
(
long
limit
)
{
this
.
limit
=
limit
;
return
this
;
}
public
Query
<
T
>
offset
(
long
offset
)
{
this
.
offset
=
offset
;
return
this
;
}
//## Java 1.5 end ##
/**
* Order by a number of columns.
*
...
...
@@ -268,6 +323,10 @@ public class Query<T> {
void
addConditionToken
(
Token
condition
)
{
conditions
.
add
(
condition
);
}
void
addDeclarationToken
(
Declaration
declaration
)
{
declarations
.
add
(
declaration
);
}
void
appendWhere
(
SQLStatement
stat
)
{
if
(!
conditions
.
isEmpty
())
{
...
...
@@ -317,6 +376,11 @@ public class Query<T> {
stat
.
appendSQL
(
" "
);
}
}
if
(
limit
>
0
)
db
.
getDialect
().
appendLimit
(
stat
,
limit
);
if
(
offset
>
0
)
db
.
getDialect
().
appendOffset
(
stat
,
offset
);
StatementLogger
.
select
(
stat
.
getSQL
());
return
stat
;
}
//## Java 1.5 end ##
...
...
h2/src/tools/org/h2/jaqu/QueryWhere.java
浏览文件 @
0bedabe6
...
...
@@ -33,6 +33,16 @@ public class QueryWhere<T> {
query
.
addConditionToken
(
ConditionAndOr
.
OR
);
return
new
QueryCondition
<
T
,
A
>(
query
,
x
);
}
public
QueryWhere
<
T
>
limit
(
long
limit
)
{
query
.
limit
(
limit
);
return
this
;
}
public
QueryWhere
<
T
>
offset
(
long
offset
)
{
query
.
offset
(
offset
);
return
this
;
}
public
<
X
,
Z
>
List
<
X
>
select
(
Z
x
)
{
return
query
.
select
(
x
);
...
...
@@ -123,6 +133,10 @@ public class QueryWhere<T> {
return
query
.
delete
();
}
public
int
update
()
{
return
query
.
update
();
}
public
long
selectCount
()
{
return
query
.
selectCount
();
}
...
...
h2/src/tools/org/h2/jaqu/SQLDialect.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
import
java.text.MessageFormat
;
import
org.h2.jaqu.TableDefinition.IndexDefinition
;
import
org.h2.jaqu.util.StatementBuilder
;
import
org.h2.jaqu.util.StringUtils
;
/**
* Interface that defines points where JaQu can build different statements for
* DB-specific SQL.
*
*/
public
interface
SQLDialect
{
public
String
tableName
(
String
schema
,
String
table
);
public
String
createIndex
(
String
schema
,
String
table
,
IndexDefinition
index
);
public
void
appendLimit
(
SQLStatement
stat
,
long
limit
);
public
void
appendOffset
(
SQLStatement
stat
,
long
offset
);
/**
* Default implementation of an SQL dialect.
* Designed for an H2 database. May be suitable for others.
*/
public
static
class
DefaultSQLDialect
implements
SQLDialect
{
@Override
public
String
tableName
(
String
schema
,
String
table
)
{
if
(
StringUtils
.
isNullOrEmpty
(
schema
))
return
table
;
return
schema
+
"."
+
table
;
}
@Override
public
String
createIndex
(
String
schema
,
String
table
,
IndexDefinition
index
)
{
StatementBuilder
cols
=
new
StatementBuilder
();
for
(
String
col:
index
.
columnNames
)
{
cols
.
appendExceptFirst
(
", "
);
cols
.
append
(
col
);
}
String
type
;
switch
(
index
.
type
)
{
case
UNIQUE:
type
=
" UNIQUE "
;
break
;
case
HASH:
type
=
" HASH "
;
break
;
case
UNIQUE_HASH:
type
=
" UNIQUE HASH "
;
break
;
case
STANDARD:
default
:
type
=
" "
;
break
;
}
return
MessageFormat
.
format
(
"CREATE{0}INDEX IF NOT EXISTS {1} ON {2}({3})"
,
type
,
index
.
indexName
,
table
,
cols
);
}
@Override
public
void
appendLimit
(
SQLStatement
stat
,
long
limit
)
{
stat
.
appendSQL
(
" LIMIT "
+
limit
);
}
@Override
public
void
appendOffset
(
SQLStatement
stat
,
long
offset
)
{
stat
.
appendSQL
(
" OFFSET "
+
offset
);
}
}
}
h2/src/tools/org/h2/jaqu/SQLStatement.java
浏览文件 @
0bedabe6
...
...
@@ -11,6 +11,7 @@ import java.sql.PreparedStatement;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
org.h2.jaqu.util.JdbcUtils
;
//## Java 1.5 end ##
/**
...
...
@@ -37,6 +38,10 @@ public class SQLStatement {
sql
=
null
;
return
this
;
}
public
SQLStatement
appendTable
(
String
schema
,
String
table
)
{
return
appendSQL
(
db
.
getDialect
().
tableName
(
schema
,
table
));
}
String
getSQL
()
{
if
(
sql
==
null
)
{
...
...
@@ -49,20 +54,42 @@ public class SQLStatement {
params
.
add
(
o
);
return
this
;
}
ResultSet
executeQuery
()
{
try
{
return
prepare
().
executeQuery
();
return
prepare
(
false
).
executeQuery
();
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
int
executeUpdate
()
{
PreparedStatement
ps
=
null
;
try
{
ps
=
prepare
(
false
);
return
ps
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
JdbcUtils
.
closeSilently
(
ps
);
}
}
long
executeInsert
()
{
PreparedStatement
ps
=
null
;
try
{
return
prepare
().
executeUpdate
();
ps
=
prepare
(
true
);
ps
.
executeUpdate
();
long
identity
=
-
1
;
ResultSet
rs
=
ps
.
getGeneratedKeys
();
if
(
rs
!=
null
&&
rs
.
next
())
identity
=
rs
.
getLong
(
1
);
JdbcUtils
.
closeSilently
(
rs
);
return
identity
;
}
catch
(
SQLException
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
JdbcUtils
.
closeSilently
(
ps
);
}
}
...
...
@@ -74,8 +101,8 @@ public class SQLStatement {
}
}
private
PreparedStatement
prepare
()
{
PreparedStatement
prep
=
db
.
prepare
(
getSQL
());
private
PreparedStatement
prepare
(
boolean
returnIdentity
)
{
PreparedStatement
prep
=
db
.
prepare
(
getSQL
()
,
returnIdentity
);
for
(
int
i
=
0
;
i
<
params
.
size
();
i
++)
{
Object
o
=
params
.
get
(
i
);
setValue
(
prep
,
i
+
1
,
o
);
...
...
h2/src/tools/org/h2/jaqu/SelectTable.java
浏览文件 @
0bedabe6
...
...
@@ -55,9 +55,9 @@ class SelectTable <T> {
void
appendSQL
(
SQLStatement
stat
)
{
if
(
query
.
isJoin
())
{
stat
.
append
SQL
(
aliasDef
.
tableName
+
" AS "
+
as
);
stat
.
append
Table
(
aliasDef
.
schemaName
,
aliasDef
.
tableName
).
appendSQL
(
" AS "
+
as
);
}
else
{
stat
.
append
SQL
(
aliasDef
.
tableName
);
stat
.
append
Table
(
aliasDef
.
schemaName
,
aliasDef
.
tableName
);
}
}
...
...
h2/src/tools/org/h2/jaqu/SetColumn.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
/**
* This class represents a "column=value" token for a SET statement.
*
* @param <A> the new value data type
*/
//## Java 1.5 begin ##
public
class
SetColumn
<
T
,
A
>
implements
Declaration
{
private
Query
<
T
>
query
;
private
A
x
;
private
A
y
;
SetColumn
(
Query
<
T
>
query
,
A
x
)
{
this
.
query
=
query
;
this
.
x
=
x
;
}
public
Query
<
T
>
to
(
A
y
)
{
query
.
addDeclarationToken
(
this
);
this
.
y
=
y
;
return
query
;
}
@Override
public
void
appendSQL
(
SQLStatement
stat
)
{
query
.
appendSQL
(
stat
,
x
);
stat
.
appendSQL
(
"=?"
);
stat
.
addParameter
(
y
);
}
}
//## Java 1.5 end ##
h2/src/tools/org/h2/jaqu/Table.java
浏览文件 @
0bedabe6
差异被折叠。
点击展开。
h2/src/tools/org/h2/jaqu/TableDefinition.java
浏览文件 @
0bedabe6
差异被折叠。
点击展开。
h2/src/tools/org/h2/jaqu/TableInspector.java
0 → 100644
浏览文件 @
0bedabe6
差异被折叠。
点击展开。
h2/src/tools/org/h2/jaqu/Validation.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
;
import
org.h2.jaqu.TableDefinition.FieldDefinition
;
import
org.h2.jaqu.TableInspector.ColumnInspector
;
import
org.h2.jaqu.util.StringUtils
;
/**
* A Validation Remark is a result of running a model validation.
* <p>
* Each remark has a level, associated component (schema, table, column, index),
* and a message.
*
*/
public
class
Validation
{
public
static
Validation
CONSIDER
(
String
table
,
String
type
,
String
message
)
{
return
new
Validation
(
Level
.
CONSIDER
,
table
,
type
,
message
);
}
public
static
Validation
CONSIDER
(
String
table
,
ColumnInspector
col
,
String
message
)
{
return
new
Validation
(
Level
.
CONSIDER
,
table
,
col
,
message
);
}
public
static
Validation
WARN
(
String
table
,
ColumnInspector
col
,
String
message
)
{
return
new
Validation
(
Level
.
WARN
,
table
,
col
,
message
);
}
public
static
Validation
WARN
(
String
table
,
String
type
,
String
message
)
{
return
new
Validation
(
Level
.
WARN
,
table
,
type
,
message
);
}
public
static
Validation
ERROR
(
String
table
,
ColumnInspector
col
,
String
message
)
{
return
new
Validation
(
Level
.
ERROR
,
table
,
col
,
message
);
}
public
static
Validation
ERROR
(
String
table
,
String
type
,
String
message
)
{
return
new
Validation
(
Level
.
ERROR
,
table
,
type
,
message
);
}
public
static
Validation
ERROR
(
String
table
,
FieldDefinition
field
,
String
message
)
{
return
new
Validation
(
Level
.
ERROR
,
table
,
field
,
message
);
}
public
static
enum
Level
{
CONSIDER
,
WARN
,
ERROR
;
}
Level
level
;
String
table
;
String
fieldType
;
String
fieldName
;
String
message
;
private
Validation
(
Level
level
,
String
table
,
String
type
,
String
message
)
{
this
.
level
=
level
;
this
.
table
=
table
;
this
.
fieldType
=
type
;
this
.
fieldName
=
""
;
this
.
message
=
message
;
}
private
Validation
(
Level
level
,
String
table
,
FieldDefinition
field
,
String
message
)
{
this
.
level
=
level
;
this
.
table
=
table
;
this
.
fieldType
=
field
.
dataType
;
this
.
fieldName
=
field
.
columnName
;
this
.
message
=
message
;
}
private
Validation
(
Level
level
,
String
table
,
ColumnInspector
col
,
String
message
)
{
this
.
level
=
level
;
this
.
table
=
table
;
this
.
fieldType
=
col
.
type
;
this
.
fieldName
=
col
.
name
;
this
.
message
=
message
;
}
public
Validation
throwError
(
boolean
throwOnError
)
{
if
(
throwOnError
&&
isError
())
throw
new
RuntimeException
(
toString
());
return
this
;
}
public
boolean
isError
()
{
return
level
.
equals
(
Level
.
ERROR
);
}
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
StringUtils
.
pad
(
level
.
name
(),
9
,
" "
,
true
));
sb
.
append
(
StringUtils
.
pad
(
table
,
25
,
" "
,
true
));
sb
.
append
(
StringUtils
.
pad
(
fieldName
,
20
,
" "
,
true
));
sb
.
append
(
' '
);
sb
.
append
(
message
);
return
sb
.
toString
();
}
public
String
toCSVString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
level
.
name
()).
append
(
','
);
sb
.
append
(
table
).
append
(
','
);
sb
.
append
(
fieldType
).
append
(
','
);
sb
.
append
(
fieldName
).
append
(
','
);
sb
.
append
(
message
);
return
sb
.
toString
();
}
}
h2/src/tools/org/h2/jaqu/bytecode/ConstantString.java
浏览文件 @
0bedabe6
...
...
@@ -8,7 +8,7 @@ package org.h2.jaqu.bytecode;
import
org.h2.jaqu.Query
;
import
org.h2.jaqu.SQLStatement
;
import
org.h2.util.StringUtils
;
import
org.h2.
jaqu.
util.StringUtils
;
/**
* A string constant.
...
...
h2/src/tools/org/h2/jaqu/util/GenerateModels.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
.
util
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.PrintStream
;
import
java.io.PrintWriter
;
import
java.io.Writer
;
import
java.sql.Connection
;
import
java.sql.DriverManager
;
import
java.sql.SQLException
;
import
java.util.List
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
org.h2.jaqu.Db
;
import
org.h2.jaqu.DbInspector
;
/**
* Generates JaQu models.
*
*/
public
class
GenerateModels
{
/**
* The output stream where this tool writes to.
*/
protected
PrintStream
out
=
System
.
out
;
public
static
void
main
(
String
...
args
)
throws
SQLException
{
new
GenerateModels
().
runTool
(
args
);
}
public
void
runTool
(
String
...
args
)
throws
SQLException
{
String
url
=
null
;
String
user
=
"sa"
;
String
password
=
""
;
String
schema
=
null
;
String
table
=
null
;
String
packageName
=
""
;
String
folder
=
null
;
boolean
annotateSchema
=
true
;
boolean
trimStrings
=
false
;
for
(
int
i
=
0
;
args
!=
null
&&
i
<
args
.
length
;
i
++)
{
String
arg
=
args
[
i
];
if
(
arg
.
equals
(
"-url"
))
{
url
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-user"
))
{
user
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-password"
))
{
password
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-schema"
))
{
schema
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-table"
))
{
table
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-package"
))
{
packageName
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-folder"
))
{
folder
=
args
[++
i
];
}
else
if
(
arg
.
equals
(
"-annotateSchema"
))
{
try
{
annotateSchema
=
Boolean
.
parseBoolean
(
args
[++
i
]);
}
catch
(
Throwable
t
)
{
throw
new
SQLException
(
"Can not parse -annotateSchema value"
);
}
}
else
if
(
arg
.
equals
(
"-trimStrings"
))
{
try
{
trimStrings
=
Boolean
.
parseBoolean
(
args
[++
i
]);
}
catch
(
Throwable
t
)
{
throw
new
SQLException
(
"Can not parse -trimStrings value"
);
}
}
else
{
throwUnsupportedOption
(
arg
);
}
}
if
(
url
==
null
)
{
throw
new
SQLException
(
"URL not set"
);
}
execute
(
url
,
user
,
password
,
schema
,
table
,
packageName
,
folder
,
annotateSchema
,
trimStrings
);
}
/**
* Generates models from the database.
*
* @param url the database URL
* @param user the user name
* @param password the password
* @param schema the schema to read from. null for all schemas.
* @param table the table to model. null for all tables within schema.
* @param packageName the package name of the model classes.
* @param folder destination folder for model classes (package path not included)
* @param annotateSchema includes the schema in the table model annotations
* @param trimStrings automatically trim strings that exceed maxLength
*/
public
static
void
execute
(
String
url
,
String
user
,
String
password
,
String
schema
,
String
table
,
String
packageName
,
String
folder
,
boolean
annotateSchema
,
boolean
trimStrings
)
throws
SQLException
{
Connection
conn
=
null
;
try
{
org
.
h2
.
Driver
.
load
();
conn
=
DriverManager
.
getConnection
(
url
,
user
,
password
);
Db
db
=
Db
.
open
(
url
,
user
,
password
.
toCharArray
());
DbInspector
inspector
=
new
DbInspector
(
db
);
List
<
String
>
models
=
inspector
.
generateModel
(
schema
,
table
,
packageName
,
annotateSchema
,
trimStrings
);
File
parentFile
;
if
(
StringUtils
.
isNullOrEmpty
(
folder
))
parentFile
=
new
File
(
System
.
getProperty
(
"user.dir"
));
else
parentFile
=
new
File
(
folder
);
parentFile
.
mkdirs
();
Pattern
p
=
Pattern
.
compile
(
"class ([a-zA-Z0-9]+)"
);
for
(
String
model
:
models
)
{
Matcher
m
=
p
.
matcher
(
model
);
if
(
m
.
find
())
{
String
className
=
m
.
group
().
substring
(
"class"
.
length
()).
trim
();
File
classFile
=
new
File
(
parentFile
,
className
+
".java"
);
Writer
o
=
new
FileWriter
(
classFile
,
false
);
PrintWriter
writer
=
new
PrintWriter
(
new
BufferedWriter
(
o
));
writer
.
write
(
model
);
writer
.
close
();
System
.
out
.
println
(
"Generated "
+
classFile
.
getAbsolutePath
());
}
}
}
catch
(
SQLException
s
)
{
throw
s
;
}
catch
(
IOException
i
)
{
throw
new
SQLException
(
i
);
}
finally
{
JdbcUtils
.
closeSilently
(
conn
);
}
}
/**
* Throw a SQLException saying this command line option is not supported.
*
* @param option the unsupported option
* @return this method never returns normally
*/
protected
SQLException
throwUnsupportedOption
(
String
option
)
throws
SQLException
{
showUsage
();
throw
new
SQLException
(
"Unsupported option: "
+
option
);
}
protected
void
showUsage
()
{
out
.
println
(
"GenerateModels"
);
out
.
println
(
"Usage: java "
+
getClass
().
getName
());
out
.
println
();
out
.
println
(
"(*) -url jdbc:h2:~test"
);
out
.
println
(
" -user <string>"
);
out
.
println
(
" -password <string>"
);
out
.
println
(
" -schema <string>"
);
out
.
println
(
" -table <string>"
);
out
.
println
(
" -package <string>"
);
out
.
println
(
" -folder <string>"
);
out
.
println
(
" -annotateSchema <boolean>"
);
out
.
println
(
" -trimStrings <boolean>"
);
}
}
h2/src/tools/org/h2/jaqu/util/JdbcUtils.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
jaqu
.
util
;
import
java.sql.Connection
;
import
java.sql.DriverManager
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.util.Properties
;
import
javax.naming.Context
;
import
javax.sql.DataSource
;
import
javax.sql.XAConnection
;
/**
* This is a utility class with JDBC helper functions.
*/
public
class
JdbcUtils
{
private
static
final
String
[]
DRIVERS
=
{
"h2:"
,
"org.h2.Driver"
,
"Cache:"
,
"com.intersys.jdbc.CacheDriver"
,
"daffodilDB://"
,
"in.co.daffodil.db.rmi.RmiDaffodilDBDriver"
,
"daffodil"
,
"in.co.daffodil.db.jdbc.DaffodilDBDriver"
,
"db2:"
,
"COM.ibm.db2.jdbc.net.DB2Driver"
,
"derby:net:"
,
"org.apache.derby.jdbc.ClientDriver"
,
"derby://"
,
"org.apache.derby.jdbc.ClientDriver"
,
"derby:"
,
"org.apache.derby.jdbc.EmbeddedDriver"
,
"FrontBase:"
,
"com.frontbase.jdbc.FBJDriver"
,
"firebirdsql:"
,
"org.firebirdsql.jdbc.FBDriver"
,
"hsqldb:"
,
"org.hsqldb.jdbcDriver"
,
"informix-sqli:"
,
"com.informix.jdbc.IfxDriver"
,
"jtds:"
,
"net.sourceforge.jtds.jdbc.Driver"
,
"microsoft:"
,
"com.microsoft.jdbc.sqlserver.SQLServerDriver"
,
"mimer:"
,
"com.mimer.jdbc.Driver"
,
"mysql:"
,
"com.mysql.jdbc.Driver"
,
"odbc:"
,
"sun.jdbc.odbc.JdbcOdbcDriver"
,
"oracle:"
,
"oracle.jdbc.driver.OracleDriver"
,
"pervasive:"
,
"com.pervasive.jdbc.v2.Driver"
,
"pointbase:micro:"
,
"com.pointbase.me.jdbc.jdbcDriver"
,
"pointbase:"
,
"com.pointbase.jdbc.jdbcUniversalDriver"
,
"postgresql:"
,
"org.postgresql.Driver"
,
"sybase:"
,
"com.sybase.jdbc3.jdbc.SybDriver"
,
"sqlserver:"
,
"com.microsoft.sqlserver.jdbc.SQLServerDriver"
,
"teradata:"
,
"com.ncr.teradata.TeraDriver"
,
};
private
JdbcUtils
()
{
// utility class
}
/**
* Close a statement without throwing an exception.
*
* @param stat the statement or null
*/
public
static
void
closeSilently
(
Statement
stat
)
{
if
(
stat
!=
null
)
{
try
{
stat
.
close
();
}
catch
(
SQLException
e
)
{
// ignore
}
}
}
/**
* Close a connection without throwing an exception.
*
* @param conn the connection or null
*/
public
static
void
closeSilently
(
Connection
conn
)
{
if
(
conn
!=
null
)
{
try
{
conn
.
close
();
}
catch
(
SQLException
e
)
{
// ignore
}
}
}
/**
* Close a result set without throwing an exception.
*
* @param rs the result set or null
*/
public
static
void
closeSilently
(
ResultSet
rs
)
{
closeSilently
(
rs
,
false
);
}
/**
* Close a result set, and optionally its statement without throwing an
* exception.
*
* @param rs the result set or null
*/
public
static
void
closeSilently
(
ResultSet
rs
,
boolean
closeStatement
)
{
if
(
rs
!=
null
)
{
Statement
stat
=
null
;
if
(
closeStatement
)
{
try
{
stat
=
rs
.
getStatement
();
}
catch
(
SQLException
e
)
{
//ignore
}
}
try
{
rs
.
close
();
}
catch
(
SQLException
e
)
{
// ignore
}
closeSilently
(
stat
);
}
}
/**
* Close an XA connection set without throwing an exception.
*
* @param conn the XA connection or null
*/
//## Java 1.4 begin ##
public
static
void
closeSilently
(
XAConnection
conn
)
{
if
(
conn
!=
null
)
{
try
{
conn
.
close
();
}
catch
(
SQLException
e
)
{
// ignore
}
}
}
//## Java 1.4 end ##
/**
* Open a new database connection with the given settings.
*
* @param driver the driver class name
* @param url the database URL
* @param user the user name
* @param password the password
* @return the database connection
*/
public
static
Connection
getConnection
(
String
driver
,
String
url
,
String
user
,
String
password
)
throws
SQLException
{
Properties
prop
=
new
Properties
();
if
(
user
!=
null
)
{
prop
.
setProperty
(
"user"
,
user
);
}
if
(
password
!=
null
)
{
prop
.
setProperty
(
"password"
,
password
);
}
return
getConnection
(
driver
,
url
,
prop
);
}
/**
* Escape table or schema patterns used for DatabaseMetaData functions.
*
* @param pattern the pattern
* @return the escaped pattern
*/
public
static
String
escapeMetaDataPattern
(
String
pattern
)
{
if
(
pattern
==
null
||
pattern
.
length
()
==
0
)
{
return
pattern
;
}
return
StringUtils
.
replaceAll
(
pattern
,
"\\"
,
"\\\\"
);
}
/**
* Open a new database connection with the given settings.
*
* @param driver the driver class name
* @param url the database URL
* @param prop the properties containing at least the user name and password
* @return the database connection
*/
public
static
Connection
getConnection
(
String
driver
,
String
url
,
Properties
prop
)
throws
SQLException
{
if
(
StringUtils
.
isNullOrEmpty
(
driver
))
{
JdbcUtils
.
load
(
url
);
}
else
{
Class
<?>
d
=
ClassUtils
.
loadClass
(
driver
);
if
(
java
.
sql
.
Driver
.
class
.
isAssignableFrom
(
d
))
{
return
DriverManager
.
getConnection
(
url
,
prop
);
//## Java 1.4 begin ##
}
else
if
(
javax
.
naming
.
Context
.
class
.
isAssignableFrom
(
d
))
{
// JNDI context
try
{
Context
context
=
(
Context
)
d
.
newInstance
();
DataSource
ds
=
(
DataSource
)
context
.
lookup
(
url
);
String
user
=
prop
.
getProperty
(
"user"
);
String
password
=
prop
.
getProperty
(
"password"
);
if
(
StringUtils
.
isNullOrEmpty
(
user
)
&&
StringUtils
.
isNullOrEmpty
(
password
))
{
return
ds
.
getConnection
();
}
return
ds
.
getConnection
(
user
,
password
);
}
catch
(
Exception
e
)
{
throw
Message
.
convert
(
e
);
}
//## Java 1.4 end ##
}
else
{
// Don't know, but maybe it loaded a JDBC Driver
return
DriverManager
.
getConnection
(
url
,
prop
);
}
}
return
DriverManager
.
getConnection
(
url
,
prop
);
}
/**
* Get the driver class name for the given URL, or null if the URL is
* unknown.
*
* @param url the database URL
* @return the driver class name
*/
public
static
String
getDriver
(
String
url
)
{
if
(
url
.
startsWith
(
"jdbc:"
))
{
url
=
url
.
substring
(
"jdbc:"
.
length
());
for
(
int
i
=
0
;
i
<
DRIVERS
.
length
;
i
+=
2
)
{
String
prefix
=
DRIVERS
[
i
];
if
(
url
.
startsWith
(
prefix
))
{
return
DRIVERS
[
i
+
1
];
}
}
}
return
null
;
}
/**
* Load the driver class for the given URL, if the database URL is known.
*
* @param url the database URL
*/
public
static
void
load
(
String
url
)
{
String
driver
=
getDriver
(
url
);
if
(
driver
!=
null
)
{
ClassUtils
.
loadClass
(
driver
);
}
}
}
h2/src/tools/org/h2/jaqu/util/StatementBuilder.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
jaqu
.
util
;
/**
* A utility class to build a statement. In addition to the methods supported by
* StringBuilder, it allows to add a text only in the second iteration. This
* simplified constructs such as:
* <pre>
* StringBuilder buff = new StringBuilder();
* for (int i = 0; i < args.length; i++) {
* if (i > 0) {
* buff.append(", ");
* }
* buff.append(args[i]);
* }
* </pre>
* to
* <pre>
* StatementBuilder buff = new StatementBuilder();
* for (String s : args) {
* buff.appendExceptFirst(", ");
* buff.append(a);
* }
*</pre>
*/
public
class
StatementBuilder
{
private
final
StringBuilder
builder
=
new
StringBuilder
();
private
int
index
;
/**
* Create a new builder.
*/
public
StatementBuilder
()
{
// nothing to do
}
/**
* Create a new builder.
*
* @param string the initial string
*/
public
StatementBuilder
(
String
string
)
{
builder
.
append
(
string
);
}
/**
* Append a text.
*
* @param s the text to append
* @return itself
*/
public
StatementBuilder
append
(
String
s
)
{
builder
.
append
(
s
);
return
this
;
}
/**
* Append a character.
*
* @param c the character to append
* @return itself
*/
public
StatementBuilder
append
(
char
c
)
{
builder
.
append
(
c
);
return
this
;
}
/**
* Append a number.
*
* @param x the number to append
* @return itself
*/
public
StatementBuilder
append
(
long
x
)
{
builder
.
append
(
x
);
return
this
;
}
/**
* Reset the loop counter.
*
* @return itself
*/
public
StatementBuilder
resetCount
()
{
index
=
0
;
return
this
;
}
/**
* Append a text, but only if appendExceptFirst was never called.
*
* @param s the text to append
*/
public
void
appendOnlyFirst
(
String
s
)
{
if
(
index
==
0
)
{
builder
.
append
(
s
);
}
}
/**
* Append a text, except when this method is called the first time.
*
* @param s the text to append
*/
public
void
appendExceptFirst
(
String
s
)
{
if
(
index
++
>
0
)
{
builder
.
append
(
s
);
}
}
public
void
append
(
StatementBuilder
sb
)
{
builder
.
append
(
sb
);
}
public
void
insert
(
int
offset
,
char
c
)
{
builder
.
insert
(
offset
,
c
);
}
public
String
toString
()
{
return
builder
.
toString
();
}
/**
* Get the length.
*
* @return the length
*/
public
int
length
()
{
return
builder
.
length
();
}
}
h2/src/tools/org/h2/jaqu/util/StatementLogger.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package
org
.
h2
.
jaqu
.
util
;
import
java.io.PrintWriter
;
import
java.text.DecimalFormat
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* Utility class to optionally log generated statements to an output stream.<br>
* Default output stream is System.out.<br>
* Statement logging is disabled by default.
* <p>
* This class also tracks the counts for generated statements by major type.
*
*/
public
class
StatementLogger
{
public
static
boolean
logStatements
=
false
;
public
static
PrintWriter
out
=
new
PrintWriter
(
System
.
out
);
public
final
static
AtomicLong
selectCount
=
new
AtomicLong
(
0
);
public
final
static
AtomicLong
createCount
=
new
AtomicLong
(
0
);
public
final
static
AtomicLong
insertCount
=
new
AtomicLong
(
0
);
public
final
static
AtomicLong
updateCount
=
new
AtomicLong
(
0
);
public
final
static
AtomicLong
mergeCount
=
new
AtomicLong
(
0
);
public
final
static
AtomicLong
deleteCount
=
new
AtomicLong
(
0
);
public
static
void
create
(
String
statement
)
{
createCount
.
incrementAndGet
();
log
(
statement
);
}
public
static
void
insert
(
String
statement
)
{
insertCount
.
incrementAndGet
();
log
(
statement
);
}
public
static
void
update
(
String
statement
)
{
updateCount
.
incrementAndGet
();
log
(
statement
);
}
public
static
void
merge
(
String
statement
)
{
mergeCount
.
incrementAndGet
();
log
(
statement
);
}
public
static
void
delete
(
String
statement
)
{
deleteCount
.
incrementAndGet
();
log
(
statement
);
}
public
static
void
select
(
String
statement
)
{
selectCount
.
incrementAndGet
();
log
(
statement
);
}
private
static
void
log
(
String
statement
)
{
if
(
logStatements
)
out
.
println
(
statement
);
}
public
static
void
printStats
()
{
out
.
println
(
"JaQu Runtime Stats"
);
out
.
println
(
"======================="
);
printStat
(
"CREATE"
,
createCount
);
printStat
(
"INSERT"
,
insertCount
);
printStat
(
"UPDATE"
,
updateCount
);
printStat
(
"MERGE"
,
mergeCount
);
printStat
(
"DELETE"
,
deleteCount
);
printStat
(
"SELECT"
,
selectCount
);
}
private
static
void
printStat
(
String
name
,
AtomicLong
value
)
{
if
(
value
.
get
()
>
0
)
{
DecimalFormat
df
=
new
DecimalFormat
(
"###,###,###,###"
);
out
.
println
(
name
+
"="
+
df
.
format
(
createCount
.
get
()));
}
}
}
\ No newline at end of file
h2/src/tools/org/h2/jaqu/util/StringUtils.java
0 → 100644
浏览文件 @
0bedabe6
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
jaqu
.
util
;
public
class
StringUtils
{
/**
* Replace all occurrences of the before string with the after string.
*
* @param s the string
* @param before the old text
* @param after the new text
* @return the string with the before string replaced
*/
public
static
String
replaceAll
(
String
s
,
String
before
,
String
after
)
{
int
next
=
s
.
indexOf
(
before
);
if
(
next
<
0
)
{
return
s
;
}
StringBuilder
buff
=
new
StringBuilder
(
s
.
length
()
-
before
.
length
()
+
after
.
length
());
int
index
=
0
;
while
(
true
)
{
buff
.
append
(
s
.
substring
(
index
,
next
)).
append
(
after
);
index
=
next
+
before
.
length
();
next
=
s
.
indexOf
(
before
,
index
);
if
(
next
<
0
)
{
buff
.
append
(
s
.
substring
(
index
));
break
;
}
}
return
buff
.
toString
();
}
/**
* Check if a String is null or empty (the length is null).
*
* @param s the string to check
* @return true if it is null or empty
*/
public
static
boolean
isNullOrEmpty
(
String
s
)
{
return
s
==
null
||
s
.
length
()
==
0
;
}
/**
* Convert a string to a Java literal using the correct escape sequences.
* The literal is not enclosed in double quotes. The result can be used in
* properties files or in Java source code.
*
* @param s the text to convert
* @return the Java representation
*/
public
static
String
javaEncode
(
String
s
)
{
int
length
=
s
.
length
();
StringBuilder
buff
=
new
StringBuilder
(
length
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
char
c
=
s
.
charAt
(
i
);
switch
(
c
)
{
// case '\b':
// // BS backspace
// // not supported in properties files
// buff.append("\\b");
// break;
case
'\t'
:
// HT horizontal tab
buff
.
append
(
"\\t"
);
break
;
case
'\n'
:
// LF linefeed
buff
.
append
(
"\\n"
);
break
;
case
'\f'
:
// FF form feed
buff
.
append
(
"\\f"
);
break
;
case
'\r'
:
// CR carriage return
buff
.
append
(
"\\r"
);
break
;
case
'"'
:
// double quote
buff
.
append
(
"\\\""
);
break
;
case
'\\'
:
// backslash
buff
.
append
(
"\\\\"
);
break
;
default
:
int
ch
=
c
&
0xffff
;
if
(
ch
>=
' '
&&
(
ch
<
0x80
))
{
buff
.
append
(
c
);
// not supported in properties files
// } else if(ch < 0xff) {
// buff.append("\\");
// // make sure it's three characters (0x200 is octal 1000)
// buff.append(Integer.toOctalString(0x200 |
// ch).substring(1));
}
else
{
buff
.
append
(
"\\u"
);
// make sure it's four characters
buff
.
append
(
Integer
.
toHexString
(
0x10000
|
ch
).
substring
(
1
));
}
}
}
return
buff
.
toString
();
}
/**
* Pad a string. This method is used for the SQL function RPAD and LPAD.
*
* @param string the original string
* @param n the target length
* @param padding the padding string
* @param right true if the padding should be appended at the end
* @return the padded string
*/
public
static
String
pad
(
String
string
,
int
n
,
String
padding
,
boolean
right
)
{
if
(
n
<
0
)
{
n
=
0
;
}
if
(
n
<
string
.
length
())
{
return
string
.
substring
(
0
,
n
);
}
else
if
(
n
==
string
.
length
())
{
return
string
;
}
char
paddingChar
;
if
(
padding
==
null
||
padding
.
length
()
==
0
)
{
paddingChar
=
' '
;
}
else
{
paddingChar
=
padding
.
charAt
(
0
);
}
StringBuilder
buff
=
new
StringBuilder
(
n
);
n
-=
string
.
length
();
if
(
right
)
{
buff
.
append
(
string
);
}
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
buff
.
append
(
paddingChar
);
}
if
(!
right
)
{
buff
.
append
(
string
);
}
return
buff
.
toString
();
}
/**
* Convert a string to a SQL literal. Null is converted to NULL. The text is
* enclosed in single quotes. If there are any special characters, the method
* STRINGDECODE is used.
*
* @param s the text to convert.
* @return the SQL literal
*/
public
static
String
quoteStringSQL
(
String
s
)
{
if
(
s
==
null
)
{
return
"NULL"
;
}
int
length
=
s
.
length
();
StringBuilder
buff
=
new
StringBuilder
(
length
+
2
);
buff
.
append
(
'\''
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
char
c
=
s
.
charAt
(
i
);
if
(
c
==
'\''
)
{
buff
.
append
(
c
);
}
else
if
(
c
<
' '
||
c
>
127
)
{
// need to start from the beginning because maybe there was a \
// that was not quoted
return
"STRINGDECODE("
+
quoteStringSQL
(
javaEncode
(
s
))
+
")"
;
}
buff
.
append
(
c
);
}
buff
.
append
(
'\''
);
return
buff
.
toString
();
}
}
h2/src/tools/org/h2/jaqu/util/Utils.java
浏览文件 @
0bedabe6
...
...
@@ -7,19 +7,24 @@
package
org
.
h2
.
jaqu
.
util
;
//## Java 1.5 begin ##
import
java.io.IOException
;
import
java.io.Reader
;
import
java.io.StringWriter
;
import
java.lang.reflect.Constructor
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.sql.Clob
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.IdentityHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.h2.util.IOUtils
;
//## Java 1.5 end ##
import
java.util.Set
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* Generic utility methods.
...
...
@@ -27,13 +32,31 @@ import org.h2.util.IOUtils;
public
class
Utils
{
//## Java 1.5 begin ##
private
static
volatile
long
counter
;
private
static
final
AtomicLong
counter
=
new
AtomicLong
(
0
)
;
private
static
final
boolean
MAKE_ACCESSIBLE
=
true
;
private
static
final
int
BUFFER_BLOCK_SIZE
=
4
*
1024
;
public
static
<
T
>
ArrayList
<
T
>
newArrayList
()
{
return
new
ArrayList
<
T
>();
}
public
static
<
T
>
ArrayList
<
T
>
newArrayList
(
Collection
<
T
>
c
)
{
return
new
ArrayList
<
T
>(
c
);
}
public
static
<
T
>
HashSet
<
T
>
newHashSet
()
{
return
new
HashSet
<
T
>();
}
public
static
<
T
>
HashSet
<
T
>
newHashSet
(
Collection
<
T
>
list
)
{
return
new
HashSet
<
T
>(
list
);
}
public
static
<
T
>
Set
<
T
>
newConcurrentHashSet
()
{
return
Collections
.
newSetFromMap
(
new
ConcurrentHashMap
<
T
,
Boolean
>());
}
public
static
<
A
,
B
>
HashMap
<
A
,
B
>
newHashMap
()
{
return
new
HashMap
<
A
,
B
>();
...
...
@@ -52,35 +75,35 @@ public class Utils {
public
static
<
T
>
T
newObject
(
Class
<
T
>
clazz
)
{
// must create new instances
if
(
clazz
==
Integer
.
class
)
{
return
(
T
)
new
Integer
((
int
)
counter
++
);
return
(
T
)
new
Integer
((
int
)
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
String
.
class
)
{
return
(
T
)
(
""
+
counter
++
);
return
(
T
)
(
""
+
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
Long
.
class
)
{
return
(
T
)
new
Long
(
counter
++
);
return
(
T
)
new
Long
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
Short
.
class
)
{
return
(
T
)
new
Short
((
short
)
counter
++
);
return
(
T
)
new
Short
((
short
)
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
Byte
.
class
)
{
return
(
T
)
new
Byte
((
byte
)
counter
++
);
return
(
T
)
new
Byte
((
byte
)
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
Float
.
class
)
{
return
(
T
)
new
Float
(
counter
++
);
return
(
T
)
new
Float
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
Double
.
class
)
{
return
(
T
)
new
Double
(
counter
++
);
return
(
T
)
new
Double
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
Boolean
.
class
)
{
return
(
T
)
new
Boolean
(
false
);
}
else
if
(
clazz
==
BigDecimal
.
class
)
{
return
(
T
)
new
BigDecimal
(
counter
++
);
return
(
T
)
new
BigDecimal
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
BigInteger
.
class
)
{
return
(
T
)
new
BigInteger
(
""
+
counter
++
);
return
(
T
)
new
BigInteger
(
""
+
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
java
.
sql
.
Date
.
class
)
{
return
(
T
)
new
java
.
sql
.
Date
(
counter
++
);
return
(
T
)
new
java
.
sql
.
Date
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
java
.
sql
.
Time
.
class
)
{
return
(
T
)
new
java
.
sql
.
Time
(
counter
++
);
return
(
T
)
new
java
.
sql
.
Time
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
java
.
sql
.
Timestamp
.
class
)
{
return
(
T
)
new
java
.
sql
.
Timestamp
(
counter
++
);
return
(
T
)
new
java
.
sql
.
Timestamp
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
java
.
util
.
Date
.
class
)
{
return
(
T
)
new
java
.
util
.
Date
(
counter
++
);
return
(
T
)
new
java
.
util
.
Date
(
counter
.
incrementAndGet
()
);
}
else
if
(
clazz
==
List
.
class
)
{
return
(
T
)
new
ArrayList
();
return
(
T
)
newArrayList
();
}
try
{
return
clazz
.
newInstance
();
...
...
@@ -137,7 +160,7 @@ public class Utils {
Clob
c
=
(
Clob
)
o
;
try
{
Reader
r
=
c
.
getCharacterStream
();
return
IOUtils
.
readStringAndClose
(
r
,
-
1
);
return
readStringAndClose
(
r
,
-
1
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Error converting CLOB to String: "
+
e
.
toString
(),
e
);
}
...
...
@@ -146,7 +169,11 @@ public class Utils {
}
if
(
Number
.
class
.
isAssignableFrom
(
currentType
))
{
Number
n
=
(
Number
)
o
;
if
(
targetType
==
Integer
.
class
)
{
if
(
targetType
==
Byte
.
class
)
{
return
n
.
byteValue
();
}
else
if
(
targetType
==
Short
.
class
)
{
return
n
.
shortValue
();
}
else
if
(
targetType
==
Integer
.
class
)
{
return
n
.
intValue
();
}
else
if
(
targetType
==
Long
.
class
)
{
return
n
.
longValue
();
...
...
@@ -159,6 +186,37 @@ public class Utils {
throw
new
RuntimeException
(
"Can not convert the value "
+
o
+
" from "
+
currentType
+
" to "
+
targetType
);
}
/**
* Read a number of characters from a reader and close it.
*
* @param in the reader
* @param length the maximum number of characters to read, or -1 to read
* until the end of file
* @return the string read
*/
public
static
String
readStringAndClose
(
Reader
in
,
int
length
)
throws
IOException
{
try
{
if
(
length
<=
0
)
{
length
=
Integer
.
MAX_VALUE
;
}
int
block
=
Math
.
min
(
BUFFER_BLOCK_SIZE
,
length
);
StringWriter
out
=
new
StringWriter
(
length
==
Integer
.
MAX_VALUE
?
block
:
length
);
char
[]
buff
=
new
char
[
block
];
while
(
length
>
0
)
{
int
len
=
Math
.
min
(
block
,
length
);
len
=
in
.
read
(
buff
,
0
,
len
);
if
(
len
<
0
)
{
break
;
}
out
.
write
(
buff
,
0
,
len
);
length
-=
len
;
}
return
out
.
toString
();
}
finally
{
in
.
close
();
}
}
//## Java 1.5 end ##
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论