Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
3d2cd051
提交
3d2cd051
authored
12月 15, 2006
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
--no commit message
上级
77fe8768
显示空白字符变更
内嵌
并排
正在显示
61 个修改的文件
包含
9310 行增加
和
0 行删除
+9310
-0
java.sql.Driver
h2/src/main/META-INF/services/java.sql.Driver
+1
-0
BitField.java
h2/src/main/org/h2/util/BitField.java
+140
-0
ByteUtils.java
h2/src/main/org/h2/util/ByteUtils.java
+151
-0
Cache.java
h2/src/main/org/h2/util/Cache.java
+28
-0
Cache2Q.java
h2/src/main/org/h2/util/Cache2Q.java
+316
-0
CacheHead.java
h2/src/main/org/h2/util/CacheHead.java
+20
-0
CacheLRU.java
h2/src/main/org/h2/util/CacheLRU.java
+314
-0
CacheObject.java
h2/src/main/org/h2/util/CacheObject.java
+64
-0
CacheWriter.java
h2/src/main/org/h2/util/CacheWriter.java
+15
-0
ExactUTF8InputStreamReader.java
h2/src/main/org/h2/util/ExactUTF8InputStreamReader.java
+40
-0
FileUtils.java
h2/src/main/org/h2/util/FileUtils.java
+411
-0
HashBase.java
h2/src/main/org/h2/util/HashBase.java
+57
-0
IOUtils.java
h2/src/main/org/h2/util/IOUtils.java
+196
-0
IntArray.java
h2/src/main/org/h2/util/IntArray.java
+244
-0
IntIntHashMap.java
h2/src/main/org/h2/util/IntIntHashMap.java
+137
-0
MathUtils.java
h2/src/main/org/h2/util/MathUtils.java
+72
-0
MemoryFile.java
h2/src/main/org/h2/util/MemoryFile.java
+76
-0
MemoryUtils.java
h2/src/main/org/h2/util/MemoryUtils.java
+44
-0
NetUtils.java
h2/src/main/org/h2/util/NetUtils.java
+59
-0
ObjectArray.java
h2/src/main/org/h2/util/ObjectArray.java
+213
-0
Permutations.java
h2/src/main/org/h2/util/Permutations.java
+234
-0
RandomUtils.java
h2/src/main/org/h2/util/RandomUtils.java
+52
-0
ReaderInputStream.java
h2/src/main/org/h2/util/ReaderInputStream.java
+75
-0
ResourceData.java
h2/src/main/org/h2/util/ResourceData.java
+11
-0
Resources.java
h2/src/main/org/h2/util/Resources.java
+109
-0
ScriptReader.java
h2/src/main/org/h2/util/ScriptReader.java
+184
-0
SmallLRUCache.java
h2/src/main/org/h2/util/SmallLRUCache.java
+22
-0
SmallMap.java
h2/src/main/org/h2/util/SmallMap.java
+62
-0
StartBrowser.java
h2/src/main/org/h2/util/StartBrowser.java
+29
-0
StringCache.java
h2/src/main/org/h2/util/StringCache.java
+107
-0
StringUtils.java
h2/src/main/org/h2/util/StringUtils.java
+590
-0
TempFileDeleter.java
h2/src/main/org/h2/util/TempFileDeleter.java
+60
-0
TypeConverter.java
h2/src/main/org/h2/util/TypeConverter.java
+190
-0
UpdatableRow.java
h2/src/main/org/h2/util/UpdatableRow.java
+233
-0
ValueHashMap.java
h2/src/main/org/h2/util/ValueHashMap.java
+145
-0
CompareMode.java
h2/src/main/org/h2/value/CompareMode.java
+62
-0
DataType.java
h2/src/main/org/h2/value/DataType.java
+678
-0
Transfer.java
h2/src/main/org/h2/value/Transfer.java
+408
-0
Value.java
h2/src/main/org/h2/value/Value.java
+591
-0
ValueArray.java
h2/src/main/org/h2/value/ValueArray.java
+163
-0
ValueBoolean.java
h2/src/main/org/h2/value/ValueBoolean.java
+83
-0
ValueByte.java
h2/src/main/org/h2/value/ValueByte.java
+129
-0
ValueBytes.java
h2/src/main/org/h2/value/ValueBytes.java
+35
-0
ValueBytesBase.java
h2/src/main/org/h2/value/ValueBytesBase.java
+69
-0
ValueDate.java
h2/src/main/org/h2/value/ValueDate.java
+95
-0
ValueDecimal.java
h2/src/main/org/h2/value/ValueDecimal.java
+179
-0
ValueDouble.java
h2/src/main/org/h2/value/ValueDouble.java
+127
-0
ValueFloat.java
h2/src/main/org/h2/value/ValueFloat.java
+127
-0
ValueInt.java
h2/src/main/org/h2/value/ValueInt.java
+153
-0
ValueJavaObject.java
h2/src/main/org/h2/value/ValueJavaObject.java
+32
-0
ValueLob.java
h2/src/main/org/h2/value/ValueLob.java
+586
-0
ValueLong.java
h2/src/main/org/h2/value/ValueLong.java
+184
-0
ValueNull.java
h2/src/main/org/h2/value/ValueNull.java
+135
-0
ValueResultSet.java
h2/src/main/org/h2/value/ValueResultSet.java
+111
-0
ValueShort.java
h2/src/main/org/h2/value/ValueShort.java
+129
-0
ValueString.java
h2/src/main/org/h2/value/ValueString.java
+71
-0
ValueStringBase.java
h2/src/main/org/h2/value/ValueStringBase.java
+60
-0
ValueStringIgnoreCase.java
h2/src/main/org/h2/value/ValueStringIgnoreCase.java
+57
-0
ValueTime.java
h2/src/main/org/h2/value/ValueTime.java
+87
-0
ValueTimestamp.java
h2/src/main/org/h2/value/ValueTimestamp.java
+114
-0
ValueUuid.java
h2/src/main/org/h2/value/ValueUuid.java
+144
-0
没有找到文件。
h2/src/main/META-INF/services/java.sql.Driver
0 → 100644
浏览文件 @
3d2cd051
org.h2.Driver
\ No newline at end of file
h2/src/main/org/h2/util/BitField.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
/**
* @author Thomas
*/
public
class
BitField
{
private
long
[]
data
=
new
long
[
10
];
private
static
final
int
ADDRESS_BITS
=
6
;
private
static
final
int
BITS
=
64
;
private
static
final
int
ADDRESS_MASK
=
BITS
-
1
;
public
int
getLastSetBit
()
{
int
i
=
(
data
.
length
<<
ADDRESS_BITS
)
-
1
;
while
(
i
>=
0
)
{
if
(
get
(
i
))
{
return
i
;
}
i
--;
}
return
-
1
;
}
public
int
nextSetBit
(
int
fromIndex
)
{
int
i
=
fromIndex
>>
ADDRESS_BITS
;
int
max
=
data
.
length
;
int
maxAddress
=
data
.
length
<<
ADDRESS_BITS
;
for
(;
i
<
max
;
i
++)
{
if
(
data
[
i
]
==
0
)
{
continue
;
}
for
(
int
j
=
Math
.
max
(
fromIndex
,
i
<<
ADDRESS_BITS
);
j
<
maxAddress
;
j
++)
{
if
(
get
(
j
))
{
return
j
;
}
}
}
return
-
1
;
}
public
int
nextClearBit
(
int
fromIndex
)
{
int
i
=
fromIndex
>>
ADDRESS_BITS
;
int
max
=
data
.
length
;
for
(;
i
<
max
;
i
++)
{
if
(
data
[
i
]
==
-
1
)
{
continue
;
}
for
(
int
j
=
Math
.
max
(
fromIndex
,
i
<<
ADDRESS_BITS
);
;
j
++)
{
if
(!
get
(
j
))
{
return
j
;
}
}
}
return
fromIndex
;
}
public
long
getLong
(
int
i
)
{
int
addr
=
getAddress
(
i
);
if
(
addr
>=
data
.
length
)
{
return
0
;
}
return
data
[
addr
];
}
public
boolean
get
(
int
i
)
{
int
addr
=
getAddress
(
i
);
if
(
addr
>=
data
.
length
)
{
return
false
;
}
return
(
data
[
addr
]
&
getBitMask
(
i
))
!=
0
;
}
public
void
set
(
int
i
)
{
int
addr
=
getAddress
(
i
);
checkCapacity
(
addr
);
data
[
addr
]
|=
getBitMask
(
i
);
}
public
void
clear
(
int
i
)
{
int
addr
=
getAddress
(
i
);
if
(
addr
>=
data
.
length
)
{
return
;
}
data
[
addr
]
&=
~
getBitMask
(
i
);
}
private
int
getAddress
(
int
i
)
{
return
i
>>
ADDRESS_BITS
;
}
private
long
getBitMask
(
int
i
)
{
return
1L
<<
(
i
&
ADDRESS_MASK
);
}
private
void
checkCapacity
(
int
size
)
{
while
(
size
>=
data
.
length
)
{
int
newSize
=
data
.
length
==
0
?
1
:
data
.
length
*
2
;
long
[]
d
=
new
long
[
newSize
];
System
.
arraycopy
(
data
,
0
,
d
,
0
,
data
.
length
);
data
=
d
;
}
}
/*
private BitSet data = new BitSet();
public boolean get(int i) {
return data.get(i);
}
public void set(int i) {
data.set(i);
}
public void clear(int i) {
data.clear(i);
}
*/
public
void
setRange
(
int
start
,
int
len
,
boolean
value
)
{
for
(
int
end
=
start
+
len
;
start
<
end
;
start
++)
{
set
(
start
,
value
);
}
}
private
void
set
(
int
i
,
boolean
value
)
{
if
(
value
)
{
set
(
i
);
}
else
{
clear
(
i
);
}
}
}
h2/src/main/org/h2/util/ByteUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
public
class
ByteUtils
{
private
static
final
char
[]
HEX
=
"0123456789abcdef"
.
toCharArray
();
public
static
int
readInt
(
byte
[]
buff
,
int
pos
)
{
return
(
buff
[
pos
++]<<
24
)
+
((
buff
[
pos
++]
&
0xff
)
<<
16
)
+
((
buff
[
pos
++]
&
0xff
)
<<
8
)
+
(
buff
[
pos
++]
&
0xff
);
}
public
static
long
readLong
(
byte
[]
buff
,
int
pos
)
{
return
((
long
)(
readInt
(
buff
,
pos
))
<<
32
)
+
(
readInt
(
buff
,
pos
+
4
)
&
0xffffffff
L
);
}
public
static
int
indexOf
(
byte
[]
bytes
,
byte
[]
pattern
,
int
start
)
{
if
(
pattern
.
length
==
0
)
{
return
start
;
}
if
(
start
>
bytes
.
length
)
{
return
-
1
;
}
int
last
=
bytes
.
length
-
pattern
.
length
+
1
;
next:
for
(;
start
<
last
;
start
++)
{
for
(
int
i
=
0
;
i
<
pattern
.
length
;
i
++)
{
if
(
bytes
[
start
+
i
]
!=
pattern
[
i
])
{
continue
next
;
}
}
return
start
;
}
return
-
1
;
}
public
static
byte
[]
convertStringToBytes
(
String
s
)
throws
SQLException
{
int
len
=
s
.
length
();
if
(
len
%
2
==
1
)
{
throw
Message
.
getSQLException
(
Message
.
HEX_STRING_ODD_1
,
s
);
}
len
/=
2
;
byte
[]
buff
=
new
byte
[
len
];
try
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
buff
[
i
]
=
(
byte
)
((
Character
.
digit
(
s
.
charAt
(
i
+
i
),
16
)
<<
4
)
|
(
Character
.
digit
(
s
.
charAt
(
i
+
i
+
1
),
16
)));
}
}
catch
(
NumberFormatException
e
)
{
throw
Message
.
getSQLException
(
Message
.
HEX_STRING_WRONG_1
,
s
);
}
return
buff
;
}
public
static
int
getByteArrayHash
(
byte
[]
value
)
{
int
h
=
1
;
for
(
int
i
=
0
;
i
<
value
.
length
;)
{
h
=
31
*
h
+
value
[
i
++];
}
return
h
;
}
public
static
String
convertBytesToString
(
byte
[]
value
)
{
return
convertBytesToString
(
value
,
value
.
length
);
}
public
static
String
convertBytesToString
(
byte
[]
value
,
int
len
)
{
char
[]
buff
=
new
char
[
len
+
len
];
char
[]
hex
=
HEX
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
c
=
value
[
i
]
&
0xff
;
buff
[
i
+
i
]
=
hex
[
c
>>
4
];
buff
[
i
+
i
+
1
]
=
hex
[
c
&
0xf
];
}
return
new
String
(
buff
);
}
public
static
boolean
compareSecure
(
byte
[]
test
,
byte
[]
good
)
{
if
((
test
==
null
)
||
(
good
==
null
))
{
return
(
test
==
null
)
&&
(
good
==
null
);
}
if
(
test
.
length
!=
good
.
length
)
{
return
false
;
}
if
(
test
.
length
==
0
)
{
return
true
;
}
// silly loop: this should help a little against timing attacks
boolean
correct
=
true
,
correct2
=
false
;
for
(
int
i
=
0
;
i
<
good
.
length
;
i
++)
{
if
(
test
[
i
]
!=
good
[
i
])
{
correct
=
false
;
}
else
{
correct2
=
true
;
}
}
return
correct
&&
correct2
;
}
public
static
void
clear
(
byte
[]
buff
)
{
for
(
int
i
=
0
;
i
<
buff
.
length
;
i
++)
{
buff
[
i
]
=
0
;
}
}
public
static
int
compareNotNull
(
byte
[]
data1
,
byte
[]
data2
)
{
int
len
=
Math
.
min
(
data1
.
length
,
data2
.
length
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
byte
b
=
data1
[
i
];
byte
b2
=
data2
[
i
];
if
(
b
!=
b2
)
{
return
b
>
b2
?
1
:
-
1
;
}
}
int
c
=
data1
.
length
-
data2
.
length
;
return
c
==
0
?
0
:
(
c
<
0
?
-
1
:
1
);
}
public
static
String
convertToBinString
(
byte
[]
buff
)
{
char
[]
chars
=
new
char
[
buff
.
length
];
for
(
int
i
=
0
;
i
<
buff
.
length
;
i
++)
{
chars
[
i
]
=
(
char
)
(
buff
[
i
]
&
0xff
);
}
return
new
String
(
chars
);
}
public
static
byte
[]
convertBinStringToBytes
(
String
data
)
{
byte
[]
buff
=
new
byte
[
data
.
length
()];
for
(
int
i
=
0
;
i
<
data
.
length
();
i
++)
{
buff
[
i
]
=
(
byte
)
(
data
.
charAt
(
i
)
&
0xff
);
}
return
buff
;
}
public
static
byte
[]
copy
(
byte
[]
source
,
byte
[]
target
)
{
int
len
=
source
.
length
;
if
(
len
>
target
.
length
)
{
target
=
new
byte
[
len
];
}
System
.
arraycopy
(
source
,
0
,
target
,
0
,
len
);
return
target
;
}
}
h2/src/main/org/h2/util/Cache.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
public
interface
Cache
{
ObjectArray
getAllChanged
();
void
clear
();
CacheObject
get
(
int
pos
);
void
put
(
CacheObject
r
)
throws
SQLException
;
CacheObject
update
(
int
pos
,
CacheObject
record
)
throws
SQLException
;
void
remove
(
int
pos
);
CacheObject
find
(
int
i
);
void
setMaxSize
(
int
value
)
throws
SQLException
;
String
getTypeName
();
}
h2/src/main/org/h2/util/Cache2Q.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* For details about the 2Q algorithm, see http://www.vldb.org/conf/1994/P439.PDF.
* However, items are moved from 'in' queue and move to the 'main' queue if the are referenced again.
*/
public
class
Cache2Q
implements
Cache
{
public
static
String
TYPE_NAME
=
"TQ"
;
private
static
final
int
MAIN
=
1
,
IN
=
2
,
OUT
=
3
;
private
int
maxSize
;
private
CacheWriter
writer
;
private
int
percentIn
=
20
,
percentOut
=
50
;
private
int
maxMain
,
maxIn
,
maxOut
;
private
CacheObject
headMain
=
new
CacheHead
();
private
CacheObject
headIn
=
new
CacheHead
();
private
CacheObject
headOut
=
new
CacheHead
();
private
int
sizeMain
,
sizeIn
,
sizeOut
,
sizeRecords
;
private
int
len
;
private
CacheObject
[]
values
;
private
int
mask
;
public
Cache2Q
(
CacheWriter
writer
,
int
maxSize
)
{
this
.
writer
=
writer
;
this
.
maxSize
=
maxSize
;
this
.
len
=
maxSize
/
2
;
MathUtils
.
checkPowerOf2
(
len
);
this
.
mask
=
len
-
1
;
clear
();
}
public
void
clear
()
{
headMain
.
next
=
headMain
.
previous
=
headMain
;
headIn
.
next
=
headIn
.
previous
=
headIn
;
headOut
.
next
=
headOut
.
previous
=
headOut
;
values
=
new
CacheObject
[
len
];
sizeIn
=
sizeOut
=
sizeMain
=
0
;
sizeRecords
=
0
;
recalcMax
();
}
void
setPercentIn
(
int
percent
)
{
percentIn
=
percent
;
recalcMax
();
}
void
setPercentOut
(
int
percent
)
{
percentOut
=
percent
;
recalcMax
();
}
private
void
recalcMax
()
{
maxMain
=
maxSize
;
maxIn
=
maxSize
*
percentIn
/
100
;
maxOut
=
maxSize
*
percentOut
/
100
;
}
private
void
addToFront
(
CacheObject
head
,
CacheObject
rec
)
{
if
(
Constants
.
CHECK
)
{
if
(
rec
==
head
)
{
throw
Message
.
getInternalError
(
"try to move head"
);
}
if
(
rec
.
next
!=
null
||
rec
.
previous
!=
null
)
{
throw
Message
.
getInternalError
(
"already linked"
);
}
}
rec
.
next
=
head
;
rec
.
previous
=
head
.
previous
;
rec
.
previous
.
next
=
rec
;
head
.
previous
=
rec
;
}
private
void
removeFromList
(
CacheObject
rec
)
{
if
(
Constants
.
CHECK
&&
(
rec
instanceof
CacheHead
&&
rec
.
cacheQueue
!=
OUT
))
{
throw
Message
.
getInternalError
();
}
rec
.
previous
.
next
=
rec
.
next
;
rec
.
next
.
previous
=
rec
.
previous
;
// TODO cache: mystery: why is this required? needs more memory if we don't do this
rec
.
next
=
null
;
rec
.
previous
=
null
;
}
public
CacheObject
get
(
int
pos
)
{
CacheObject
r
=
findCacheObject
(
pos
);
if
(
r
==
null
)
{
return
null
;
}
if
(
r
.
cacheQueue
==
MAIN
)
{
removeFromList
(
r
);
addToFront
(
headMain
,
r
);
}
else
if
(
r
.
cacheQueue
==
OUT
)
{
return
null
;
}
else
if
(
r
.
cacheQueue
==
IN
)
{
removeFromList
(
r
);
sizeIn
-=
r
.
getBlockCount
();
sizeMain
+=
r
.
getBlockCount
();
r
.
cacheQueue
=
MAIN
;
addToFront
(
headMain
,
r
);
}
return
r
;
}
private
CacheObject
findCacheObject
(
int
pos
)
{
CacheObject
rec
=
values
[
pos
&
mask
];
while
(
rec
!=
null
&&
rec
.
getPos
()
!=
pos
)
{
rec
=
rec
.
chained
;
}
return
rec
;
}
private
CacheObject
removeCacheObject
(
int
pos
)
{
int
index
=
pos
&
mask
;
CacheObject
rec
=
values
[
index
];
if
(
rec
==
null
)
{
return
null
;
}
if
(
rec
.
getPos
()
==
pos
)
{
values
[
index
]
=
rec
.
chained
;
}
else
{
CacheObject
last
;
do
{
last
=
rec
;
rec
=
rec
.
chained
;
if
(
rec
==
null
)
{
return
null
;
}
}
while
(
rec
.
getPos
()
!=
pos
);
last
.
chained
=
rec
.
chained
;
}
sizeRecords
--;
if
(
Constants
.
CHECK
)
{
rec
.
chained
=
null
;
}
return
rec
;
}
public
void
remove
(
int
pos
)
{
CacheObject
r
=
removeCacheObject
(
pos
);
if
(
r
!=
null
)
{
removeFromList
(
r
);
if
(
r
.
cacheQueue
==
MAIN
)
{
sizeMain
-=
r
.
getBlockCount
();
}
else
if
(
r
.
cacheQueue
==
IN
)
{
sizeIn
-=
r
.
getBlockCount
();
}
}
}
private
void
removeOld
()
throws
SQLException
{
if
((
sizeIn
<
maxIn
)
&&
(
sizeOut
<
maxOut
)
&&
(
sizeMain
<
maxMain
))
{
return
;
}
int
i
=
0
;
ObjectArray
changed
=
new
ObjectArray
();
while
(((
sizeIn
*
4
>
maxIn
*
3
)
||
(
sizeOut
*
4
>
maxOut
*
3
)
||
(
sizeMain
*
4
>
maxMain
*
3
))
&&
sizeRecords
>
Constants
.
CACHE_MIN_RECORDS
)
{
if
(
i
++
>=
sizeRecords
)
{
// can't remove any record, because the log is not written yet
// hopefully this does not happen too much, but it could happen theoretically
// TODO log this
break
;
}
if
(
sizeIn
>
maxIn
)
{
CacheObject
r
=
headIn
.
next
;
if
(!
r
.
canRemove
())
{
removeFromList
(
r
);
addToFront
(
headIn
,
r
);
continue
;
}
sizeIn
-=
r
.
getBlockCount
();
int
pos
=
r
.
getPos
();
removeCacheObject
(
pos
);
removeFromList
(
r
);
if
(
r
.
isChanged
())
{
changed
.
add
(
r
);
}
r
=
new
CacheHead
();
r
.
setPos
(
pos
);
r
.
cacheQueue
=
OUT
;
putCacheObject
(
r
);
addToFront
(
headOut
,
r
);
sizeOut
++;
if
(
sizeOut
>=
maxOut
)
{
r
=
headOut
.
next
;
sizeOut
--;
removeCacheObject
(
r
.
getPos
());
removeFromList
(
r
);
}
}
else
{
CacheObject
r
=
headMain
.
next
;
if
(!
r
.
canRemove
())
{
removeFromList
(
r
);
addToFront
(
headMain
,
r
);
continue
;
}
sizeMain
-=
r
.
getBlockCount
();
removeCacheObject
(
r
.
getPos
());
removeFromList
(
r
);
if
(
r
.
isChanged
())
{
changed
.
add
(
r
);
}
}
}
if
(
changed
.
size
()
>
0
)
{
CacheObject
.
sort
(
changed
);
for
(
i
=
0
;
i
<
changed
.
size
();
i
++)
{
CacheObject
rec
=
(
CacheObject
)
changed
.
get
(
i
);
writer
.
writeBack
(
rec
);
}
}
}
public
ObjectArray
getAllChanged
()
{
ObjectArray
list
=
new
ObjectArray
();
for
(
CacheObject
o
=
headMain
.
next
;
o
!=
headMain
;
o
=
o
.
next
)
{
if
(
o
.
isChanged
())
{
list
.
add
(
o
);
}
}
for
(
CacheObject
o
=
headIn
.
next
;
o
!=
headIn
;
o
=
o
.
next
)
{
if
(
o
.
isChanged
())
{
list
.
add
(
o
);
}
}
CacheObject
.
sort
(
list
);
return
list
;
}
public
CacheObject
find
(
int
pos
)
{
CacheObject
o
=
findCacheObject
(
pos
);
if
(
o
!=
null
&&
o
.
cacheQueue
!=
OUT
)
{
return
o
;
}
return
null
;
}
private
void
putCacheObject
(
CacheObject
rec
)
{
if
(
Constants
.
CHECK
)
{
for
(
int
i
=
0
;
i
<
rec
.
getBlockCount
();
i
++)
{
CacheObject
old
=
find
(
rec
.
getPos
()
+
i
);
if
(
old
!=
null
)
{
throw
Message
.
getInternalError
(
"try to add a record twice i="
+
i
);
}
}
}
int
index
=
rec
.
getPos
()
&
mask
;
rec
.
chained
=
values
[
index
];
values
[
index
]
=
rec
;
sizeRecords
++;
}
public
void
put
(
CacheObject
rec
)
throws
SQLException
{
int
pos
=
rec
.
getPos
();
CacheObject
r
=
findCacheObject
(
pos
);
if
(
r
!=
null
)
{
if
(
r
.
cacheQueue
==
OUT
)
{
removeCacheObject
(
pos
);
removeFromList
(
r
);
removeOld
();
rec
.
cacheQueue
=
MAIN
;
putCacheObject
(
rec
);
addToFront
(
headMain
,
rec
);
sizeMain
+=
rec
.
getBlockCount
();
}
}
else
if
(
sizeMain
<
maxMain
)
{
removeOld
();
rec
.
cacheQueue
=
MAIN
;
putCacheObject
(
rec
);
addToFront
(
headMain
,
rec
);
sizeMain
+=
rec
.
getBlockCount
();
}
else
{
removeOld
();
rec
.
cacheQueue
=
IN
;
putCacheObject
(
rec
);
addToFront
(
headIn
,
rec
);
sizeIn
+=
rec
.
getBlockCount
();
}
}
public
CacheObject
update
(
int
pos
,
CacheObject
rec
)
throws
SQLException
{
CacheObject
old
=
find
(
pos
);
if
(
old
==
null
||
old
.
cacheQueue
==
OUT
)
{
put
(
rec
);
}
else
{
if
(
old
==
rec
)
{
if
(
rec
.
cacheQueue
==
MAIN
)
{
removeFromList
(
rec
);
addToFront
(
headMain
,
rec
);
}
}
}
return
old
;
}
public
void
setMaxSize
(
int
newSize
)
throws
SQLException
{
maxSize
=
newSize
<
0
?
0
:
newSize
;
recalcMax
();
removeOld
();
}
public
String
getTypeName
()
{
return
TYPE_NAME
;
}
}
h2/src/main/org/h2/util/CacheHead.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
org.h2.store.DataPage
;
public
class
CacheHead
extends
CacheObject
{
public
int
getByteCount
(
DataPage
dummy
)
throws
SQLException
{
return
0
;
}
public
void
write
(
DataPage
buff
)
throws
SQLException
{
}
}
h2/src/main/org/h2/util/CacheLRU.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* Special behavior of the cache: You are not allowed to add the same record
* twice.
*
* @author Thomas
*/
public
class
CacheLRU
implements
Cache
{
public
static
String
TYPE_NAME
=
"LRU"
;
private
int
len
;
private
int
maxSize
;
private
CacheObject
[]
values
;
private
int
mask
;
private
CacheWriter
writer
;
private
int
sizeRecords
;
private
int
sizeBlocks
;
private
CacheObject
head
=
new
CacheHead
();
public
CacheLRU
(
CacheWriter
writer
,
int
maxSize
)
{
this
.
writer
=
writer
;
this
.
len
=
maxSize
/
2
;
this
.
mask
=
len
-
1
;
MathUtils
.
checkPowerOf2
(
len
);
this
.
maxSize
=
maxSize
;
clear
();
}
public
void
put
(
CacheObject
rec
)
throws
SQLException
{
if
(
Constants
.
CHECK
)
{
for
(
int
i
=
0
;
i
<
rec
.
getBlockCount
();
i
++)
{
CacheObject
old
=
find
(
rec
.
getPos
()
+
i
);
if
(
old
!=
null
)
{
throw
Message
.
getInternalError
(
"try to add a record twice i="
+
i
);
}
}
}
int
index
=
rec
.
getPos
()
&
mask
;
rec
.
chained
=
values
[
index
];
values
[
index
]
=
rec
;
sizeRecords
++;
sizeBlocks
+=
rec
.
getBlockCount
();
addToFront
(
rec
);
removeOld
();
}
public
CacheObject
update
(
int
pos
,
CacheObject
rec
)
throws
SQLException
{
CacheObject
old
=
find
(
pos
);
if
(
old
==
null
)
{
put
(
rec
);
}
else
{
if
(
Constants
.
CHECK
)
{
if
(
old
!=
rec
)
{
throw
Message
.
getInternalError
(
"old != record old="
+
old
+
" new="
+
rec
);
}
}
removeFromLinkedList
(
rec
);
addToFront
(
rec
);
}
return
old
;
}
private
void
removeOld
()
throws
SQLException
{
if
(
sizeBlocks
<
maxSize
)
{
return
;
}
int
i
=
0
;
ObjectArray
changed
=
new
ObjectArray
();
while
(
sizeBlocks
*
4
>
maxSize
*
3
&&
sizeRecords
>
Constants
.
CACHE_MIN_RECORDS
)
{
CacheObject
last
=
head
.
next
;
if
(
i
++
>=
sizeRecords
)
{
// can't remove any record, because the log is not written yet
// hopefully this does not happen too much, but it could happen theoretically
// TODO log this
break
;
}
if
(
Constants
.
CHECK
&&
last
==
head
)
{
throw
Message
.
getInternalError
(
"try to remove head"
);
}
// we are not allowed to remove it if the log is not yet written
// (because we need to log before writing the data)
// also, can't write it if the record is pinned
if
(!
last
.
canRemove
())
{
removeFromLinkedList
(
last
);
addToFront
(
last
);
continue
;
}
remove
(
last
.
getPos
());
if
(
last
.
isChanged
())
{
changed
.
add
(
last
);
}
}
if
(
changed
.
size
()
>
0
)
{
CacheObject
.
sort
(
changed
);
for
(
i
=
0
;
i
<
changed
.
size
();
i
++)
{
CacheObject
rec
=
(
CacheObject
)
changed
.
get
(
i
);
writer
.
writeBack
(
rec
);
}
}
}
private
void
addToFront
(
CacheObject
rec
)
{
if
(
Constants
.
CHECK
&&
rec
==
head
)
{
throw
Message
.
getInternalError
(
"try to move head"
);
}
rec
.
next
=
head
;
rec
.
previous
=
head
.
previous
;
rec
.
previous
.
next
=
rec
;
head
.
previous
=
rec
;
}
private
void
removeFromLinkedList
(
CacheObject
rec
)
{
if
(
Constants
.
CHECK
&&
rec
==
head
)
{
throw
Message
.
getInternalError
(
"try to remove head"
);
}
rec
.
previous
.
next
=
rec
.
next
;
rec
.
next
.
previous
=
rec
.
previous
;
// TODO cache: mystery: why is this required? needs more memory if we don't do this
rec
.
next
=
null
;
rec
.
previous
=
null
;
}
public
void
remove
(
int
pos
)
{
int
index
=
pos
&
mask
;
CacheObject
rec
=
values
[
index
];
if
(
rec
==
null
)
{
return
;
}
if
(
rec
.
getPos
()
==
pos
)
{
values
[
index
]
=
rec
.
chained
;
}
else
{
CacheObject
last
;
do
{
last
=
rec
;
rec
=
rec
.
chained
;
if
(
rec
==
null
)
{
return
;
}
}
while
(
rec
.
getPos
()
!=
pos
);
last
.
chained
=
rec
.
chained
;
}
sizeRecords
--;
sizeBlocks
-=
rec
.
getBlockCount
();
removeFromLinkedList
(
rec
);
if
(
Constants
.
CHECK
)
{
rec
.
chained
=
null
;
if
(
find
(
pos
)
!=
null
)
{
throw
Message
.
getInternalError
(
"not removed!"
);
}
}
}
public
CacheObject
find
(
int
pos
)
{
CacheObject
rec
=
values
[
pos
&
mask
];
while
(
rec
!=
null
&&
rec
.
getPos
()
!=
pos
)
{
rec
=
rec
.
chained
;
}
return
rec
;
}
public
CacheObject
get
(
int
pos
)
{
CacheObject
rec
=
find
(
pos
);
if
(
rec
!=
null
)
{
removeFromLinkedList
(
rec
);
addToFront
(
rec
);
}
return
rec
;
}
// private void testConsistency() {
// int s = size;
// HashSet set = new HashSet();
// for(int i=0; i<values.length; i++) {
// Record rec = values[i];
// if(rec == null) {
// continue;
// }
// set.add(rec);
// while(rec.chained != null) {
// rec = rec.chained;
// set.add(rec);
// }
// }
// Record rec = head.next;
// while(rec != head) {
// set.add(rec);
// rec = rec.next;
// }
// rec = head.previous;
// while(rec != head) {
// set.add(rec);
// rec = rec.previous;
// }
// if(set.size() != size) {
// System.out.println("size="+size+" but el.size="+set.size());
// }
// }
public
ObjectArray
getAllChanged
()
{
// if(Database.CHECK) {
// testConsistency();
// }
// TODO cache: should probably use the LRU list
ObjectArray
list
=
new
ObjectArray
();
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
CacheObject
rec
=
values
[
i
];
while
(
rec
!=
null
)
{
if
(
rec
.
isChanged
())
{
list
.
add
(
rec
);
if
(
list
.
size
()
>=
sizeRecords
)
{
if
(
Constants
.
CHECK
)
{
if
(
list
.
size
()
>
sizeRecords
)
{
throw
Message
.
getInternalError
(
"cache chain error"
);
}
}
else
{
break
;
}
}
}
rec
=
rec
.
chained
;
}
}
return
list
;
}
public
void
clear
()
{
head
.
next
=
head
.
previous
=
head
;
values
=
new
CacheObject
[
len
];
sizeRecords
=
0
;
sizeBlocks
=
0
;
}
public
void
setMaxSize
(
int
newSize
)
throws
SQLException
{
maxSize
=
newSize
<
0
?
0
:
newSize
;
removeOld
();
}
public
String
getTypeName
()
{
return
TYPE_NAME
;
}
}
// Unmaintained reference code (very old)
//import java.util.Iterator;
//import java.util.LinkedHashMap;
//import java.util.Map;
//
//public class Cache extends LinkedHashMap {
//
// final static int MAX_SIZE = 1 << 10;
// private CacheWriter writer;
//
// public Cache(CacheWriter writer) {
// super(16, (float) 0.75, true);
// this.writer = writer;
// }
//
// protected boolean removeEldestEntry(Map.Entry eldest) {
// if(size() <= MAX_SIZE) {
// return false;
// }
// Record entry = (Record) eldest.getValue();
// if(entry.getDeleted()) {
// return true;
// }
// if(entry.isChanged()) {
// try {
////System.out.println("cache write "+entry.getPos());
// writer.writeBack(entry);
// } catch(SQLException e) {
// // TODO cache: printStackTrace not needed if we use our own hashtable
// e.printStackTrace();
// }
// }
// return true;
// }
//
// public void put(Record rec) {
// put(new Integer(rec.getPos()), rec);
// }
//
// public Record get(int pos) {
// return (Record)get(new Integer(pos));
// }
//
// public void remove(int pos) {
// remove(new Integer(pos));
// }
//
// public ObjectArray getAllChanged() {
// Iterator it = values().iterator();
// ObjectArray list = new ObjectArray();
// while(it.hasNext()) {
// Record rec = (Record)it.next();
// if(rec.isChanged()) {
// list.add(rec);
// }
// }
// return list;
// }
//}
h2/src/main/org/h2/util/CacheObject.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.util.Comparator
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
public
abstract
class
CacheObject
{
private
boolean
changed
;
public
CacheObject
previous
,
next
,
chained
;
public
int
cacheQueue
;
private
int
blockCount
;
private
int
pos
;
public
static
void
sort
(
ObjectArray
recordList
)
{
recordList
.
sort
(
new
Comparator
()
{
public
int
compare
(
Object
a
,
Object
b
)
{
int
pa
=
((
CacheObject
)
a
).
getPos
();
int
pb
=
((
CacheObject
)
b
).
getPos
();
return
pa
==
pb
?
0
:
(
pa
<
pb
?
-
1
:
1
);
}
});
}
public
void
setBlockCount
(
int
size
)
{
this
.
blockCount
=
size
;
}
public
int
getBlockCount
()
{
return
blockCount
;
}
public
void
setPos
(
int
pos
)
{
if
(
Constants
.
CHECK
&&
(
previous
!=
null
||
next
!=
null
||
chained
!=
null
))
{
throw
Message
.
getInternalError
(
"setPos too late"
);
}
this
.
pos
=
pos
;
}
public
int
getPos
()
{
return
pos
;
}
public
boolean
isChanged
()
{
return
changed
;
}
public
void
setChanged
(
boolean
b
)
{
changed
=
b
;
}
public
boolean
isPinned
()
{
return
false
;
}
public
boolean
canRemove
()
{
return
true
;
}
}
h2/src/main/org/h2/util/CacheWriter.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
/**
* @author Thomas
*/
public
interface
CacheWriter
{
void
writeBack
(
CacheObject
entry
)
throws
SQLException
;
}
h2/src/main/org/h2/util/ExactUTF8InputStreamReader.java
0 → 100644
浏览文件 @
3d2cd051
package
org
.
h2
.
util
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Reader
;
/**
* The InputStreamReader may read some more bytes than required.
* If this is a problem, use this class
*/
public
class
ExactUTF8InputStreamReader
extends
Reader
{
private
InputStream
in
;
public
ExactUTF8InputStreamReader
(
InputStream
in
)
{
this
.
in
=
in
;
}
public
void
close
()
throws
IOException
{
}
public
int
read
(
char
[]
cbuf
,
int
off
,
int
len
)
throws
IOException
{
for
(
int
i
=
0
;
i
<
len
;
i
++,
off
++)
{
int
x
=
in
.
read
();
if
(
x
<
0
)
{
return
i
==
0
?
-
1
:
i
;
}
x
=
x
&
0xff
;
if
(
x
<
0x80
)
{
cbuf
[
off
]
=
(
char
)
x
;
}
else
if
(
x
>=
0xe0
)
{
cbuf
[
off
]
=
(
char
)(((
x
&
0xf
)
<<
12
)
+
((
in
.
read
()
&
0x3f
)
<<
6
)
+
(
in
.
read
()
&
0x3f
));
}
else
{
cbuf
[
off
]
=
(
char
)(((
x
&
0x1f
)
<<
6
)
+
(
in
.
read
()
&
0x3f
));
}
}
return
len
;
}
}
h2/src/main/org/h2/util/FileUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.RandomAccessFile
;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
java.util.Properties
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
import
org.h2.message.TraceSystem
;
/**
* @author Thomas
*/
public
class
FileUtils
{
public
static
HashMap
memoryFiles
=
new
HashMap
();
private
static
final
String
MEMORY_PREFIX
=
"inmemory:"
;
private
static
final
String
MEMORY_PREFIX_2
=
"mem:"
;
// TODO detection of 'case in sensitive filesystem' could maybe implemented using some other means
private
static
final
boolean
isCaseInsensitiveFileSystem
=
(
File
.
separatorChar
==
'\\'
);
// TODO gcj: use our own UTF-8 encoder
public
static
RandomAccessFile
openRandomAccessFile
(
String
fileName
,
String
mode
)
throws
IOException
{
try
{
return
new
RandomAccessFile
(
fileName
,
mode
);
}
catch
(
IOException
e
)
{
freeMemoryAndFinalize
();
return
new
RandomAccessFile
(
fileName
,
mode
);
}
}
public
static
void
setLength
(
RandomAccessFile
file
,
long
newLength
)
throws
IOException
{
try
{
file
.
setLength
(
newLength
);
}
catch
(
IOException
e
)
{
long
length
=
file
.
length
();
if
(
newLength
<
length
)
{
throw
e
;
}
else
{
long
pos
=
file
.
getFilePointer
();
file
.
seek
(
length
);
long
remaining
=
newLength
-
length
;
int
maxSize
=
1024
*
1024
;
int
block
=
(
int
)
Math
.
min
(
remaining
,
maxSize
);
byte
[]
buffer
=
new
byte
[
block
];
while
(
remaining
>
0
)
{
int
write
=
(
int
)
Math
.
min
(
remaining
,
maxSize
);
file
.
write
(
buffer
,
0
,
write
);
remaining
-=
write
;
}
file
.
seek
(
pos
);
}
}
}
public
static
FileWriter
openFileWriter
(
String
fileName
,
boolean
append
)
throws
IOException
{
try
{
return
new
FileWriter
(
fileName
,
append
);
}
catch
(
IOException
e
)
{
freeMemoryAndFinalize
();
return
new
FileWriter
(
fileName
,
append
);
}
}
public
static
boolean
fileStartsWith
(
String
fileName
,
String
prefix
)
{
if
(
isCaseInsensitiveFileSystem
)
{
fileName
=
StringUtils
.
toUpperEnglish
(
fileName
);
prefix
=
StringUtils
.
toUpperEnglish
(
prefix
);
}
return
fileName
.
startsWith
(
prefix
);
}
public
static
FileOutputStream
openFileOutputStream
(
File
file
)
throws
IOException
{
try
{
return
new
FileOutputStream
(
file
);
}
catch
(
IOException
e
)
{
freeMemoryAndFinalize
();
return
new
FileOutputStream
(
file
);
}
}
private
static
void
freeMemoryAndFinalize
()
{
long
mem
=
Runtime
.
getRuntime
().
freeMemory
();
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
System
.
gc
();
long
now
=
Runtime
.
getRuntime
().
freeMemory
();
Runtime
.
getRuntime
().
runFinalization
();
if
(
now
==
mem
)
{
break
;
}
mem
=
now
;
}
}
public
static
void
rename
(
String
oldName
,
String
newName
)
throws
SQLException
{
if
(
isInMemory
(
oldName
))
{
MemoryFile
f
=
getMemoryFile
(
oldName
);
f
.
setName
(
newName
);
memoryFiles
.
put
(
newName
,
f
);
return
;
}
File
oldFile
=
new
File
(
oldName
);
File
newFile
=
new
File
(
newName
);
if
(
oldFile
.
getName
().
equals
(
newFile
.
getName
()))
{
throw
Message
.
getInternalError
(
"rename file old=new"
);
}
if
(
oldFile
.
exists
()
&&
!
newFile
.
exists
())
{
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
boolean
ok
=
oldFile
.
renameTo
(
newFile
);
if
(
ok
)
{
return
;
}
wait
(
i
);
}
}
throw
Message
.
getSQLException
(
Message
.
FILE_RENAME_FAILED_2
,
new
String
[]{
oldName
,
newName
},
null
);
}
public
static
synchronized
Properties
loadProperties
(
File
file
)
throws
IOException
{
Properties
prop
=
new
Properties
();
if
(
file
.
exists
())
{
FileInputStream
in
=
new
FileInputStream
(
file
);
try
{
prop
.
load
(
in
);
}
finally
{
in
.
close
();
}
}
return
prop
;
}
public
static
boolean
getBooleanProperty
(
Properties
prop
,
String
key
,
boolean
def
)
{
String
value
=
prop
.
getProperty
(
key
,
""
+
def
);
try
{
return
Boolean
.
valueOf
(
value
).
booleanValue
();
}
catch
(
Exception
e
)
{
TraceSystem
.
traceThrowable
(
e
);
return
def
;
}
}
public
static
int
getIntProperty
(
Properties
prop
,
String
key
,
int
def
)
{
String
value
=
prop
.
getProperty
(
key
,
""
+
def
);
try
{
return
MathUtils
.
decodeInt
(
value
);
}
catch
(
Exception
e
)
{
TraceSystem
.
traceThrowable
(
e
);
return
def
;
}
}
public
static
void
createDirs
(
String
fileName
)
throws
SQLException
{
File
f
=
new
File
(
fileName
);
if
(!
f
.
exists
())
{
String
parent
=
f
.
getParent
();
if
(
parent
==
null
)
{
return
;
}
File
dir
=
new
File
(
parent
);
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
if
(
dir
.
exists
()
||
dir
.
mkdirs
())
{
return
;
}
wait
(
i
);
}
throw
Message
.
getSQLException
(
Message
.
FILE_CREATION_FAILED_1
,
parent
);
}
}
public
static
boolean
createNewFile
(
String
fileName
)
throws
SQLException
{
if
(
isInMemory
(
fileName
))
{
if
(
exists
(
fileName
))
{
return
false
;
}
// creates the file (not thread safe)
getMemoryFile
(
fileName
);
return
true
;
}
File
file
=
new
File
(
fileName
);
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
try
{
return
file
.
createNewFile
();
}
catch
(
IOException
e
)
{
// TODO file lock: check if 'access denied' exceptions are really a concurrent access problem
wait
(
i
);
}
}
// TODO GCJ: it seems gcj throws 'CreateFile failed' if the file already exists?!
return
false
;
// TODO is this message used elsewhere?
// throw Message.getSQLException(Message.FILE_CREATION_FAILED_1, fileName);
}
public
static
void
delete
(
String
fileName
)
throws
SQLException
{
if
(
isInMemory
(
fileName
))
{
memoryFiles
.
remove
(
fileName
);
return
;
}
File
file
=
new
File
(
fileName
);
if
(
file
.
exists
())
{
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
boolean
ok
=
file
.
delete
();
if
(
ok
)
{
return
;
}
wait
(
i
);
}
throw
Message
.
getSQLException
(
Message
.
FILE_DELETE_FAILED_1
,
fileName
);
}
}
private
static
void
wait
(
int
i
)
{
if
(
i
>
8
)
{
System
.
gc
();
}
try
{
// sleep at most 256 ms
Thread
.
sleep
(
i
*
i
);
}
catch
(
InterruptedException
e
)
{
// ignore
}
}
public
static
String
getFileName
(
String
name
)
throws
SQLException
{
String
separator
=
System
.
getProperty
(
"file.separator"
);
String
path
=
getParent
(
name
)
+
separator
;
String
fullFileName
=
normalize
(
name
);
if
(!
fullFileName
.
startsWith
(
path
))
{
throw
Message
.
getInternalError
(
"file utils error: "
+
fullFileName
+
" does not start with "
+
path
);
}
String
fileName
=
fullFileName
.
substring
(
path
.
length
());
return
fileName
;
}
public
static
File
getFileInUserHome
(
String
filename
)
{
String
userDir
=
System
.
getProperty
(
"user.home"
);
if
(
userDir
==
null
)
{
return
new
File
(
filename
);
}
return
new
File
(
userDir
,
filename
);
}
public
static
String
normalize
(
String
fileName
)
throws
SQLException
{
if
(
isInMemory
(
fileName
))
{
return
fileName
;
}
File
f
=
new
File
(
fileName
);
try
{
return
f
.
getCanonicalPath
();
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
static
void
tryDelete
(
String
fileName
)
{
if
(
isInMemory
(
fileName
))
{
memoryFiles
.
remove
(
fileName
);
return
;
}
new
File
(
fileName
).
delete
();
}
public
static
boolean
isReadOnly
(
String
fileName
)
{
if
(
isInMemory
(
fileName
))
{
return
false
;
}
File
f
=
new
File
(
fileName
);
return
f
.
exists
()
&&
!
f
.
canWrite
();
}
public
static
boolean
exists
(
String
fileName
)
{
if
(
isInMemory
(
fileName
))
{
return
memoryFiles
.
get
(
fileName
)
!=
null
;
}
return
new
File
(
fileName
).
exists
();
}
public
static
MemoryFile
getMemoryFile
(
String
fileName
)
{
MemoryFile
m
=
(
MemoryFile
)
memoryFiles
.
get
(
fileName
);
if
(
m
==
null
)
{
m
=
new
MemoryFile
(
fileName
);
memoryFiles
.
put
(
fileName
,
m
);
}
return
m
;
}
public
static
long
length
(
String
fileName
)
{
if
(
isInMemory
(
fileName
))
{
return
getMemoryFile
(
fileName
).
length
();
}
return
new
File
(
fileName
).
length
();
}
public
static
boolean
isInMemory
(
String
fileName
)
{
return
fileName
.
startsWith
(
MEMORY_PREFIX
)
||
fileName
.
startsWith
(
MEMORY_PREFIX_2
);
}
public
static
String
createTempFile
(
String
name
,
String
suffix
,
boolean
deleteOnExit
)
throws
IOException
{
name
+=
"."
;
if
(
isInMemory
(
name
))
{
for
(
int
i
=
0
;;
i
++)
{
String
n
=
name
+
i
+
suffix
;
if
(!
exists
(
n
))
{
// creates the file (not thread safe)
getMemoryFile
(
n
);
return
n
;
}
}
}
String
prefix
=
new
File
(
name
).
getName
();
File
dir
=
new
File
(
name
).
getAbsoluteFile
().
getParentFile
();
File
f
=
File
.
createTempFile
(
prefix
,
suffix
,
dir
);
if
(
deleteOnExit
)
{
f
.
deleteOnExit
();
}
return
f
.
getCanonicalPath
();
}
// public static void deleteOnExit(String temp) {
// if(isInMemory(temp)) {
// // nothing to do
// return;
// }
// new File(temp).deleteOnExit();
// }
public
static
String
getParent
(
String
fileName
)
{
if
(
isInMemory
(
fileName
))
{
return
MEMORY_PREFIX
;
}
return
new
File
(
fileName
).
getParent
();
}
public
static
String
[]
listFiles
(
String
path
)
throws
SQLException
{
if
(
isInMemory
(
path
))
{
String
[]
list
=
new
String
[
memoryFiles
.
size
()];
MemoryFile
[]
l
=
new
MemoryFile
[
memoryFiles
.
size
()];
memoryFiles
.
values
().
toArray
(
l
);
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
list
[
i
]
=
l
[
i
].
getName
();
}
return
list
;
}
try
{
File
[]
files
=
new
File
(
path
).
listFiles
();
if
(
files
==
null
)
{
return
new
String
[
0
];
}
String
[]
list
=
new
String
[
files
.
length
];
for
(
int
i
=
0
;
i
<
files
.
length
;
i
++)
{
list
[
i
]
=
files
[
i
].
getCanonicalPath
();
}
return
list
;
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
static
boolean
isDirectory
(
String
fileName
)
{
if
(
isInMemory
(
fileName
))
{
// TODO inmemory: currently doesn't support directories
return
false
;
}
return
new
File
(
fileName
).
isDirectory
();
}
public
static
void
copy
(
String
original
,
String
copy
)
throws
SQLException
{
FileOutputStream
out
=
null
;
FileInputStream
in
=
null
;
try
{
out
=
openFileOutputStream
(
new
File
(
copy
));
in
=
new
FileInputStream
(
new
File
(
original
));
byte
[]
buffer
=
new
byte
[
Constants
.
IO_BUFFER_SIZE
];
while
(
true
)
{
int
len
=
in
.
read
(
buffer
);
if
(
len
<
0
)
{
break
;
}
out
.
write
(
buffer
,
0
,
len
);
}
}
catch
(
IOException
e
)
{
IOUtils
.
closeSilently
(
in
);
IOUtils
.
closeSilently
(
out
);
throw
Message
.
convert
(
e
);
}
}
public
static
void
deleteRecursive
(
String
fileName
)
throws
SQLException
{
if
(
FileUtils
.
isDirectory
(
fileName
))
{
String
[]
list
=
FileUtils
.
listFiles
(
fileName
);
for
(
int
i
=
0
;
list
!=
null
&&
i
<
list
.
length
;
i
++)
{
deleteRecursive
(
list
[
i
]);
}
}
FileUtils
.
delete
(
fileName
);
}
}
h2/src/main/org/h2/util/HashBase.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
public
abstract
class
HashBase
{
protected
int
mask
,
len
,
size
,
deletedCount
,
level
;
protected
boolean
zeroKey
;
private
int
maxSize
,
minSize
,
maxDeleted
;
private
static
final
int
MAX_LOAD
=
90
;
public
HashBase
()
{
reset
(
2
);
}
public
int
size
()
{
return
size
+
(
zeroKey
?
1
:
0
);
}
protected
void
checkSizePut
()
throws
SQLException
{
if
(
deletedCount
>
size
)
{
rehash
(
level
);
}
if
(
size
+
deletedCount
>=
maxSize
)
{
rehash
(
level
+
1
);
}
}
protected
void
checkSizeRemove
()
throws
SQLException
{
if
(
size
<
minSize
&&
level
>
0
)
{
rehash
(
level
-
1
);
}
else
if
(
deletedCount
>
maxDeleted
)
{
rehash
(
level
);
}
}
protected
abstract
void
rehash
(
int
newLevel
)
throws
SQLException
;
protected
void
reset
(
int
newLevel
)
{
minSize
=
size
*
3
/
4
;
size
=
0
;
level
=
newLevel
;
len
=
2
<<
level
;
mask
=
len
-
1
;
maxSize
=
(
int
)(
len
*
MAX_LOAD
/
100L
);
deletedCount
=
0
;
maxDeleted
=
20
+
len
/
2
;
}
protected
int
getIndex
(
int
hash
)
{
return
hash
&
mask
;
}
}
h2/src/main/org/h2/util/IOUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.Reader
;
import
java.io.StringWriter
;
import
java.io.Writer
;
public
class
IOUtils
{
private
static
final
int
BUFFER_BLOCK_SIZE
=
4
*
1024
;
public
static
void
closeSilently
(
OutputStream
out
)
{
if
(
out
!=
null
)
{
try
{
out
.
close
();
}
catch
(
IOException
e
)
{
// ignore
}
}
}
public
static
void
skipFully
(
InputStream
in
,
long
skip
)
throws
IOException
{
while
(
skip
>
0
)
{
skip
-=
in
.
skip
(
skip
);
}
}
public
static
void
skipFully
(
Reader
reader
,
long
skip
)
throws
IOException
{
while
(
skip
>
0
)
{
skip
-=
reader
.
skip
(
skip
);
}
}
public
static
long
copyAndClose
(
InputStream
in
,
OutputStream
out
)
throws
IOException
{
try
{
return
copyAndCloseInput
(
in
,
out
);
}
finally
{
out
.
close
();
}
}
public
static
long
copyAndCloseInput
(
InputStream
in
,
OutputStream
out
)
throws
IOException
{
int
written
=
0
;
try
{
byte
[]
buffer
=
new
byte
[
4
*
1024
];
while
(
true
)
{
int
len
=
in
.
read
(
buffer
);
if
(
len
<
0
)
{
break
;
}
out
.
write
(
buffer
,
0
,
len
);
written
+=
len
;
}
}
finally
{
in
.
close
();
}
return
written
;
}
public
static
long
copyAndCloseInput
(
Reader
in
,
Writer
out
)
throws
IOException
{
long
written
=
0
;
try
{
char
[]
buffer
=
new
char
[
4
*
1024
];
while
(
true
)
{
int
len
=
in
.
read
(
buffer
);
if
(
len
<
0
)
{
break
;
}
out
.
write
(
buffer
,
0
,
len
);
written
+=
len
;
}
}
finally
{
in
.
close
();
}
return
written
;
}
public
static
void
closeSilently
(
InputStream
in
)
{
if
(
in
!=
null
)
{
try
{
in
.
close
();
}
catch
(
IOException
e
)
{
// ignore
}
}
}
public
static
void
closeSilently
(
Reader
reader
)
{
if
(
reader
!=
null
)
{
try
{
reader
.
close
();
}
catch
(
IOException
e
)
{
// ignore
}
}
}
public
static
void
closeSilently
(
Writer
writer
)
{
if
(
writer
!=
null
)
{
try
{
writer
.
flush
();
writer
.
close
();
}
catch
(
IOException
e
)
{
// ignore
}
}
}
public
static
byte
[]
readBytesAndClose
(
InputStream
in
,
int
length
)
throws
IOException
{
try
{
if
(
length
<=
0
)
{
length
=
Integer
.
MAX_VALUE
;
}
int
block
=
Math
.
min
(
BUFFER_BLOCK_SIZE
,
length
);
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
(
block
);
byte
[]
buff
=
new
byte
[
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
.
toByteArray
();
}
finally
{
in
.
close
();
}
}
public
static
String
readStringAndClose
(
Reader
in
,
int
length
)
throws
IOException
{
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
;
}
in
.
close
();
return
out
.
toString
();
}
public
static
int
readFully
(
InputStream
in
,
byte
[]
buffer
,
int
max
)
throws
IOException
{
int
off
=
0
,
len
=
Math
.
min
(
max
,
buffer
.
length
);
if
(
len
==
0
)
{
return
0
;
}
while
(
true
)
{
int
l
=
len
-
off
;
if
(
l
<=
0
)
{
break
;
}
l
=
in
.
read
(
buffer
,
off
,
l
);
if
(
l
<
0
)
{
break
;
}
off
+=
l
;
}
return
off
<
0
?
-
1
:
off
;
}
public
static
int
readFully
(
Reader
in
,
char
[]
buffer
,
int
max
)
throws
IOException
{
int
off
=
0
,
len
=
Math
.
min
(
max
,
buffer
.
length
);
if
(
len
==
0
)
{
return
0
;
}
while
(
true
)
{
int
l
=
len
-
off
;
if
(
l
<=
0
)
{
break
;
}
l
=
in
.
read
(
buffer
,
off
,
l
);
if
(
l
<
0
)
{
break
;
}
off
+=
l
;
}
return
off
<
0
?
-
1
:
off
;
}
}
h2/src/main/org/h2/util/IntArray.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
IntArray
{
private
int
[]
data
;
private
int
size
;
private
int
hash
;
public
IntArray
()
{
data
=
new
int
[
10
];
}
public
IntArray
(
int
[]
data
)
{
this
.
data
=
data
;
size
=
data
.
length
;
}
public
static
int
[]
clone
(
int
[]
array
)
{
if
(
array
==
null
)
{
return
null
;
}
int
[]
copy
=
new
int
[
array
.
length
];
System
.
arraycopy
(
array
,
0
,
copy
,
0
,
array
.
length
);
return
copy
;
}
public
static
boolean
equals
(
int
[]
a
,
int
[]
b
)
{
if
(
a
==
null
||
b
==
null
)
{
return
a
==
b
;
}
if
(
a
.
length
!=
b
.
length
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
return
false
;
}
}
return
true
;
}
public
void
add
(
int
value
)
{
checkCapacity
();
data
[
size
++]
=
value
;
}
public
int
get
(
int
i
)
{
if
(
Constants
.
CHECK
&&
i
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
return
data
[
i
];
}
public
int
remove
(
int
i
)
{
if
(
Constants
.
CHECK
&&
i
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
int
value
=
data
[
i
];
System
.
arraycopy
(
data
,
i
+
1
,
data
,
i
,
size
-
i
-
1
);
size
--;
return
value
;
}
private
void
checkCapacity
()
{
if
(
size
>=
data
.
length
)
{
int
[]
d
=
new
int
[
data
.
length
*
2
];
System
.
arraycopy
(
data
,
0
,
d
,
0
,
data
.
length
);
data
=
d
;
}
}
public
void
add
(
int
i
,
int
value
)
{
if
(
Constants
.
CHECK
&&
i
>
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
checkCapacity
();
if
(
i
==
size
)
{
add
(
value
);
}
else
{
System
.
arraycopy
(
data
,
i
,
data
,
i
+
1
,
size
-
i
);
data
[
i
]
=
value
;
size
++;
}
}
public
void
set
(
int
i
,
int
value
)
{
if
(
Constants
.
CHECK
&&
i
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
data
[
i
]
=
value
;
}
public
boolean
equals
(
Object
obj
)
{
IntArray
other
=
(
IntArray
)
obj
;
if
(
hashCode
()
!=
other
.
hashCode
()
||
size
!=
other
.
size
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(
data
[
i
]
!=
other
.
data
[
i
])
{
return
false
;
}
}
return
true
;
}
public
int
hashCode
()
{
if
(
hash
!=
0
)
{
return
hash
;
}
int
h
=
size
+
1
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
h
=
h
*
31
+
data
[
i
];
}
hash
=
h
;
return
h
;
}
public
int
size
()
{
return
size
;
}
public
void
addValueSorted
(
int
value
)
{
int
l
=
0
,
r
=
size
;
while
(
l
<
r
)
{
int
i
=
(
l
+
r
)
>>>
1
;
int
d
=
data
[
i
];
if
(
d
==
value
)
{
return
;
}
else
if
(
d
>
value
)
{
r
=
i
;
}
else
{
l
=
i
+
1
;
}
}
add
(
l
,
value
);
}
// public void addValueSorted(int value) {
// int l = 0, r = size - 1;
// while(l <= r) {
// int i = (l + r) >>> 1;
// int d = data[i];
// if(d == value) {
// return;
// } else if(d > value) {
// r = i - 1;
// } else {
// l = i + 1;
// }
// }
// add(l, value);
// }
public
void
removeValue
(
int
value
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(
data
[
i
]
==
value
)
{
remove
(
i
);
return
;
}
}
throw
Message
.
getInternalError
();
}
public
int
findNextValueIndex
(
int
value
)
{
int
l
=
0
,
r
=
size
;
while
(
l
<
r
)
{
int
i
=
(
l
+
r
)
>>>
1
;
int
d
=
data
[
i
];
if
(
d
>=
value
)
{
r
=
i
;
}
else
{
l
=
i
+
1
;
}
}
return
l
;
// for(int i=0; i<size; i++) {
// if(data[i] >= value) {
// return i;
// }
// }
// return size;
}
public
void
sort
()
{
for
(
int
i
=
1
,
j
;
i
<
size
();
i
++)
{
int
t
=
get
(
i
);
for
(
j
=
i
-
1
;
j
>=
0
&&
(
get
(
j
)
>
t
);
j
--)
{
set
(
j
+
1
,
get
(
j
));
}
set
(
j
+
1
,
t
);
}
}
public
void
toArray
(
int
[]
array
)
{
System
.
arraycopy
(
data
,
0
,
array
,
0
,
size
);
}
// ArrayList data = new ArrayList();
//
// public IntArray() {
// }
//
// public IntArray(int[] data) {
// for (int i = 0; i < data.length; i++) {
// this.data.add(new Integer(data[i]));
// }
// }
//
// public void add(int value) {
// this.data.add(new Integer(value));
// }
//
// public int get(int i) {
// return ((Integer) data.get(i)).intValue();
// }
//
// public void remove(int i) {
// data.remove(i);
// }
//
// public void add(int i, int value) {
// data.add(i, new Integer(value));
// }
//
// public void set(int i, int value) {
// data.set(i, new Integer(value));
// }
//
// public int size() {
// return data.size();
// }
}
h2/src/main/org/h2/util/IntIntHashMap.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
/**
* An empty record has key=0 and value=0
* A deleted record has key=0 and value=DELETED
* value NOT_FOUND: -1; this value cannot be stored in the map (however 0 can be stored)
* @author Thomas
*/
public
class
IntIntHashMap
extends
HashBase
{
public
static
final
int
NOT_FOUND
=
-
1
;
private
static
final
int
DELETED
=
1
;
private
int
[]
keys
;
private
int
[]
values
;
private
int
zeroValue
;
protected
void
reset
(
int
newLevel
)
{
super
.
reset
(
newLevel
);
keys
=
new
int
[
len
];
values
=
new
int
[
len
];
}
public
void
put
(
int
key
,
int
value
)
{
if
(
key
==
0
)
{
zeroKey
=
true
;
zeroValue
=
value
;
}
try
{
checkSizePut
();
}
catch
(
SQLException
e
)
{
// in fact, it is never thrown
// TODO hash: maybe optimize it
}
int
index
=
getIndex
(
key
);
int
plus
=
1
;
int
deleted
=
-
1
;
do
{
int
k
=
keys
[
index
];
if
(
k
==
0
)
{
if
(
values
[
index
]
!=
DELETED
)
{
// found an empty record
if
(
deleted
>=
0
)
{
index
=
deleted
;
deletedCount
--;
}
size
++;
keys
[
index
]
=
key
;
values
[
index
]
=
value
;
return
;
}
// found a deleted record
if
(
deleted
<
0
)
{
deleted
=
index
;
}
}
else
if
(
k
==
key
)
{
// update existing
values
[
index
]
=
value
;
return
;
}
index
=
(
index
+
plus
++)
&
mask
;
}
while
(
plus
<=
len
);
// no space
throw
Message
.
getInternalError
(
"hashmap is full"
);
}
public
void
remove
(
int
key
)
{
if
(
key
==
0
)
{
zeroKey
=
false
;
return
;
}
try
{
checkSizeRemove
();
}
catch
(
SQLException
e
)
{
// in fact, it is never thrown
// TODO hash: maybe optimize it
}
int
index
=
getIndex
(
key
);
int
plus
=
1
;
do
{
int
k
=
keys
[
index
];
if
(
k
==
key
)
{
// found the record
keys
[
index
]
=
0
;
values
[
index
]
=
DELETED
;
deletedCount
++;
size
--;
return
;
}
else
if
(
k
==
0
&&
values
[
index
]
==
0
)
{
// found an empty record
return
;
}
index
=
(
index
+
plus
++)
&
mask
;
k
=
keys
[
index
];
}
while
(
plus
<=
len
);
// not found
}
protected
void
rehash
(
int
newLevel
)
{
int
[]
oldKeys
=
keys
;
int
[]
oldValues
=
values
;
reset
(
newLevel
);
for
(
int
i
=
0
;
i
<
oldKeys
.
length
;
i
++)
{
int
k
=
oldKeys
[
i
];
if
(
k
!=
0
)
{
put
(
k
,
oldValues
[
i
]);
}
}
}
public
int
get
(
int
key
)
{
if
(
key
==
0
)
{
return
zeroKey
?
zeroValue
:
NOT_FOUND
;
}
int
index
=
getIndex
(
key
);
int
plus
=
1
;
do
{
int
k
=
keys
[
index
];
if
(
k
==
0
&&
values
[
index
]==
0
)
{
// found an empty record
return
NOT_FOUND
;
}
else
if
(
k
==
key
)
{
// found it
return
values
[
index
];
}
index
=
(
index
+
plus
++)
&
mask
;
}
while
(
plus
<=
len
);
return
NOT_FOUND
;
}
}
h2/src/main/org/h2/util/MathUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.math.BigDecimal
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
MathUtils
{
// with blockSizePowerOf2 8: 0 > 0; 1..8 > 8, 9..16 > 16, ...
public
static
int
roundUp
(
int
x
,
int
blockSizePowerOf2
)
{
return
(
x
+
blockSizePowerOf2
-
1
)
&
(-
blockSizePowerOf2
);
}
public
static
void
checkPowerOf2
(
int
len
)
{
if
((
len
&
(
len
-
1
))
!=
0
&&
len
>
0
)
{
throw
Message
.
getInternalError
(
"not a power of 2: "
+
len
);
}
}
public
static
long
scaleUp50Percent
(
long
start
,
long
min
,
long
blockSize
)
{
while
(
start
<
min
)
{
start
+=
start
/
2
;
start
+=
start
%
blockSize
;
}
return
start
;
}
public
static
BigDecimal
setScale
(
BigDecimal
bd
,
int
scale
)
throws
SQLException
{
if
(
scale
>
Constants
.
BIGDECIMAL_SCALE_MAX
)
{
throw
Message
.
getInvalidValueException
(
""
+
scale
,
"scale"
);
}
else
if
(
scale
<
0
)
{
throw
Message
.
getInvalidValueException
(
""
+
scale
,
"scale"
);
}
return
bd
.
setScale
(
scale
,
BigDecimal
.
ROUND_HALF_UP
);
}
public
static
byte
decodeByte
(
String
s
)
{
return
Byte
.
decode
(
s
).
byteValue
();
}
public
static
short
decodeShort
(
String
s
)
{
return
Short
.
decode
(
s
).
shortValue
();
}
public
static
int
decodeInt
(
String
s
)
{
return
Integer
.
decode
(
s
).
intValue
();
}
public
static
long
decodeLong
(
String
s
)
{
return
Long
.
decode
(
s
).
longValue
();
}
public
static
int
convertLongToInt
(
long
l
)
{
if
(
l
<=
Integer
.
MIN_VALUE
)
{
return
Integer
.
MIN_VALUE
;
}
else
if
(
l
>=
Integer
.
MAX_VALUE
)
{
return
Integer
.
MAX_VALUE
;
}
else
{
return
(
int
)
l
;
}
}
}
h2/src/main/org/h2/util/MemoryFile.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
public
class
MemoryFile
{
private
String
name
;
private
int
length
;
private
byte
[]
data
;
private
int
pos
;
private
byte
[]
magic
;
MemoryFile
(
String
name
)
{
this
.
name
=
name
;
data
=
new
byte
[
16
];
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
long
length
()
{
return
length
;
}
public
void
setLength
(
long
l
)
{
length
=
(
int
)
l
;
}
public
void
seek
(
long
pos
)
{
this
.
pos
=
(
int
)
pos
;
}
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
{
if
(
pos
+
len
>
length
)
{
length
=
pos
+
len
;
}
if
(
pos
+
len
>
data
.
length
)
{
byte
[]
n
=
new
byte
[
length
*
2
];
System
.
arraycopy
(
data
,
0
,
n
,
0
,
data
.
length
);
data
=
n
;
}
System
.
arraycopy
(
b
,
off
,
data
,
pos
,
len
);
pos
+=
len
;
}
public
void
readFully
(
byte
[]
b
,
int
off
,
int
len
)
{
if
(
pos
+
len
>
length
)
{
length
=
pos
+
len
;
}
if
(
pos
+
len
>
data
.
length
)
{
byte
[]
n
=
new
byte
[
length
*
2
];
System
.
arraycopy
(
data
,
0
,
n
,
0
,
data
.
length
);
data
=
n
;
}
System
.
arraycopy
(
data
,
pos
,
b
,
off
,
len
);
pos
+=
len
;
}
public
long
getFilePointer
()
{
return
pos
;
}
public
void
setMagic
(
byte
[]
magic
)
{
this
.
magic
=
magic
;
}
public
byte
[]
getMagic
()
{
return
magic
;
}
}
h2/src/main/org/h2/util/MemoryUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
public
class
MemoryUtils
{
private
static
long
lastGC
;
private
static
int
GC_DELAY
=
50
;
private
static
int
MAX_GC
=
8
;
public
static
int
getMemoryUsed
()
{
collectGarbage
();
Runtime
rt
=
Runtime
.
getRuntime
();
long
mem
=
rt
.
totalMemory
()
-
rt
.
freeMemory
();
return
(
int
)
(
mem
>>
10
);
}
public
static
int
getMemoryFree
()
{
collectGarbage
();
Runtime
rt
=
Runtime
.
getRuntime
();
long
mem
=
rt
.
freeMemory
();
return
(
int
)
(
mem
>>
10
);
}
private
static
synchronized
void
collectGarbage
()
{
Runtime
runtime
=
Runtime
.
getRuntime
();
long
total
=
runtime
.
totalMemory
();
long
time
=
System
.
currentTimeMillis
();
if
(
lastGC
+
GC_DELAY
<
time
)
{
for
(
int
i
=
0
;
i
<
MAX_GC
;
i
++)
{
runtime
.
gc
();
long
now
=
runtime
.
totalMemory
();
if
(
now
==
total
)
{
lastGC
=
System
.
currentTimeMillis
();
break
;
}
total
=
now
;
}
}
}
}
h2/src/main/org/h2/util/NetUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.IOException
;
import
java.net.BindException
;
import
java.net.InetAddress
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
import
org.h2.security.SecureSocketFactory
;
public
class
NetUtils
{
public
static
Socket
createLoopbackSocket
(
int
port
,
boolean
ssl
)
throws
IOException
,
SQLException
{
InetAddress
address
=
InetAddress
.
getByName
(
"127.0.0.1"
);
return
createSocket
(
address
,
port
,
ssl
);
}
public
static
Socket
createSocket
(
InetAddress
address
,
int
port
,
boolean
ssl
)
throws
IOException
,
SQLException
{
if
(
ssl
)
{
SecureSocketFactory
f
=
SecureSocketFactory
.
getInstance
();
return
f
.
createSocket
(
address
,
port
);
}
else
{
return
new
Socket
(
address
,
port
);
}
}
public
static
ServerSocket
createServerSocket
(
int
port
,
boolean
ssl
)
throws
SQLException
{
try
{
return
createServerSocketTry
(
port
,
ssl
);
}
catch
(
SQLException
e
)
{
// try again
return
createServerSocketTry
(
port
,
ssl
);
}
}
private
static
ServerSocket
createServerSocketTry
(
int
port
,
boolean
ssl
)
throws
SQLException
{
// TODO server sockets: maybe automatically open the next port if this is in use?
// TODO server sockets: maybe a parameter to allow anonymous ssl?
try
{
if
(
ssl
)
{
SecureSocketFactory
f
=
SecureSocketFactory
.
getInstance
();
return
f
.
createServerSocket
(
port
);
}
else
{
return
new
ServerSocket
(
port
);
}
}
catch
(
BindException
be
)
{
throw
Message
.
getSQLException
(
Message
.
EXCEPTION_OPENING_PORT_1
,
new
String
[]{
""
+
port
},
be
);
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
}
h2/src/main/org/h2/util/ObjectArray.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.util.Collection
;
import
java.util.Comparator
;
import
java.util.Iterator
;
import
org.h2.engine.Constants
;
/**
* @author Thomas
*/
public
class
ObjectArray
{
private
static
final
int
SIZE_INIT
=
4
,
SIZE_SHRINK
=
256
;
private
Object
[]
data
;
private
int
size
;
public
ObjectArray
()
{
this
(
SIZE_INIT
);
}
public
ObjectArray
(
int
size
)
{
data
=
new
Object
[
size
>
1
?
size
:
1
];
}
public
ObjectArray
(
Object
[]
data
)
{
this
.
data
=
data
;
size
=
data
.
length
;
}
public
ObjectArray
(
Collection
collection
)
{
// TODO lib: Collection should not be required
size
=
collection
.
size
();
data
=
new
Object
[
size
];
Iterator
it
=
collection
.
iterator
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
data
[
i
]
=
it
.
next
();
}
}
public
void
add
(
Object
value
)
{
ensureCapacity
(
size
);
data
[
size
++]
=
value
;
}
public
Object
get
(
int
i
)
{
if
(
Constants
.
CHECK
&&
i
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
return
data
[
i
];
}
public
Object
remove
(
int
i
)
{
// TODO performance: the app should (where possible) remove from end to start, to avoid O(n^2)
if
(
Constants
.
CHECK
&&
i
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
Object
value
=
data
[
i
];
System
.
arraycopy
(
data
,
i
+
1
,
data
,
i
,
size
-
i
-
1
);
size
--;
data
[
size
]
=
null
;
// TODO optimization / lib: could shrink ObjectArray on element remove
return
value
;
}
public
void
removeRange
(
int
from
,
int
to
)
{
if
(
Constants
.
CHECK
&&
(
to
>
size
||
from
>
to
))
{
throw
new
ArrayIndexOutOfBoundsException
(
"to="
+
to
+
" from="
+
from
+
" size="
+
size
);
}
System
.
arraycopy
(
data
,
to
,
data
,
from
,
size
-
to
);
size
-=
to
-
from
;
for
(
int
i
=
size
+
(
to
-
from
)
-
1
;
i
>=
size
;
i
--)
{
data
[
i
]
=
null
;
}
}
public
void
setSize
(
int
i
)
{
ensureCapacity
(
i
);
this
.
size
=
i
;
}
private
void
ensureCapacity
(
int
i
)
{
while
(
i
>=
data
.
length
)
{
Object
[]
d
=
new
Object
[
data
.
length
*
2
];
System
.
arraycopy
(
data
,
0
,
d
,
0
,
data
.
length
);
data
=
d
;
}
}
public
void
add
(
int
i
,
Object
value
)
{
if
(
Constants
.
CHECK
&&
i
>
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
ensureCapacity
(
size
);
if
(
i
==
size
)
{
add
(
value
);
}
else
{
System
.
arraycopy
(
data
,
i
,
data
,
i
+
1
,
size
-
i
);
data
[
i
]
=
value
;
size
++;
}
}
public
void
set
(
int
i
,
Object
value
)
{
if
(
Constants
.
CHECK
&&
i
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
"i="
+
i
+
" size="
+
size
);
}
data
[
i
]
=
value
;
}
public
int
size
()
{
return
size
;
}
public
void
toArray
(
Object
[]
array
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
array
[
i
]
=
data
[
i
];
}
}
public
void
clear
()
{
if
(
data
.
length
>
SIZE_SHRINK
)
{
data
=
new
Object
[
SIZE_INIT
];
}
else
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
data
[
i
]
=
null
;
}
}
size
=
0
;
}
public
int
indexOf
(
Object
o
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(
data
[
i
]
==
o
)
{
return
i
;
}
}
return
-
1
;
}
public
void
addAll
(
ObjectArray
list
)
{
for
(
int
i
=
0
;
i
<
list
.
size
;
i
++)
{
add
(
list
.
get
(
i
));
}
}
private
void
swap
(
int
l
,
int
r
)
{
Object
t
=
data
[
r
];
data
[
r
]
=
data
[
l
];
data
[
l
]
=
t
;
}
public
void
sort
(
Comparator
comp
)
{
sort
(
comp
,
0
,
size
-
1
);
}
private
void
sort
(
Comparator
comp
,
int
l
,
int
r
)
{
int
i
,
j
;
while
(
r
-
l
>
10
)
{
i
=
(
r
+
l
)
>>
1
;
if
(
comp
.
compare
(
get
(
l
),
get
(
r
))
>
0
)
{
swap
(
l
,
r
);
}
if
(
comp
.
compare
(
get
(
i
),
get
(
l
))
<
0
)
{
swap
(
l
,
i
);
}
else
if
(
comp
.
compare
(
get
(
i
),
get
(
r
))
>
0
)
{
swap
(
i
,
r
);
}
j
=
r
-
1
;
swap
(
i
,
j
);
Object
p
=
get
(
j
);
i
=
l
;
while
(
true
)
{
do
{
++
i
;
}
while
(
comp
.
compare
(
get
(
i
),
p
)
<
0
);
do
{
--
j
;
}
while
(
comp
.
compare
(
get
(
j
),
p
)
>
0
);
if
(
i
>=
j
)
{
break
;
}
swap
(
i
,
j
);
}
swap
(
i
,
r
-
1
);
sort
(
comp
,
l
,
i
-
1
);
l
=
i
+
1
;
}
for
(
i
=
l
+
1
;
i
<=
r
;
i
++)
{
Object
t
=
get
(
i
);
for
(
j
=
i
-
1
;
j
>=
l
&&
(
comp
.
compare
(
get
(
j
),
t
)
>
0
);
j
--)
{
set
(
j
+
1
,
get
(
j
));
}
set
(
j
+
1
,
t
);
}
}
// public void sortInsertion(Comparator comp) {
// for (int i = 1, j; i < size(); i++) {
// Object t = get(i);
// for (j = i - 1; j >= 0 && (comp.compare(get(j), t) < 0); j--) {
// set(j + 1, get(j));
// }
// set(j + 1, t);
// }
// }
}
h2/src/main/org/h2/util/Permutations.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
org.h2.message.Message
;
// code originally from http://www.koders.com/java/fidD3445CD11B1DC687F6B8911075E7F01E23171553.aspx
// http://www.koders.com/java/fidD3445CD11B1DC687F6B8911075E7F01E23171553.aspx
/**
* The Permutations class provides an enumeration of all permutations of an
* array of objects. Each permutation is simply an ordered list of the group.
* <p>
* For example, to see all of the ways we can select a school representative and
* an alternate from a list of 4 children, begin with an array of names::
* <blockquote>
*
* <pre>
* Object[] children = { Leonardo, Monica, Nathan, Olivia };
* </pre>
*
* </blockquote> To see all 2-permutations of these 4 names, create and use a
* Permutations enumeration: <blockquote>
*
* <pre>
*
* Permutations c = new Permutations(children, 2);
* while (c.hasMoreElements()) {
* Object[] perm = (Object[])c.nextElement();
* for (int i = 0; i < perm.length; i++) {
* System.out.print(perm[i] + );
* }
* System.out.println();
* }
*
* </pre>
*
* </blockquote> This will print out: <blockquote>
*
* <pre>
*
* Leonardo Monica
* Leonardo Nathan
* Leonardo Olivia
* Monica Leonardo
* Monica Nathan
* Monica Olivia
* Nathan Leonardo
* Nathan Monica
* Nathan Olivia
* Olivia Leonardo
* Olivia Monica
* Olivia Nathan
*
* </pre>
*
* </blockquote>
*
*/
public
class
Permutations
implements
java
.
util
.
Enumeration
{
private
Object
[]
inArray
;
private
int
n
,
m
;
private
int
[]
index
;
private
boolean
hasMore
=
true
;
/**
* Create a Permutation to enumerate through all possible lineups of the
* supplied array of Objects.
*
* @param inArray
* the group to line up
* @exception CombinatoricException
* Should never happen with this interface
*
*/
public
Permutations
(
Object
[]
inArray
)
{
this
(
inArray
,
inArray
.
length
);
}
/**
* Create a Permutation to enumerate through all possible lineups of the
* supplied array of Objects.
*
* @param inArray
* the group to line up
* @param m
* the number of objects to use
* @exception CombinatoricException
* if m is greater than the length of inArray, or less than
* 0.
*/
public
Permutations
(
Object
[]
inArray
,
int
m
)
{
this
.
inArray
=
inArray
;
this
.
n
=
inArray
.
length
;
this
.
m
=
m
;
// throw exception unless n >= m >= 0
if
(
n
<
m
||
m
<
0
)
{
throw
Message
.
getInternalError
(
"n < m or m < 0"
);
}
/**
* index is an array of ints that keep track of the next permutation to
* return. For example, an index on a permutation of 3 things might
* contain {1 2 0}. This index will be followed by {2 0 1} and {2 1 0}.
* Initially, the index is {0 ... n - 1}.
*/
index
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
index
[
i
]
=
i
;
}
/**
* The elements from m to n are always kept ascending right to left.
* This keeps the dip in the interesting region.
*/
reverseAfter
(
m
-
1
);
}
/**
* @return true, unless we have already returned the last permutation.
*/
public
boolean
hasMoreElements
()
{
return
hasMore
;
}
/**
* Move the index forward a notch. The algorithm first finds the rightmost
* index that is less than its neighbor to the right. This is the dip point.
* The algorithm next finds the least element to the right of the dip that
* is greater than the dip. That element is switched with the dip. Finally,
* the list of elements to the right of the dip is reversed.
* <p>
* For example, in a permutation of 5 items, the index may be {1, 2, 4, 3,
* 0}. The dip is 2 the rightmost element less than its neighbor on its
* right. The least element to the right of 2 that is greater than 2 is 3.
* These elements are swapped, yielding {1, 3, 4, 2, 0}, and the list right
* of the dip point is reversed, yielding {1, 3, 0, 2, 4}.
* <p>
* The algorithm is from Applied Combinatorics, by Alan Tucker.
*
*/
private
void
moveIndex
()
{
// find the index of the first element that dips
int
i
=
rightmostDip
();
if
(
i
<
0
)
{
hasMore
=
false
;
return
;
}
// find the least greater element to the right of the dip
int
leastToRightIndex
=
i
+
1
;
for
(
int
j
=
i
+
2
;
j
<
n
;
j
++)
{
if
(
index
[
j
]
<
index
[
leastToRightIndex
]
&&
index
[
j
]
>
index
[
i
])
{
leastToRightIndex
=
j
;
}
}
// switch dip element with least greater element to its right
int
t
=
index
[
i
];
index
[
i
]
=
index
[
leastToRightIndex
];
index
[
leastToRightIndex
]
=
t
;
if
(
m
-
1
>
i
)
{
// reverse the elements to the right of the dip
reverseAfter
(
i
);
// reverse the elements to the right of m - 1
reverseAfter
(
m
-
1
);
}
}
/**
* @return java.lang.Object, the next permutation of the original Object
* array.
* <p>
* Actually, an array of Objects is returned. The declaration must
* say just Object, because the Permutations class implements
* Enumeration, which declares that the nextElement() returns a
* plain Object. Users must cast the returned object to (Object[]).
*/
public
Object
nextElement
()
{
if
(!
hasMore
)
{
return
null
;
}
Object
[]
out
=
new
Object
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++)
{
out
[
i
]
=
inArray
[
index
[
i
]];
}
moveIndex
();
return
out
;
}
/**
* Reverse the index elements to the right of the specified index.
*/
private
void
reverseAfter
(
int
i
)
{
int
start
=
i
+
1
;
int
end
=
n
-
1
;
while
(
start
<
end
)
{
int
t
=
index
[
start
];
index
[
start
]
=
index
[
end
];
index
[
end
]
=
t
;
start
++;
end
--;
}
}
/**
* @return int the index of the first element from the right that is less
* than its neighbor on the right.
*/
private
int
rightmostDip
()
{
for
(
int
i
=
n
-
2
;
i
>=
0
;
i
--)
{
if
(
index
[
i
]
<
index
[
i
+
1
])
{
return
i
;
}
}
return
-
1
;
}
}
h2/src/main/org/h2/util/RandomUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.SecureRandom
;
import
java.util.Random
;
public
class
RandomUtils
{
private
static
SecureRandom
secureRandom
;
private
static
Random
random
;
static
{
try
{
secureRandom
=
SecureRandom
.
getInstance
(
"SHA1PRNG"
);
random
=
new
Random
(
secureRandom
.
nextLong
());
}
catch
(
NoSuchAlgorithmException
e
)
{
// random is null if the algorithm is not found
// TODO log exception
random
=
new
Random
();
}
}
public
static
long
getSecureLong
()
{
if
(
secureRandom
==
null
)
{
byte
[]
buff
=
SecureRandom
.
getSeed
(
8
);
return
ByteUtils
.
readLong
(
buff
,
0
);
}
return
secureRandom
.
nextLong
();
}
public
static
byte
[]
getSecureBytes
(
int
len
)
{
if
(
secureRandom
==
null
)
{
return
SecureRandom
.
getSeed
(
len
);
}
if
(
len
<=
0
)
{
len
=
1
;
}
byte
[]
buff
=
new
byte
[
len
];
secureRandom
.
nextBytes
(
buff
);
return
buff
;
}
public
static
int
nextInt
(
int
max
)
{
return
random
.
nextInt
(
max
);
}
}
h2/src/main/org/h2/util/ReaderInputStream.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStreamWriter
;
import
java.io.Reader
;
import
java.io.UnsupportedEncodingException
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
ReaderInputStream
extends
InputStream
{
private
Reader
reader
;
private
int
pos
;
private
int
remaining
;
private
char
[]
chars
;
private
byte
[]
buffer
;
private
ByteArrayOutputStream
out
;
private
OutputStreamWriter
writer
;
public
ReaderInputStream
(
Reader
reader
)
throws
SQLException
{
chars
=
new
char
[
Constants
.
IO_BUFFER_SIZE
];
this
.
reader
=
reader
;
out
=
new
ByteArrayOutputStream
(
Constants
.
IO_BUFFER_SIZE
);
try
{
writer
=
new
OutputStreamWriter
(
out
,
Constants
.
UTF8
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
Message
.
convert
(
e
);
}
}
private
void
fillBuffer
()
throws
IOException
{
if
(
remaining
==
0
)
{
pos
=
0
;
remaining
=
reader
.
read
(
chars
,
0
,
Constants
.
IO_BUFFER_SIZE
);
if
(
remaining
<
0
)
{
return
;
}
// String s = new String(chars, 0, remaining);
// try {
// buffer = StringUtils.asBytes(s);
// } catch(SQLException e) {
// throw new IOException(e.toString());
// }
writer
.
write
(
chars
,
0
,
remaining
);
writer
.
flush
();
buffer
=
out
.
toByteArray
();
remaining
=
buffer
.
length
;
out
.
reset
();
}
}
public
int
read
()
throws
IOException
{
if
(
remaining
==
0
)
{
fillBuffer
();
}
if
(
remaining
<
0
)
{
return
-
1
;
}
remaining
--;
return
buffer
[
pos
++]
&
0xff
;
}
}
h2/src/main/org/h2/util/ResourceData.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
class
ResourceData
{
public
static
void
load
()
{
// dummy implementation
}
}
h2/src/main/org/h2/util/Resources.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.PrintWriter
;
import
java.util.HashMap
;
public
class
Resources
{
private
static
final
HashMap
FILES
=
new
HashMap
();
static
{
ResourceData
.
load
();
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
inDir
=
args
.
length
>
0
?
args
[
0
]
:
null
;
String
outDir
=
args
.
length
>
1
?
args
[
1
]
:
null
;
new
Resources
().
run
(
inDir
,
outDir
);
}
void
run
(
String
outDir
,
String
inDir
)
throws
Exception
{
if
(
outDir
==
null
)
{
outDir
=
"bin"
;
}
if
(
inDir
==
null
)
{
inDir
=
"src/main"
;
}
if
(
new
File
(
outDir
+
"/org/h2/util"
).
exists
())
{
String
file
=
outDir
+
"/org/h2/util/ResourceData.java"
;
PrintWriter
out
=
new
PrintWriter
(
new
FileWriter
(
file
));
out
.
println
(
"package org.h2.util;"
);
out
.
println
(
"// Do not change this code manually"
);
out
.
println
(
"// This code is generated by "
+
getClass
().
getName
());
out
.
println
(
"class ResourceData {"
);
out
.
println
(
" public static void load() {"
);
generate
(
out
,
inDir
+
"/org/h2/res"
,
"org.h2"
);
generate
(
out
,
inDir
+
"/org/h2/server/web/res"
,
"org.h2.server.web"
);
out
.
println
(
" }"
);
out
.
println
(
"}"
);
out
.
close
();
}
}
void
generate
(
PrintWriter
out
,
String
inDir
,
String
packageName
)
throws
Exception
{
File
dir
=
new
File
(
inDir
);
String
[]
list
=
dir
.
list
();
for
(
int
i
=
0
;
list
!=
null
&&
i
<
list
.
length
;
i
++)
{
File
f
=
new
File
(
dir
,
list
[
i
]);
if
(!
f
.
isFile
())
{
continue
;
}
if
(
list
[
i
].
endsWith
(
".java"
))
{
continue
;
}
String
name
=
"/"
+
packageName
.
replace
(
'.'
,
'/'
)
+
"/res/"
+
f
.
getName
();
// System.out.println(name+": "+f.length());
FileInputStream
in
=
new
FileInputStream
(
f
);
byte
[]
buffer
=
IOUtils
.
readBytesAndClose
(
in
,
0
);
String
s
=
ByteUtils
.
convertToBinString
(
buffer
);
out
.
print
(
" Resources.add("
+
StringUtils
.
quoteJavaString
(
name
)
+
", "
);
out
.
print
(
"new String[]{"
);
do
{
String
s2
;
if
(
s
.
length
()
<
65000
)
{
s2
=
s
;
s
=
null
;
}
else
{
s2
=
s
.
substring
(
0
,
65000
);
s
=
s
.
substring
(
65000
);
}
out
.
print
(
StringUtils
.
quoteJavaString
(
s2
));
out
.
println
(
", "
);
}
while
(
s
!=
null
);
out
.
println
(
"});"
);
}
}
static
void
add
(
String
name
,
String
[]
data
)
{
StringBuffer
buff
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
data
.
length
;
i
++)
{
buff
.
append
(
data
[
i
]);
}
FILES
.
put
(
name
,
ByteUtils
.
convertBinStringToBytes
(
buff
.
toString
()));
}
public
static
byte
[]
get
(
String
name
)
throws
IOException
{
byte
[]
data
;
if
(
FILES
.
size
()
==
0
)
{
// TODO web: security (check what happens with files like 'lpt1.txt' on windows)
InputStream
in
=
Resources
.
class
.
getResourceAsStream
(
name
);
if
(
in
==
null
)
{
data
=
null
;
}
else
{
data
=
IOUtils
.
readBytesAndClose
(
in
,
0
);
}
}
else
{
data
=
(
byte
[])
FILES
.
get
(
name
);
}
return
data
==
null
?
new
byte
[
0
]
:
data
;
}
}
h2/src/main/org/h2/util/ScriptReader.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.IOException
;
import
java.io.Reader
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
public
class
ScriptReader
{
private
Reader
reader
;
private
boolean
end
;
private
boolean
insideRemark
;
private
boolean
blockRemark
;
private
boolean
skipRemarks
;
public
ScriptReader
(
Reader
reader
)
{
this
.
reader
=
reader
;
}
private
int
read
()
throws
SQLException
{
try
{
return
reader
.
read
();
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
String
readStatement
()
throws
SQLException
{
if
(
end
)
{
return
null
;
}
StringBuffer
buff
=
new
StringBuffer
();
int
c
=
read
();
while
(
true
)
{
if
(
c
<
0
)
{
end
=
true
;
return
buff
.
length
()
==
0
?
null
:
buff
.
toString
();
}
else
if
(
c
==
';'
)
{
break
;
}
switch
(
c
)
{
case
'\''
:
buff
.
append
((
char
)
c
);
while
(
true
)
{
c
=
read
();
if
(
c
<
0
)
{
break
;
}
buff
.
append
((
char
)
c
);
if
(
c
==
'\''
)
{
break
;
}
}
c
=
read
();
break
;
case
'"'
:
buff
.
append
((
char
)
c
);
while
(
true
)
{
c
=
read
();
if
(
c
<
0
)
{
break
;
}
buff
.
append
((
char
)
c
);
if
(
c
==
'\"'
)
{
break
;
}
}
c
=
read
();
break
;
case
'/'
:
{
int
last
=
c
;
c
=
read
();
if
(
c
==
'*'
)
{
// block comment
insideRemark
=
true
;
blockRemark
=
true
;
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
last
);
buff
.
append
((
char
)
c
);
}
while
(
true
)
{
c
=
read
();
if
(
c
<
0
)
{
break
;
}
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
c
);
}
if
(
c
==
'*'
)
{
c
=
read
();
if
(
c
<
0
)
{
break
;
}
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
c
);
}
if
(
c
==
'/'
)
{
insideRemark
=
false
;
break
;
}
}
}
c
=
read
();
}
else
if
(
c
==
'/'
)
{
// single line comment
insideRemark
=
true
;
blockRemark
=
false
;
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
last
);
buff
.
append
((
char
)
c
);
}
while
(
true
)
{
c
=
read
();
if
(
c
<
0
)
{
break
;
}
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
c
);
}
if
(
c
==
'\r'
||
c
==
'\n'
)
{
insideRemark
=
false
;
break
;
}
}
c
=
read
();
}
else
{
buff
.
append
((
char
)
last
);
}
break
;
}
case
'-'
:
{
int
last
=
c
;
c
=
read
();
if
(
c
==
'-'
)
{
// single line comment
insideRemark
=
true
;
blockRemark
=
false
;
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
last
);
buff
.
append
((
char
)
c
);
}
while
(
true
)
{
c
=
read
();
if
(
c
<
0
)
{
break
;
}
if
(!
skipRemarks
)
{
buff
.
append
((
char
)
c
);
}
if
(
c
==
'\r'
||
c
==
'\n'
)
{
insideRemark
=
false
;
break
;
}
}
c
=
read
();
}
else
{
buff
.
append
((
char
)
last
);
}
break
;
}
default
:
buff
.
append
((
char
)
c
);
c
=
read
();
}
}
return
buff
.
toString
();
}
public
boolean
isInsideRemark
()
{
return
insideRemark
;
}
public
boolean
isBlockRemark
()
{
return
blockRemark
;
}
public
void
setSkipRemarks
(
boolean
skipRemarks
)
{
this
.
skipRemarks
=
skipRemarks
;
}
}
h2/src/main/org/h2/util/SmallLRUCache.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
public
class
SmallLRUCache
extends
LinkedHashMap
{
private
static
final
long
serialVersionUID
=
3643268440910181829L
;
private
int
size
;
public
SmallLRUCache
(
int
size
)
{
this
.
size
=
size
;
}
protected
boolean
removeEldestEntry
(
Map
.
Entry
eldest
)
{
return
size
()
>
size
;
}
}
h2/src/main/org/h2/util/SmallMap.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
org.h2.message.Message
;
public
class
SmallMap
{
private
HashMap
map
=
new
HashMap
();
private
Object
cache
;
private
int
cacheId
;
private
int
lastId
;
private
int
maxElements
;
public
SmallMap
(
int
maxElements
)
{
this
.
maxElements
=
maxElements
;
}
public
int
addObject
(
int
id
,
Object
o
)
{
if
(
map
.
size
()
>
maxElements
*
2
)
{
Iterator
it
=
map
.
keySet
().
iterator
();
while
(
it
.
hasNext
())
{
Integer
k
=
(
Integer
)
it
.
next
();
if
(
k
.
intValue
()
+
maxElements
<
lastId
)
{
it
.
remove
();
}
}
}
if
(
id
>
lastId
)
{
lastId
=
id
;
}
map
.
put
(
new
Integer
(
id
),
o
);
cacheId
=
id
;
cache
=
o
;
return
id
;
}
public
void
freeObject
(
int
id
)
{
if
(
cacheId
==
id
)
{
cacheId
=
-
1
;
cache
=
null
;
}
map
.
remove
(
new
Integer
(
id
));
}
public
Object
getObject
(
int
id
,
boolean
ifAvailable
)
throws
SQLException
{
if
(
id
==
cacheId
)
{
return
cache
;
}
Object
obj
=
map
.
get
(
new
Integer
(
id
));
if
(
obj
==
null
&&
!
ifAvailable
)
{
throw
Message
.
getSQLException
(
Message
.
OBJECT_CLOSED
);
}
return
obj
;
}
}
h2/src/main/org/h2/util/StartBrowser.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.IOException
;
public
class
StartBrowser
{
public
static
void
openURL
(
String
url
)
{
String
osName
=
System
.
getProperty
(
"os.name"
);
try
{
if
(
osName
.
startsWith
(
"Windows"
))
{
Runtime
.
getRuntime
().
exec
(
"rundll32 url.dll,FileProtocolHandler "
+
url
);
}
else
if
(
osName
.
startsWith
(
"Mac OS X"
))
{
// Runtime.getRuntime().exec("open -a safari " + url);
// Runtime.getRuntime().exec("open " + url + "/index.html");
Runtime
.
getRuntime
().
exec
(
"open "
+
url
);
}
else
{
System
.
out
.
println
(
"Please open a browser and go to "
+
url
);
}
}
catch
(
IOException
e
)
{
System
.
out
.
println
(
"Failed to start a browser to open the url "
+
url
);
e
.
printStackTrace
();
}
}
}
h2/src/main/org/h2/util/StringCache.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.lang.ref.WeakReference
;
import
org.h2.engine.Constants
;
public
class
StringCache
{
private
static
final
boolean
ENABLED
=
true
;
private
static
WeakReference
weakCache
=
new
WeakReference
(
null
);
// testing: cacheHit / miss are public!
// public static int cacheHit = 0, cacheMiss = 0;
// 4703
// public static String get(String s) {
// if (s == null) {
// return s;
// } else if (s.length() == 0) {
// return "";
// }
// if (!Constants.USE_OBJECT_CACHE || !ENABLED || s.length() > MAX_CACHE_SIZE / 10) {
// return s;
// }
// int hash = s.hashCode();
// int index = hash & (Constants.OBJECT_CACHE_SIZE - 1);
// String cached = cache[index];
// if (cached != null) {
// if (s.equals(cached)) {
// // cacheHit++;
// return cached;
// }
// }
// // cacheMiss++;
// replace(index, s);
// return s;
// }
// 3500
// public static String get(String s) {
// return s;
// }
// 3906
public
static
String
get
(
String
s
)
{
if
(!
Constants
.
USE_OBJECT_CACHE
||
!
ENABLED
)
{
return
s
;
}
if
(
s
==
null
)
{
return
s
;
}
else
if
(
s
.
length
()
==
0
)
{
return
""
;
}
String
[]
cache
=
(
String
[])
weakCache
.
get
();
int
hash
=
s
.
hashCode
();
if
(
cache
==
null
)
{
cache
=
new
String
[
Constants
.
OBJECT_CACHE_SIZE
];
weakCache
=
new
WeakReference
(
cache
);
}
int
index
=
hash
&
(
Constants
.
OBJECT_CACHE_SIZE
-
1
);
String
cached
=
cache
[
index
];
if
(
cached
!=
null
)
{
if
(
s
.
equals
(
cached
))
{
// cacheHit++;
return
cached
;
}
}
cache
[
index
]
=
s
;
return
s
;
}
public
static
String
getNew
(
String
s
)
{
if
(!
Constants
.
USE_OBJECT_CACHE
||
!
ENABLED
)
{
return
s
;
}
if
(
s
==
null
)
{
return
s
;
}
else
if
(
s
.
length
()
==
0
)
{
return
""
;
}
String
[]
cache
=
(
String
[])
weakCache
.
get
();
int
hash
=
s
.
hashCode
();
if
(
cache
==
null
)
{
cache
=
new
String
[
Constants
.
OBJECT_CACHE_SIZE
];
weakCache
=
new
WeakReference
(
cache
);
}
int
index
=
hash
&
(
Constants
.
OBJECT_CACHE_SIZE
-
1
);
String
cached
=
cache
[
index
];
if
(
cached
!=
null
)
{
if
(
s
.
equals
(
cached
))
{
// cacheHit++;
return
cached
;
}
}
s
=
new
String
(
s
);
cache
[
index
]
=
s
;
return
s
;
}
public
static
void
clearCache
()
{
weakCache
=
new
WeakReference
(
null
);
}
}
h2/src/main/org/h2/util/StringUtils.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLEncoder
;
import
java.sql.SQLException
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.Locale
;
import
java.util.TimeZone
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
StringUtils
{
// TODO hack for gcj
//#GCJHACK private static final Class[] gcjClasses = {
//#GCJHACK gnu.gcj.convert.Input_ASCII.class,
//#GCJHACK gnu.gcj.convert.Input_UTF8.class,
//#GCJHACK gnu.gcj.convert.Input_8859_1.class,
//#GCJHACK gnu.gcj.convert.Output_ASCII.class,
//#GCJHACK gnu.gcj.convert.Output_UTF8.class,
//#GCJHACK gnu.gcj.convert.UnicodeToBytes.class,
//#GCJHACK gnu.gcj.convert.BytesToUnicode.class,
//#GCJHACK gnu.java.locale.Calendar.class,
//#GCJHACK gnu.java.locale.LocaleInformation.class,
//#GCJHACK gnu.java.locale.LocaleInformation_de.class,
//#GCJHACK java.util.GregorianCalendar.class,
//#GCJHACK };
public
static
boolean
equals
(
String
a
,
String
b
)
{
if
(
a
==
null
)
{
return
b
==
null
;
}
return
a
.
equals
(
b
);
}
public
static
String
toUpperEnglish
(
String
s
)
{
return
s
.
toUpperCase
(
Locale
.
ENGLISH
);
}
public
static
String
toLowerEnglish
(
String
s
)
{
return
s
.
toLowerCase
(
Locale
.
ENGLISH
);
}
public
static
String
getDefaultCharset
()
{
return
System
.
getProperty
(
"file.encoding"
);
}
public
static
String
quoteStringSQL
(
String
s
)
{
StringBuffer
buff
=
new
StringBuffer
(
s
.
length
()+
2
);
buff
.
append
(
'\''
);
for
(
int
i
=
0
;
i
<
s
.
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
();
}
public
static
String
javaEncode
(
String
s
)
{
StringBuffer
buff
=
new
StringBuffer
(
s
.
length
());
for
(
int
i
=
0
;
i
<
s
.
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
();
}
public
static
String
addAsterix
(
String
s
,
int
index
)
{
if
(
s
!=
null
&&
index
<
s
.
length
())
{
s
=
s
.
substring
(
0
,
index
)
+
"[*]"
+
s
.
substring
(
index
);
}
return
s
;
}
private
static
SQLException
getFormatException
(
String
s
,
int
i
)
{
return
Message
.
getSQLException
(
Message
.
STRING_FORMAT_ERROR_1
,
addAsterix
(
s
,
i
));
}
public
static
String
javaDecode
(
String
s
)
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
(
s
.
length
());
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++)
{
char
c
=
s
.
charAt
(
i
);
if
(
c
==
'"'
)
{
break
;
}
else
if
(
c
==
'\\'
)
{
if
(
i
>=
s
.
length
())
{
throw
getFormatException
(
s
,
s
.
length
()-
1
);
}
c
=
s
.
charAt
(++
i
);
switch
(
c
)
{
case
't'
:
buff
.
append
(
'\t'
);
break
;
case
'r'
:
buff
.
append
(
'\r'
);
break
;
case
'n'
:
buff
.
append
(
'\n'
);
break
;
case
'b'
:
buff
.
append
(
'\b'
);
break
;
case
'f'
:
buff
.
append
(
'\f'
);
break
;
case
'"'
:
buff
.
append
(
'"'
);
break
;
case
'\\'
:
buff
.
append
(
'\\'
);
break
;
case
'u'
:
{
try
{
c
=
(
char
)(
Integer
.
parseInt
(
s
.
substring
(
i
+
1
,
i
+
5
),
16
));
}
catch
(
NumberFormatException
e
)
{
throw
getFormatException
(
s
,
i
);
}
i
+=
4
;
buff
.
append
(
c
);
break
;
}
default
:
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
try
{
c
=
(
char
)(
Integer
.
parseInt
(
s
.
substring
(
i
,
i
+
3
),
8
));
}
catch
(
NumberFormatException
e
)
{
throw
getFormatException
(
s
,
i
);
}
i
+=
2
;
buff
.
append
(
c
);
}
else
{
throw
getFormatException
(
s
,
i
);
}
}
}
else
{
buff
.
append
(
c
);
}
}
return
buff
.
toString
();
}
public
static
String
quoteJavaString
(
String
s
)
{
if
(
s
==
null
)
{
return
"null"
;
}
else
{
return
"\""
+
javaEncode
(
s
)
+
"\""
;
}
}
public
static
byte
[]
utf8Encode
(
String
s
)
throws
SQLException
{
try
{
// TODO UTF8: String.getBytes("UTF-8") only returns 1 byte for 0xd800-0xdfff
return
s
.
getBytes
(
Constants
.
UTF8
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
static
String
utf8Decode
(
byte
[]
utf8
)
{
try
{
return
new
String
(
utf8
,
Constants
.
UTF8
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
Message
.
convertToInternal
(
e
);
}
}
public
static
String
utf8Decode
(
byte
[]
bytes
,
int
offset
,
int
length
)
{
try
{
return
new
String
(
bytes
,
offset
,
length
,
Constants
.
UTF8
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
Message
.
convertToInternal
(
e
);
}
}
public
static
String
quoteJavaStringArray
(
String
[]
array
)
{
if
(
array
==
null
)
{
return
"null"
;
}
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
"new String[]{"
);
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
", "
);
}
buff
.
append
(
quoteJavaString
(
array
[
i
]));
}
buff
.
append
(
"}"
);
return
buff
.
toString
();
}
public
static
String
quoteJavaIntArray
(
int
[]
array
)
{
if
(
array
==
null
)
{
return
"null"
;
}
StringBuffer
buff
=
new
StringBuffer
(
2
*
array
.
length
);
buff
.
append
(
"new int[]{"
);
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
", "
);
}
buff
.
append
(
array
[
i
]);
}
buff
.
append
(
"}"
);
return
buff
.
toString
();
}
public
static
String
enclose
(
String
s
)
{
if
(
s
.
startsWith
(
"("
))
{
return
s
;
}
else
{
return
"("
+
s
+
")"
;
}
}
public
static
String
unEnclose
(
String
s
)
{
if
(
s
.
startsWith
(
"("
)
&&
s
.
endsWith
(
")"
))
{
return
s
.
substring
(
1
,
s
.
length
()-
1
);
}
else
{
return
s
;
}
}
public
static
String
urlEncode
(
String
s
)
{
try
{
return
URLEncoder
.
encode
(
s
,
"UTF-8"
);
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
();
return
s
;
}
// byte[] utf = utf8Encode(s);
// StringBuffer buff = new StringBuffer(utf.length);
// for(int i=0; i<utf.length; i++) {
//
// buff.append()
// }
}
public
static
String
urlDecode
(
String
encoded
)
throws
SQLException
{
byte
[]
buff
=
new
byte
[
encoded
.
length
()];
int
j
=
0
;
for
(
int
i
=
0
;
i
<
encoded
.
length
();
i
++)
{
char
ch
=
encoded
.
charAt
(
i
);
if
(
ch
==
'+'
)
{
buff
[
j
++]
=
' '
;
}
else
if
(
ch
==
'%'
)
{
buff
[
j
++]
=
(
byte
)
Integer
.
parseInt
(
encoded
.
substring
(
i
+
1
,
i
+
3
),
16
);
i
+=
2
;
}
else
{
if
(
Constants
.
CHECK
&&
(
ch
>
127
||
ch
<
' '
))
{
throw
new
IllegalArgumentException
(
"unexpected char "
+
(
int
)
ch
+
" decoding "
+
encoded
);
}
buff
[
j
++]
=
(
byte
)
ch
;
}
}
String
s
=
utf8Decode
(
buff
,
0
,
j
);
return
s
;
}
public
static
String
[]
arraySplit
(
String
s
,
char
separatorChar
,
boolean
trim
)
{
if
(
s
==
null
)
{
return
null
;
}
if
(
s
.
length
()==
0
)
{
return
new
String
[
0
];
}
ArrayList
list
=
new
ArrayList
();
StringBuffer
buff
=
new
StringBuffer
(
s
.
length
());
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++)
{
char
c
=
s
.
charAt
(
i
);
if
(
c
==
separatorChar
)
{
String
e
=
buff
.
toString
();
list
.
add
(
trim
?
e
.
trim
()
:
e
);
buff
.
setLength
(
0
);
}
else
if
(
c
==
'\\'
&&
i
<
s
.
length
()-
1
)
{
buff
.
append
(
s
.
charAt
(++
i
));
}
else
{
buff
.
append
(
c
);
}
}
String
e
=
buff
.
toString
();
list
.
add
(
trim
?
e
.
trim
()
:
e
);
String
[]
array
=
new
String
[
list
.
size
()];
list
.
toArray
(
array
);
return
array
;
}
public
static
String
arrayCombine
(
String
[]
list
,
char
separatorChar
)
{
StringBuffer
buff
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
separatorChar
);
}
String
s
=
list
[
i
];
if
(
s
==
null
)
{
s
=
""
;
}
for
(
int
j
=
0
;
j
<
s
.
length
();
j
++)
{
char
c
=
s
.
charAt
(
j
);
if
(
c
==
'\\'
||
c
==
separatorChar
)
{
buff
.
append
(
'\\'
);
}
buff
.
append
(
c
);
}
}
return
buff
.
toString
();
}
/**
* Formats a date using a format string
*/
public
static
String
formatDateTime
(
Date
date
,
String
format
,
String
locale
,
String
timezone
)
throws
SQLException
{
SimpleDateFormat
sdf
=
getDateFormat
(
format
,
locale
,
timezone
);
return
sdf
.
format
(
date
);
}
/**
* Parses a date using a format string
*/
public
static
Date
parseDateTime
(
String
date
,
String
format
,
String
locale
,
String
timezone
)
throws
SQLException
{
SimpleDateFormat
sdf
=
getDateFormat
(
format
,
locale
,
timezone
);
try
{
return
sdf
.
parse
(
date
);
}
catch
(
ParseException
e
)
{
throw
Message
.
getSQLException
(
Message
.
PARSE_ERROR_1
,
date
);
}
}
private
static
SimpleDateFormat
getDateFormat
(
String
format
,
String
locale
,
String
timezone
)
throws
SQLException
{
try
{
SimpleDateFormat
df
;
if
(
locale
==
null
)
{
df
=
new
SimpleDateFormat
(
format
);
}
else
{
Locale
l
=
new
Locale
(
locale
);
df
=
new
SimpleDateFormat
(
format
,
l
);
}
if
(
timezone
!=
null
)
{
df
.
setTimeZone
(
TimeZone
.
getTimeZone
(
timezone
));
}
return
df
;
}
catch
(
Exception
e
)
{
throw
Message
.
getSQLException
(
Message
.
PARSE_ERROR_1
,
format
+
"/"
+
locale
+
"/"
+
timezone
);
}
}
/**
* Creates an XML attribute of the form name="value".
* A single space is prepended to the name,
* so that multiple attributes can be concatenated.
* @param name
* @param value
* @return the attribute
*/
public
static
String
xmlAttr
(
String
name
,
String
value
)
{
return
" "
+
name
+
"=\""
+
xmlText
(
value
)
+
"\""
;
}
/**
* Create an XML node with optional attributes and content.
* The data is indented with 4 spaces if it contains a newline character.
*
* @param name the element name
* @param attributes the attributes (may be null)
* @param content the content (may be null)
* @return the node
*/
public
static
String
xmlNode
(
String
name
,
String
attributes
,
String
content
)
{
String
start
=
attributes
==
null
?
name
:
name
+
attributes
;
if
(
content
==
null
)
{
return
"<"
+
start
+
"/>\n"
;
}
else
{
if
(
content
.
indexOf
(
'\n'
)
>=
0
)
{
content
=
"\n"
+
indent
(
content
);
}
return
"<"
+
start
+
">"
+
content
+
"</"
+
name
+
">\n"
;
}
}
/**
* Indents a string with 4 spaces.
* @param s the string
* @return the indented string
*/
public
static
String
indent
(
String
s
)
{
return
indent
(
s
,
4
);
}
/**
* Indents a string with spaces.
* @param s the string
* @param spaces the number of spaces
* @return the indented string
*/
public
static
String
indent
(
String
s
,
int
spaces
)
{
StringBuffer
buff
=
new
StringBuffer
(
s
.
length
()
+
spaces
);
for
(
int
i
=
0
;
i
<
s
.
length
();
)
{
for
(
int
j
=
0
;
j
<
spaces
;
j
++)
{
buff
.
append
(
' '
);
}
int
n
=
s
.
indexOf
(
'\n'
,
i
);
n
=
n
<
0
?
s
.
length
()
:
n
+
1
;
buff
.
append
(
s
.
substring
(
i
,
n
));
i
=
n
;
}
if
(!
s
.
endsWith
(
"\n"
))
{
buff
.
append
(
'\n'
);
}
return
buff
.
toString
();
}
/**
* Escapes a comment.
* If the data contains '--', it is converted to '- -'.
* The data is indented with 4 spaces if it contains a newline character.
*
* @param data
* @return <!-- data -->
*/
public
static
String
xmlComment
(
String
data
)
{
int
idx
=
0
;
while
(
true
)
{
idx
=
data
.
indexOf
(
"--"
,
idx
);
if
(
idx
<
0
)
{
break
;
}
data
=
data
.
substring
(
0
,
idx
+
1
)
+
" "
+
data
.
substring
(
idx
+
1
);
}
// must have a space at the beginning and at the end,
// otherwise the data must not contain '-' as the first/last character
if
(
data
.
indexOf
(
'\n'
)
>=
0
)
{
return
"<!--\n"
+
indent
(
data
)
+
"-->\n"
;
}
else
{
return
"<!-- "
+
data
+
" -->\n"
;
}
}
/**
* Converts the data to a CDATA element.
* If the data contains ']]>', it is escaped as a text element.
* @param data
* @return <![CDATA[data]]>
*/
public
static
String
xmlCData
(
String
data
)
{
if
(
data
.
indexOf
(
"]]>"
)
>=
0
)
{
return
xmlText
(
data
);
}
boolean
newline
=
data
.
endsWith
(
"\n"
);
data
=
"<![CDATA["
+
data
+
"]]>"
;
return
newline
?
data
+
"\n"
:
data
;
}
/**
* Returns <?xml version="1.0"?>
* @return <?xml version="1.0"?>
*/
public
static
String
xmlStartDoc
()
{
return
"<?xml version=\"1.0\"?>\n"
;
}
/**
* Escapes an XML text element.
*
* @param text
* @return the escaped text
*/
public
static
String
xmlText
(
String
text
)
{
StringBuffer
buff
=
new
StringBuffer
(
text
.
length
());
for
(
int
i
=
0
;
i
<
text
.
length
();
i
++)
{
char
ch
=
text
.
charAt
(
i
);
switch
(
ch
)
{
case
'<'
:
buff
.
append
(
"<"
);
break
;
case
'>'
:
buff
.
append
(
">"
);
break
;
case
'&'
:
buff
.
append
(
"&"
);
break
;
case
'\''
:
buff
.
append
(
"'"
);
break
;
case
'\"'
:
buff
.
append
(
"""
);
break
;
case
'\r'
:
case
'\n'
:
case
'\t'
:
buff
.
append
(
ch
);
break
;
default
:
if
(
ch
<
' '
||
ch
>
127
)
{
buff
.
append
(
"&#x"
);
buff
.
append
(
Integer
.
toHexString
(
ch
));
buff
.
append
(
';'
);
}
else
{
buff
.
append
(
ch
);
}
}
}
return
buff
.
toString
();
}
public
static
String
replaceAll
(
String
s
,
String
before
,
String
after
)
{
int
index
=
0
;
while
(
true
)
{
int
next
=
s
.
indexOf
(
before
,
index
);
if
(
next
<
0
)
{
return
s
;
}
s
=
s
.
substring
(
0
,
next
)
+
after
+
s
.
substring
(
next
+
before
.
length
());
index
=
next
+
after
.
length
();
}
}
public
static
String
quoteIdentifier
(
String
s
)
{
StringBuffer
buff
=
new
StringBuffer
(
"\""
);
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++)
{
char
c
=
s
.
charAt
(
i
);
if
(
c
==
'"'
)
{
buff
.
append
(
c
);
}
buff
.
append
(
c
);
}
return
buff
.
append
(
'\"'
).
toString
();
}
}
h2/src/main/org/h2/util/TempFileDeleter.java
0 → 100644
浏览文件 @
3d2cd051
package
org
.
h2
.
util
;
import
java.lang.ref.PhantomReference
;
import
java.lang.ref.Reference
;
import
java.lang.ref.ReferenceQueue
;
import
java.util.HashMap
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
public
class
TempFileDeleter
{
private
static
ReferenceQueue
queue
=
new
ReferenceQueue
();
private
static
HashMap
refMap
=
new
HashMap
();
public
static
synchronized
Reference
addFile
(
String
fileName
,
Object
file
)
{
PhantomReference
ref
=
new
PhantomReference
(
file
,
queue
);
refMap
.
put
(
ref
,
fileName
);
deleteUnused
();
return
ref
;
}
public
static
synchronized
void
deleteFile
(
Reference
ref
,
String
fileName
)
{
if
(
ref
!=
null
)
{
String
f2
=
(
String
)
refMap
.
remove
(
ref
);
if
(
Constants
.
CHECK
&&
f2
!=
null
&&
fileName
!=
null
&&
!
f2
.
equals
(
fileName
))
{
throw
Message
.
getInternalError
(
"f2:"
+
f2
+
" f:"
+
fileName
);
}
}
if
(
fileName
!=
null
&&
FileUtils
.
exists
(
fileName
))
{
try
{
FileUtils
.
delete
(
fileName
);
}
catch
(
Exception
e
)
{
// TODO log such errors?
}
}
deleteUnused
();
}
public
static
void
deleteUnused
()
{
while
(
true
)
{
Reference
ref
=
queue
.
poll
();
if
(
ref
==
null
)
{
break
;
}
deleteFile
(
ref
,
null
);
}
}
public
static
void
stopAutoDelete
(
Reference
ref
,
String
fileName
)
{
if
(
ref
!=
null
)
{
String
f2
=
(
String
)
refMap
.
remove
(
ref
);
if
(
Constants
.
CHECK
&&
(
f2
==
null
||
!
f2
.
equals
(
fileName
)))
{
throw
Message
.
getInternalError
(
"f2:"
+
f2
+
" f:"
+
fileName
);
}
}
deleteUnused
();
}
}
h2/src/main/org/h2/util/TypeConverter.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.ObjectInputStream
;
import
java.io.ObjectOutputStream
;
import
java.io.Reader
;
import
java.io.StringReader
;
import
java.io.UnsupportedEncodingException
;
import
java.sql.Clob
;
import
java.sql.Date
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
java.util.Calendar
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SessionInterface
;
import
org.h2.jdbc.JdbcBlob
;
import
org.h2.jdbc.JdbcClob
;
import
org.h2.jdbc.JdbcConnection
;
import
org.h2.jdbc.JdbcSQLException
;
import
org.h2.message.Message
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
/**
* @author Thomas
*/
public
class
TypeConverter
{
public
static
Object
getDefaultForPrimitiveType
(
Class
clazz
)
{
if
(
clazz
==
Boolean
.
TYPE
)
{
return
Boolean
.
FALSE
;
}
else
if
(
clazz
==
Byte
.
TYPE
)
{
return
new
Byte
((
byte
)
0
);
}
else
if
(
clazz
==
Character
.
TYPE
)
{
return
new
Character
((
char
)
0
);
}
else
if
(
clazz
==
Short
.
TYPE
)
{
return
new
Short
((
short
)
0
);
}
else
if
(
clazz
==
Integer
.
TYPE
)
{
return
new
Integer
(
0
);
}
else
if
(
clazz
==
Long
.
TYPE
)
{
return
new
Long
(
0
);
}
else
if
(
clazz
==
Float
.
TYPE
)
{
return
new
Float
(
0
);
}
else
if
(
clazz
==
Double
.
TYPE
)
{
return
new
Double
(
0
);
}
else
{
throw
Message
.
getInternalError
(
"primitive="
+
clazz
.
toString
());
}
}
public
static
byte
[]
serialize
(
Object
obj
)
throws
SQLException
{
try
{
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
ObjectOutputStream
os
=
new
ObjectOutputStream
(
out
);
os
.
writeObject
(
obj
);
return
out
.
toByteArray
();
}
catch
(
Throwable
e
)
{
throw
Message
.
getSQLException
(
Message
.
SERIALIZATION_FAILED
,
null
,
e
);
}
}
public
static
Object
deserialize
(
byte
[]
data
)
throws
SQLException
{
try
{
ByteArrayInputStream
in
=
new
ByteArrayInputStream
(
data
);
ObjectInputStream
is
=
new
ObjectInputStream
(
in
);
Object
obj
=
is
.
readObject
();
return
obj
;
}
catch
(
Throwable
e
)
{
throw
Message
.
getSQLException
(
Message
.
DESERIALIZATION_FAILED
,
null
,
e
);
}
}
public
static
Reader
getReader
(
InputStream
in
)
throws
SQLException
{
try
{
// InputStreamReader may read some more bytes
return
in
==
null
?
null
:
new
InputStreamReader
(
in
,
Constants
.
UTF8
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
static
InputStream
getInputStream
(
String
s
)
throws
SQLException
{
return
new
ByteArrayInputStream
(
StringUtils
.
utf8Encode
(
s
));
}
public
static
InputStream
getInputStream
(
Reader
x
)
throws
SQLException
{
return
x
==
null
?
null
:
new
ReaderInputStream
(
x
);
}
public
static
Reader
getReader
(
String
s
)
{
return
new
StringReader
(
s
);
}
public
static
Date
convertDateToCalendar
(
Date
x
,
Calendar
calendar
)
throws
SQLException
{
return
x
==
null
?
x
:
new
Date
(
getLocalTime
(
x
,
calendar
));
}
public
static
Time
convertTimeToCalendar
(
Time
x
,
Calendar
calendar
)
throws
SQLException
{
return
x
==
null
?
x
:
new
Time
(
getLocalTime
(
x
,
calendar
));
}
public
static
Timestamp
convertTimestampToCalendar
(
Timestamp
x
,
Calendar
calendar
)
throws
SQLException
{
if
(
x
!=
null
)
{
Timestamp
y
=
new
Timestamp
(
getLocalTime
(
x
,
calendar
));
// fix the nano seconds
y
.
setNanos
(
x
.
getNanos
());
x
=
y
;
}
return
x
;
}
public
static
Value
convertDateToUniversal
(
Date
x
,
Calendar
source
)
throws
SQLException
{
return
ValueDate
.
get
(
new
Date
(
TypeConverter
.
getUniversalTime
(
source
,
x
)));
}
public
static
Value
convertTimeToUniversal
(
Time
x
,
Calendar
source
)
throws
SQLException
{
return
ValueTime
.
get
(
new
Time
(
TypeConverter
.
getUniversalTime
(
source
,
x
)));
}
public
static
Value
convertTimestampToUniversal
(
Timestamp
x
,
Calendar
source
)
throws
SQLException
{
Timestamp
y
=
new
Timestamp
(
TypeConverter
.
getUniversalTime
(
source
,
x
));
// fix the nano seconds
y
.
setNanos
(
x
.
getNanos
());
return
ValueTimestamp
.
get
(
y
);
}
private
static
long
getUniversalTime
(
Calendar
source
,
java
.
util
.
Date
x
)
throws
SQLException
{
if
(
source
==
null
)
{
throw
Message
.
getInvalidValueException
(
"calendar"
,
null
);
}
source
=
(
Calendar
)
source
.
clone
();
Calendar
universal
=
Calendar
.
getInstance
();
source
.
setTime
(
x
);
convertTime
(
source
,
universal
);
return
universal
.
getTime
().
getTime
();
}
private
static
long
getLocalTime
(
java
.
util
.
Date
x
,
Calendar
target
)
throws
SQLException
{
if
(
target
==
null
)
{
throw
Message
.
getInvalidValueException
(
"calendar"
,
null
);
}
target
=
(
Calendar
)
target
.
clone
();
Calendar
local
=
Calendar
.
getInstance
();
local
.
setTime
(
x
);
convertTime
(
local
,
target
);
return
target
.
getTime
().
getTime
();
}
private
static
void
convertTime
(
Calendar
from
,
Calendar
to
)
{
to
.
set
(
Calendar
.
YEAR
,
from
.
get
(
Calendar
.
YEAR
));
to
.
set
(
Calendar
.
MONTH
,
from
.
get
(
Calendar
.
MONTH
));
to
.
set
(
Calendar
.
DAY_OF_MONTH
,
from
.
get
(
Calendar
.
DAY_OF_MONTH
));
to
.
set
(
Calendar
.
HOUR_OF_DAY
,
from
.
get
(
Calendar
.
HOUR_OF_DAY
));
to
.
set
(
Calendar
.
MINUTE
,
from
.
get
(
Calendar
.
MINUTE
));
to
.
set
(
Calendar
.
SECOND
,
from
.
get
(
Calendar
.
SECOND
));
to
.
set
(
Calendar
.
MILLISECOND
,
from
.
get
(
Calendar
.
MILLISECOND
));
}
public
static
Reader
getAsciiReader
(
InputStream
x
)
throws
SQLException
{
try
{
return
x
==
null
?
null
:
new
InputStreamReader
(
x
,
"US-ASCII"
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
static
Object
convertTo
(
SessionInterface
session
,
JdbcConnection
conn
,
Value
v
,
Class
paramClass
)
throws
JdbcSQLException
{
if
(
paramClass
==
java
.
sql
.
Blob
.
class
)
{
return
new
JdbcBlob
(
session
,
conn
,
v
,
0
);
}
else
if
(
paramClass
==
Clob
.
class
)
{
return
new
JdbcClob
(
session
,
conn
,
v
,
0
);
}
else
{
throw
Message
.
getUnsupportedException
();
}
}
}
h2/src/main/org/h2/util/UpdatableRow.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.Connection
;
import
java.sql.DatabaseMetaData
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
org.h2.engine.SessionInterface
;
import
org.h2.message.Message
;
import
org.h2.result.ResultInterface
;
import
org.h2.value.DataType
;
import
org.h2.value.Value
;
import
org.h2.value.ValueNull
;
public
class
UpdatableRow
{
private
SessionInterface
session
;
private
Connection
conn
;
private
DatabaseMetaData
meta
;
private
ResultInterface
result
;
private
int
columnCount
;
private
String
schemaName
;
private
String
tableName
;
private
ObjectArray
key
;
private
boolean
isUpdatable
;
public
UpdatableRow
(
Connection
conn
,
ResultInterface
result
,
SessionInterface
session
)
throws
SQLException
{
this
.
conn
=
conn
;
this
.
meta
=
conn
.
getMetaData
();
this
.
result
=
result
;
this
.
session
=
session
;
columnCount
=
result
.
getVisibleColumnCount
();
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
String
t
=
result
.
getTableName
(
i
);
String
s
=
result
.
getSchemaName
(
i
);
if
(
t
==
null
||
s
==
null
)
{
return
;
}
if
(
tableName
==
null
)
{
tableName
=
t
;
}
else
if
(!
tableName
.
equals
(
t
))
{
return
;
}
if
(
schemaName
==
null
)
{
schemaName
=
s
;
}
else
if
(!
schemaName
.
equals
(
s
))
{
return
;
}
}
ResultSet
rs
=
meta
.
getTables
(
null
,
schemaName
,
tableName
,
new
String
[]{
"TABLE"
});
if
(!
rs
.
next
())
{
return
;
}
if
(
rs
.
getString
(
"SQL"
)==
null
)
{
// system table
return
;
}
key
=
new
ObjectArray
();
rs
=
meta
.
getPrimaryKeys
(
null
,
schemaName
,
tableName
);
while
(
rs
.
next
())
{
key
.
add
(
rs
.
getString
(
"COLUMN_NAME"
));
}
if
(
key
.
size
()
==
0
)
{
return
;
}
isUpdatable
=
true
;
}
public
boolean
isUpdatable
()
{
return
isUpdatable
;
}
void
initKey
()
throws
SQLException
{
}
private
int
getColumnIndex
(
String
columnName
)
throws
SQLException
{
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
String
col
=
result
.
getColumnName
(
i
);
if
(
col
.
equals
(
columnName
))
{
return
i
;
}
}
throw
Message
.
getSQLException
(
Message
.
COLUMN_NOT_FOUND_1
,
columnName
);
}
private
void
appendColumnList
(
StringBuffer
buff
,
boolean
set
)
{
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
", "
);
}
String
col
=
result
.
getColumnName
(
i
);
buff
.
append
(
StringUtils
.
quoteIdentifier
(
col
));
if
(
set
)
{
buff
.
append
(
"=? "
);
}
}
}
private
void
appendKeyCondition
(
StringBuffer
buff
)
{
buff
.
append
(
" WHERE "
);
for
(
int
i
=
0
;
i
<
key
.
size
();
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
" AND "
);
}
buff
.
append
(
StringUtils
.
quoteIdentifier
((
String
)
key
.
get
(
i
)));
buff
.
append
(
"=?"
);
}
}
private
void
setKey
(
PreparedStatement
prep
,
int
start
,
Value
[]
current
)
throws
SQLException
{
for
(
int
i
=
0
;
i
<
key
.
size
();
i
++)
{
String
col
=
(
String
)
key
.
get
(
i
);
int
idx
=
getColumnIndex
(
col
);
Value
v
=
current
[
idx
];
v
.
set
(
prep
,
start
+
i
);
}
}
// public boolean isRowDeleted(Value[] row) throws SQLException {
// StringBuffer buff = new StringBuffer();
// buff.append("SELECT COUNT(*) FROM ");
// buff.append(StringUtils.quoteIdentifier(tableName));
// appendKeyCondition(buff);
// PreparedStatement prep = conn.prepareStatement(buff.toString());
// setKey(prep, 1, row);
// ResultSet rs = prep.executeQuery();
// rs.next();
// return rs.getInt(1) == 0;
// }
public
void
refreshRow
(
Value
[]
row
)
throws
SQLException
{
Value
[]
newRow
=
readRow
(
row
);
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
row
[
i
]
=
newRow
[
i
];
}
}
private
void
appendTableName
(
StringBuffer
buff
)
{
if
(
schemaName
!=
null
&&
schemaName
.
length
()>
0
)
{
buff
.
append
(
StringUtils
.
quoteIdentifier
(
schemaName
));
buff
.
append
(
'.'
);
}
buff
.
append
(
StringUtils
.
quoteIdentifier
(
tableName
));
}
private
Value
[]
readRow
(
Value
[]
row
)
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
"SELECT "
);
appendColumnList
(
buff
,
false
);
buff
.
append
(
" FROM "
);
appendTableName
(
buff
);
appendKeyCondition
(
buff
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
buff
.
toString
());
setKey
(
prep
,
1
,
row
);
ResultSet
rs
=
prep
.
executeQuery
();
if
(!
rs
.
next
())
{
throw
Message
.
getSQLException
(
Message
.
NO_DATA_AVAILABLE
);
}
Value
[]
newRow
=
new
Value
[
columnCount
];
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
int
type
=
result
.
getColumnType
(
i
);
// TODO lob: support updatable rows
newRow
[
i
]
=
DataType
.
readValue
(
session
,
rs
,
i
+
1
,
type
);
}
return
newRow
;
}
public
void
deleteRow
(
Value
[]
current
)
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
"DELETE FROM "
);
appendTableName
(
buff
);
appendKeyCondition
(
buff
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
buff
.
toString
());
setKey
(
prep
,
1
,
current
);
int
count
=
prep
.
executeUpdate
();
if
(
count
!=
1
)
{
throw
Message
.
getSQLException
(
Message
.
NO_DATA_AVAILABLE
);
}
}
public
void
updateRow
(
Value
[]
current
,
Value
[]
updateRow
)
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
"UPDATE "
);
appendTableName
(
buff
);
buff
.
append
(
" SET "
);
appendColumnList
(
buff
,
true
);
// TODO updatable result set: we could add all current values to the where clause
// - like this optimistic ('no') locking is possible
appendKeyCondition
(
buff
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
buff
.
toString
());
int
j
=
1
;
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
Value
v
=
updateRow
[
i
];
if
(
v
==
null
)
{
v
=
current
[
i
];
}
v
.
set
(
prep
,
j
++);
}
setKey
(
prep
,
j
,
current
);
prep
.
execute
();
}
public
void
insertRow
(
Value
[]
row
)
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
"INSERT INTO "
);
appendTableName
(
buff
);
buff
.
append
(
"("
);
appendColumnList
(
buff
,
false
);
buff
.
append
(
")VALUES("
);
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
","
);
}
buff
.
append
(
"?"
);
}
buff
.
append
(
")"
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
buff
.
toString
());
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
Value
v
=
row
[
i
];
if
(
v
==
null
)
{
v
=
ValueNull
.
INSTANCE
;
}
v
.
set
(
prep
,
i
+
1
);
}
prep
.
executeUpdate
();
}
}
h2/src/main/org/h2/util/ValueHashMap.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
import
org.h2.store.DataHandler
;
import
org.h2.value.Value
;
import
org.h2.value.ValueNull
;
public
class
ValueHashMap
extends
HashBase
{
private
Value
[]
keys
;
private
Object
[]
values
;
private
DataHandler
database
;
public
ValueHashMap
(
DataHandler
database
)
{
this
.
database
=
database
;
}
protected
void
reset
(
int
newLevel
)
{
super
.
reset
(
newLevel
);
keys
=
new
Value
[
len
];
values
=
new
Object
[
len
];
}
protected
void
rehash
(
int
newLevel
)
throws
SQLException
{
Value
[]
oldKeys
=
keys
;
Object
[]
oldValues
=
values
;
reset
(
newLevel
);
for
(
int
i
=
0
;
i
<
oldKeys
.
length
;
i
++)
{
Value
k
=
oldKeys
[
i
];
if
(
k
!=
null
&&
k
!=
ValueNull
.
DELETED
)
{
put
(
k
,
oldValues
[
i
]);
}
}
}
private
int
getIndex
(
Value
key
)
{
return
key
.
hashCode
()
&
mask
;
}
public
void
put
(
Value
key
,
Object
value
)
throws
SQLException
{
checkSizePut
();
int
index
=
getIndex
(
key
);
int
plus
=
1
;
int
deleted
=
-
1
;
do
{
Value
k
=
keys
[
index
];
if
(
k
==
null
)
{
// found an empty record
if
(
deleted
>=
0
)
{
index
=
deleted
;
deletedCount
--;
}
size
++;
keys
[
index
]
=
key
;
values
[
index
]
=
value
;
return
;
}
else
if
(
k
==
ValueNull
.
DELETED
)
{
// found a deleted record
if
(
deleted
<
0
)
{
deleted
=
index
;
}
}
else
if
(
database
.
compareTypeSave
(
k
,
key
)==
0
)
{
// update existing
values
[
index
]
=
value
;
return
;
}
index
=
(
index
+
plus
++)
&
mask
;
}
while
(
plus
<=
len
);
// no space
throw
Message
.
getInternalError
(
"hashmap is full"
);
}
public
void
remove
(
Value
key
)
throws
SQLException
{
checkSizeRemove
();
int
index
=
getIndex
(
key
);
int
plus
=
1
;
do
{
Value
k
=
keys
[
index
];
if
(
k
==
null
)
{
// found an empty record
return
;
}
else
if
(
k
==
ValueNull
.
DELETED
)
{
// found a deleted record
}
else
if
(
database
.
compareTypeSave
(
k
,
key
)==
0
)
{
// found the record
keys
[
index
]
=
ValueNull
.
DELETED
;
values
[
index
]
=
null
;
deletedCount
++;
size
--;
return
;
}
index
=
(
index
+
plus
++)
&
mask
;
k
=
keys
[
index
];
}
while
(
plus
<=
len
);
// not found
}
public
Object
get
(
Value
key
)
throws
SQLException
{
int
index
=
getIndex
(
key
);
int
plus
=
1
;
do
{
Value
k
=
keys
[
index
];
if
(
k
==
null
)
{
// found an empty record
return
null
;
}
else
if
(
k
==
ValueNull
.
DELETED
)
{
// found a deleted record
}
else
if
(
database
.
compareTypeSave
(
k
,
key
)==
0
)
{
// found it
return
values
[
index
];
}
index
=
(
index
+
plus
++)
&
mask
;
}
while
(
plus
<=
len
);
return
null
;
}
public
ObjectArray
keys
()
{
ObjectArray
list
=
new
ObjectArray
(
size
);
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
Value
k
=
keys
[
i
];
if
(
k
!=
null
&&
k
!=
ValueNull
.
DELETED
)
{
list
.
add
(
k
);
}
}
return
list
;
}
public
ObjectArray
values
()
{
ObjectArray
list
=
new
ObjectArray
(
size
);
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
Value
k
=
keys
[
i
];
if
(
k
!=
null
&&
k
!=
ValueNull
.
DELETED
)
{
list
.
add
(
values
[
i
]);
}
}
return
list
;
}
}
h2/src/main/org/h2/value/CompareMode.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.text.Collator
;
import
java.util.Locale
;
import
org.h2.util.StringUtils
;
public
class
CompareMode
{
public
static
final
String
OFF
=
"OFF"
;
private
String
name
=
OFF
;
private
Collator
collator
;
public
CompareMode
(
Collator
collator
,
String
name
)
{
this
.
collator
=
collator
;
if
(
name
!=
null
)
{
this
.
name
=
name
;
}
}
public
int
compareString
(
String
a
,
String
b
,
boolean
ignoreCase
)
{
if
(
collator
==
null
)
{
if
(
ignoreCase
)
{
return
a
.
compareToIgnoreCase
(
b
);
}
return
a
.
compareTo
(
b
);
}
if
(
ignoreCase
)
{
// this is locale sensitive
a
=
a
.
toUpperCase
();
b
=
b
.
toUpperCase
();
}
int
comp
=
collator
.
compare
(
a
,
b
);
return
comp
;
}
public
static
String
getName
(
Locale
l
)
{
Locale
english
=
Locale
.
ENGLISH
;
String
name
=
l
.
getDisplayLanguage
(
english
)
+
' '
+
l
.
getDisplayCountry
(
english
)
+
' '
+
l
.
getVariant
();
name
=
StringUtils
.
toUpperEnglish
(
name
.
trim
().
replace
(
' '
,
'_'
));
return
name
;
}
public
static
Collator
getCollator
(
String
name
)
{
Locale
[]
locales
=
Collator
.
getAvailableLocales
();
for
(
int
i
=
0
;
i
<
locales
.
length
;
i
++)
{
Locale
locale
=
locales
[
i
];
if
(
name
.
equalsIgnoreCase
(
locale
.
toString
())
||
name
.
equalsIgnoreCase
(
getName
(
locale
)))
{
return
Collator
.
getInstance
(
locale
);
}
}
return
null
;
}
public
String
getName
()
{
return
name
;
}
}
h2/src/main/org/h2/value/DataType.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.math.BigDecimal
;
import
java.sql.Date
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
java.sql.Types
;
import
java.util.Calendar
;
import
java.util.HashMap
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SessionInterface
;
import
org.h2.message.Message
;
import
org.h2.util.ObjectArray
;
import
org.h2.util.StringUtils
;
import
org.h2.util.TypeConverter
;
public
class
DataType
{
private
static
ObjectArray
types
=
new
ObjectArray
();
private
static
HashMap
typesByName
=
new
HashMap
();
private
static
DataType
[]
typesByValueType
=
new
DataType
[
Value
.
TYPE_COUNT
];
public
int
type
;
public
String
name
;
public
int
sqlType
;
public
String
jdbc
;
// how closely the data type maps to the corresponding JDBC SQL type (low is best)
public
int
order
;
public
int
maxPrecision
;
public
int
minScale
,
maxScale
;
public
boolean
decimal
;
public
String
prefix
,
suffix
;
public
String
params
;
public
boolean
autoInc
;
public
boolean
caseSensitive
;
public
boolean
supportsPrecision
,
supportsScale
;
public
long
defaultPrecision
;
public
int
defaultScale
;
public
boolean
hidden
;
static
{
add
(
Value
.
NULL
,
Types
.
NULL
,
"Null"
,
new
DataType
(),
new
String
[]{
"NULL"
}
);
add
(
Value
.
BOOLEAN
,
Types
.
BOOLEAN
,
"Boolean"
,
createDecimal
(
ValueBoolean
.
PRECISION
,
ValueBoolean
.
PRECISION
,
0
,
false
,
false
),
new
String
[]{
"BOOLEAN"
,
"BIT"
,
"BOOL"
}
);
add
(
Value
.
BYTE
,
Types
.
TINYINT
,
"Byte"
,
createDecimal
(
ValueByte
.
PRECISION
,
ValueByte
.
PRECISION
,
0
,
false
,
false
),
new
String
[]{
"TINYINT"
}
);
add
(
Value
.
SHORT
,
Types
.
SMALLINT
,
"Short"
,
createDecimal
(
ValueShort
.
PRECISION
,
ValueShort
.
PRECISION
,
0
,
false
,
false
),
new
String
[]{
"SMALLINT"
,
"YEAR"
,
"INT2"
}
);
add
(
Value
.
INT
,
Types
.
INTEGER
,
"Int"
,
createDecimal
(
ValueInt
.
PRECISION
,
ValueInt
.
PRECISION
,
0
,
false
,
false
),
new
String
[]{
"INTEGER"
,
"INT"
,
"MEDIUMINT"
,
"INT4"
,
"SIGNED"
}
);
add
(
Value
.
LONG
,
Types
.
BIGINT
,
"Long"
,
createDecimal
(
ValueLong
.
PRECISION
,
ValueLong
.
PRECISION
,
0
,
false
,
false
),
new
String
[]{
"BIGINT"
,
"INT8"
}
);
add
(
Value
.
LONG
,
Types
.
BIGINT
,
"Long"
,
createDecimal
(
ValueLong
.
PRECISION
,
ValueLong
.
PRECISION
,
0
,
false
,
true
),
new
String
[]{
"IDENTITY"
}
);
add
(
Value
.
DECIMAL
,
Types
.
DECIMAL
,
"BigDecimal"
,
createDecimal
(
Integer
.
MAX_VALUE
,
ValueDecimal
.
DEFAULT_PRECISION
,
ValueDecimal
.
DEFAULT_SCALE
,
true
,
false
),
new
String
[]{
"DECIMAL"
,
"DEC"
}
// TODO value: are NaN, Inf, -Inf,... supported as well?
);
add
(
Value
.
DECIMAL
,
Types
.
NUMERIC
,
"BigDecimal"
,
createDecimal
(
Integer
.
MAX_VALUE
,
ValueDecimal
.
DEFAULT_PRECISION
,
ValueDecimal
.
DEFAULT_SCALE
,
true
,
false
),
new
String
[]{
"NUMERIC"
,
"NUMBER"
}
// TODO value: are NaN, Inf, -Inf,... supported as well?
);
add
(
Value
.
DOUBLE
,
Types
.
DOUBLE
,
"Double"
,
createDecimal
(
ValueDouble
.
PRECISION
,
ValueDouble
.
PRECISION
,
0
,
false
,
false
),
new
String
[]
{
"DOUBLE"
,
"DOUBLE PRECISION"
}
);
add
(
Value
.
DOUBLE
,
Types
.
FLOAT
,
"Double"
,
createDecimal
(
ValueDouble
.
PRECISION
,
ValueDouble
.
PRECISION
,
0
,
false
,
false
),
new
String
[]
{
"FLOAT"
,
"FLOAT8"
}
// TODO value: show min and max values, E format if supported
);
add
(
Value
.
FLOAT
,
Types
.
REAL
,
"Float"
,
createDecimal
(
ValueFloat
.
PRECISION
,
ValueFloat
.
PRECISION
,
0
,
false
,
false
),
new
String
[]
{
"REAL"
,
"FLOAT4"
}
);
add
(
Value
.
TIME
,
Types
.
TIME
,
"Time"
,
createDate
(
ValueTime
.
PRECISION
,
"TIME"
,
0
),
new
String
[]{
"TIME"
}
// TODO value: min / max for time
);
add
(
Value
.
DATE
,
Types
.
DATE
,
"Date"
,
createDate
(
ValueDate
.
PRECISION
,
"DATE"
,
0
),
new
String
[]{
"DATE"
}
// TODO value: min / max for date
);
add
(
Value
.
TIMESTAMP
,
Types
.
TIMESTAMP
,
"Timestamp"
,
createDate
(
ValueTimestamp
.
PRECISION
,
"TIMESTAMP"
,
ValueTimestamp
.
DEFAULT_SCALE
),
new
String
[]{
"TIMESTAMP"
,
"DATETIME"
,
"SMALLDATETIME"
}
// TODO value: min / max for timestamp
);
add
(
Value
.
BYTES
,
Types
.
VARBINARY
,
"Bytes"
,
createString
(
false
),
new
String
[]{
"VARBINARY"
}
);
add
(
Value
.
BYTES
,
Types
.
BINARY
,
"Bytes"
,
createString
(
false
),
new
String
[]{
"BINARY"
,
"RAW"
,
"BYTEA"
,
"LONG RAW"
}
);
add
(
Value
.
UUID
,
Types
.
BINARY
,
"Bytes"
,
createString
(
false
),
new
String
[]{
"UUID"
}
);
add
(
Value
.
BYTES
,
Types
.
LONGVARBINARY
,
"Bytes"
,
createString
(
false
),
new
String
[]{
"LONGVARBINARY"
}
);
add
(
Value
.
JAVA_OBJECT
,
Types
.
OTHER
,
"Object"
,
createString
(
false
),
new
String
[]{
"OTHER"
,
"OBJECT"
,
"JAVA_OBJECT"
}
);
add
(
Value
.
STRING
,
Types
.
VARCHAR
,
"String"
,
createString
(
true
),
new
String
[]{
"VARCHAR"
,
"VARCHAR2"
,
"NVARCHAR"
,
"NVARCHAR2"
,
"VARCHAR_CASESENSITIVE"
}
);
add
(
Value
.
STRING
,
Types
.
LONGVARCHAR
,
"String"
,
createString
(
true
),
new
String
[]{
"LONGVARCHAR"
}
);
add
(
Value
.
STRING
,
Types
.
CHAR
,
"String"
,
createString
(
true
),
new
String
[]{
"CHAR"
,
"CHARACTER"
,
"NCHAR"
}
);
add
(
Value
.
STRING_IGNORECASE
,
Types
.
VARCHAR
,
"String"
,
createString
(
false
),
new
String
[]{
"VARCHAR_IGNORECASE"
}
);
add
(
Value
.
BLOB
,
Types
.
BLOB
,
"Bytes"
,
createString
(
false
),
new
String
[]{
"BLOB"
,
"TINYBLOB"
,
"MEDIUMBLOB"
,
"LONGBLOB"
,
"IMAGE"
,
"OID"
}
);
add
(
Value
.
CLOB
,
Types
.
CLOB
,
"String"
,
createString
(
true
),
new
String
[]{
"CLOB"
,
"TINYTEXT"
,
"TEXT"
,
"MEDIUMTEXT"
,
"LONGTEXT"
,
"NTEXT"
,
"NCLOB"
}
);
// TODO data types: try to support other types as well (longvarchar for odbc/access,...) - maybe map them to regular types?
}
private
static
void
add
(
int
type
,
int
sqlType
,
String
jdbc
,
DataType
dataType
,
String
[]
names
)
{
for
(
int
i
=
0
;
i
<
names
.
length
;
i
++)
{
DataType
dt
=
new
DataType
();
dt
.
type
=
type
;
dt
.
sqlType
=
sqlType
;
dt
.
jdbc
=
jdbc
;
dt
.
name
=
names
[
i
];
dt
.
autoInc
=
dataType
.
autoInc
;
dt
.
decimal
=
dataType
.
decimal
;
dt
.
maxPrecision
=
dataType
.
maxPrecision
;
dt
.
maxScale
=
dataType
.
maxScale
;
dt
.
minScale
=
dataType
.
minScale
;
dt
.
params
=
dataType
.
params
;
dt
.
prefix
=
dataType
.
prefix
;
dt
.
suffix
=
dataType
.
suffix
;
dt
.
supportsPrecision
=
dataType
.
supportsPrecision
;
dt
.
supportsScale
=
dataType
.
supportsScale
;
dt
.
defaultPrecision
=
dataType
.
defaultPrecision
;
dt
.
defaultScale
=
dataType
.
defaultScale
;
dt
.
caseSensitive
=
dataType
.
caseSensitive
;
dt
.
hidden
=
i
>
0
;
for
(
int
j
=
0
;
j
<
types
.
size
();
j
++)
{
DataType
t2
=
(
DataType
)
types
.
get
(
j
);
if
(
t2
.
sqlType
==
dt
.
sqlType
)
{
dt
.
order
++;
}
}
typesByName
.
put
(
dt
.
name
,
dt
);
if
(
typesByValueType
[
type
]
==
null
)
{
typesByValueType
[
type
]
=
dt
;
}
types
.
add
(
dt
);
}
}
public
static
String
getJdbcString
(
int
type
)
{
return
typesByValueType
[
type
].
jdbc
;
}
private
static
DataType
createDecimal
(
int
maxPrecision
,
int
defaultPrecision
,
int
defaultScale
,
boolean
needsPrecisionAndScale
,
boolean
autoInc
)
{
DataType
dataType
=
new
DataType
();
dataType
.
maxPrecision
=
maxPrecision
;
dataType
.
defaultPrecision
=
defaultPrecision
;
dataType
.
defaultScale
=
defaultScale
;
if
(
needsPrecisionAndScale
)
{
dataType
.
params
=
"PRECISION,SCALE"
;
dataType
.
supportsPrecision
=
true
;
dataType
.
supportsScale
=
true
;
}
dataType
.
decimal
=
true
;
dataType
.
autoInc
=
autoInc
;
return
dataType
;
}
private
static
DataType
createDate
(
int
precision
,
String
prefix
,
int
scale
)
{
DataType
dataType
=
new
DataType
();
dataType
.
prefix
=
prefix
+
" '"
;
dataType
.
suffix
=
"'"
;
dataType
.
maxPrecision
=
precision
;
dataType
.
supportsScale
=
scale
!=
0
;
dataType
.
maxScale
=
scale
;
dataType
.
defaultPrecision
=
precision
;
dataType
.
defaultScale
=
scale
;
return
dataType
;
}
private
static
DataType
createString
(
boolean
caseSensitive
)
{
DataType
dataType
=
new
DataType
();
dataType
.
prefix
=
"'"
;
dataType
.
suffix
=
"'"
;
dataType
.
params
=
"LENGTH"
;
dataType
.
caseSensitive
=
caseSensitive
;
dataType
.
supportsPrecision
=
true
;
dataType
.
maxPrecision
=
Integer
.
MAX_VALUE
;
dataType
.
defaultPrecision
=
Integer
.
MAX_VALUE
;
return
dataType
;
}
public
static
ObjectArray
getTypes
()
{
return
types
;
}
public
static
Value
readValue
(
SessionInterface
session
,
ResultSet
rs
,
int
columnIndex
,
int
type
)
throws
SQLException
{
Value
v
;
switch
(
type
)
{
case
Value
.
NULL
:
{
return
ValueNull
.
INSTANCE
;
}
case
Value
.
BYTES
:
{
byte
[]
buff
=
rs
.
getBytes
(
columnIndex
);
v
=
buff
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueBytes
.
get
(
buff
);
break
;
}
case
Value
.
UUID
:
{
byte
[]
buff
=
rs
.
getBytes
(
columnIndex
);
v
=
buff
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueUuid
.
get
(
buff
);
break
;
}
case
Value
.
BOOLEAN
:
{
boolean
value
=
rs
.
getBoolean
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueBoolean
.
get
(
value
);
break
;
}
case
Value
.
BYTE
:
{
byte
value
=
rs
.
getByte
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueByte
.
get
(
value
);
break
;
}
case
Value
.
DATE
:
{
Date
value
=
rs
.
getDate
(
columnIndex
);
v
=
value
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueDate
.
get
(
value
);
break
;
}
case
Value
.
TIME
:
{
Time
value
=
rs
.
getTime
(
columnIndex
);
v
=
value
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueTime
.
get
(
value
);
break
;
}
case
Value
.
TIMESTAMP
:
{
Timestamp
value
=
rs
.
getTimestamp
(
columnIndex
);
v
=
value
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueTimestamp
.
get
(
value
);
break
;
}
case
Value
.
DECIMAL
:
{
BigDecimal
value
=
rs
.
getBigDecimal
(
columnIndex
);
v
=
value
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueDecimal
.
get
(
value
);
break
;
}
case
Value
.
DOUBLE
:
{
double
value
=
rs
.
getDouble
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueDouble
.
get
(
value
);
break
;
}
case
Value
.
FLOAT
:
{
float
value
=
rs
.
getFloat
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueFloat
.
get
(
value
);
break
;
}
case
Value
.
INT
:
{
int
value
=
rs
.
getInt
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueInt
.
get
(
value
);
break
;
}
case
Value
.
LONG
:
{
long
value
=
rs
.
getLong
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueLong
.
get
(
value
);
break
;
}
case
Value
.
SHORT
:
{
short
value
=
rs
.
getShort
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueShort
.
get
(
value
);
break
;
}
case
Value
.
STRING_IGNORECASE
:
case
Value
.
STRING
:
{
String
s
=
rs
.
getString
(
columnIndex
);
v
=
(
s
==
null
)
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueString
.
get
(
s
);
break
;
}
case
Value
.
CLOB
:
{
if
(
session
==
null
)
{
v
=
ValueLob
.
createSmallLob
(
Value
.
CLOB
,
StringUtils
.
utf8Encode
(
rs
.
getString
(
columnIndex
)));
}
else
{
Reader
in
=
rs
.
getCharacterStream
(
columnIndex
);
v
=
(
in
==
null
)
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueLob
.
createClob
(
in
,
-
1
,
session
.
getDataHandler
());
}
break
;
}
case
Value
.
BLOB
:
{
if
(
session
==
null
)
{
v
=
ValueLob
.
createSmallLob
(
Value
.
BLOB
,
rs
.
getBytes
(
columnIndex
));
}
else
{
InputStream
in
=
rs
.
getBinaryStream
(
columnIndex
);
v
=
(
in
==
null
)
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueLob
.
createBlob
(
in
,
-
1
,
session
.
getDataHandler
());
}
break
;
}
case
Value
.
JAVA_OBJECT
:
{
byte
[]
buff
=
rs
.
getBytes
(
columnIndex
);
v
=
buff
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueJavaObject
.
get
(
buff
);
break
;
}
default
:
throw
Message
.
getInternalError
(
"type="
+
type
);
}
return
v
;
}
public
static
String
getTypeClassName
(
int
type
)
{
switch
(
type
)
{
case
Value
.
BOOLEAN
:
return
Boolean
.
class
.
getName
();
// "java.lang.Boolean";
case
Value
.
BYTE
:
return
Byte
.
class
.
getName
();
// "java.lang.Byte";
case
Value
.
SHORT
:
return
Short
.
class
.
getName
();
// "java.lang.Short";
case
Value
.
INT
:
return
Integer
.
class
.
getName
();
// "java.lang.Integer";
case
Value
.
LONG
:
return
Long
.
class
.
getName
();
// "java.lang.Long";
case
Value
.
DECIMAL
:
return
BigDecimal
.
class
.
getName
();
// "java.math.BigDecimal";
case
Value
.
TIME
:
return
Time
.
class
.
getName
();
// "java.sql.Time";
case
Value
.
DATE
:
return
Date
.
class
.
getName
();
// "java.sql.Date";
case
Value
.
TIMESTAMP
:
return
Timestamp
.
class
.
getName
();
// "java.sql.Timestamp";
case
Value
.
BYTES
:
case
Value
.
UUID
:
return
byte
[].
class
.
getName
();
// "[B", not "byte[]";
case
Value
.
STRING
:
case
Value
.
STRING_IGNORECASE
:
return
String
.
class
.
getName
();
// "java.lang.String";
case
Value
.
BLOB
:
return
java
.
sql
.
Blob
.
class
.
getName
();
// "java.sql.Blob";
case
Value
.
CLOB
:
return
java
.
sql
.
Clob
.
class
.
getName
();
// "java.sql.Clob";
case
Value
.
DOUBLE
:
return
Double
.
class
.
getName
();
// "java.lang.Double";
case
Value
.
FLOAT
:
return
Float
.
class
.
getName
();
// "java.lang.Float";
case
Value
.
NULL
:
return
null
;
case
Value
.
JAVA_OBJECT
:
return
Object
.
class
.
getName
();
// "java.lang.Object";
default
:
throw
Message
.
getInternalError
(
"type="
+
type
);
}
}
public
static
DataType
getDataType
(
int
type
)
{
DataType
dt
=
typesByValueType
[
type
];
if
(
dt
==
null
)
{
dt
=
typesByValueType
[
Value
.
NULL
];
}
return
dt
;
}
public
static
int
convertTypeToSQLType
(
int
type
)
{
return
getDataType
(
type
).
sqlType
;
}
public
static
int
convertSQLTypeToValueType
(
int
sqlType
)
throws
SQLException
{
switch
(
sqlType
)
{
case
Types
.
VARCHAR
:
case
Types
.
CHAR
:
case
Types
.
LONGVARCHAR
:
return
Value
.
STRING
;
case
Types
.
NUMERIC
:
case
Types
.
DECIMAL
:
return
Value
.
DECIMAL
;
case
Types
.
BIT
:
case
Types
.
BOOLEAN
:
return
Value
.
BOOLEAN
;
case
Types
.
INTEGER
:
return
Value
.
INT
;
case
Types
.
SMALLINT
:
return
Value
.
SHORT
;
case
Types
.
TINYINT
:
return
Value
.
BYTE
;
case
Types
.
BIGINT
:
return
Value
.
LONG
;
case
Types
.
REAL
:
return
Value
.
FLOAT
;
case
Types
.
DOUBLE
:
case
Types
.
FLOAT
:
return
Value
.
DOUBLE
;
case
Types
.
BINARY
:
case
Types
.
VARBINARY
:
case
Types
.
LONGVARBINARY
:
return
Value
.
BYTES
;
case
Types
.
OTHER
:
case
Types
.
JAVA_OBJECT
:
return
Value
.
JAVA_OBJECT
;
case
Types
.
DATE
:
return
Value
.
DATE
;
case
Types
.
TIME
:
return
Value
.
TIME
;
case
Types
.
TIMESTAMP
:
return
Value
.
TIMESTAMP
;
case
Types
.
BLOB
:
return
Value
.
BLOB
;
case
Types
.
CLOB
:
return
Value
.
CLOB
;
case
Types
.
NULL
:
return
Value
.
NULL
;
default
:
throw
Message
.
getSQLException
(
Message
.
UNKNOWN_DATA_TYPE_1
,
""
+
sqlType
);
}
}
public
static
int
getTypeFromClass
(
Class
x
)
throws
SQLException
{
// TODO refactor: too many if/else in functions, can reduce!
if
(
x
==
null
)
{
return
Value
.
NULL
;
}
if
(
ResultSet
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
RESULT_SET
;
}
else
if
(
String
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
STRING
;
}
else
if
(
BigDecimal
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
DECIMAL
;
}
else
if
(
Boolean
.
class
.
isAssignableFrom
(
x
)
||
boolean
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
BOOLEAN
;
}
else
if
(
Byte
.
class
.
isAssignableFrom
(
x
)
||
byte
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
BYTE
;
}
else
if
(
Short
.
class
.
isAssignableFrom
(
x
)
||
short
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
SHORT
;
}
else
if
(
Integer
.
class
.
isAssignableFrom
(
x
)
||
int
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
INT
;
}
else
if
(
Character
.
class
.
isAssignableFrom
(
x
)
||
char
.
class
.
isAssignableFrom
(
x
))
{
throw
Message
.
getSQLException
(
Message
.
DATA_CONVERSION_ERROR_1
,
"char (not supported)"
);
}
else
if
(
Long
.
class
.
isAssignableFrom
(
x
)
||
long
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
LONG
;
}
else
if
(
Float
.
class
.
isAssignableFrom
(
x
)
||
float
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
FLOAT
;
}
else
if
(
Double
.
class
.
isAssignableFrom
(
x
)
||
double
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
DOUBLE
;
}
else
if
(
byte
[].
class
.
isAssignableFrom
(
x
))
{
return
Value
.
BYTES
;
}
else
if
(
Date
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
DATE
;
}
else
if
(
Time
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
TIME
;
}
else
if
(
Timestamp
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
TIMESTAMP
;
}
else
if
(
java
.
util
.
Date
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
DATE
;
}
else
if
(
java
.
io
.
Reader
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
CLOB
;
}
else
if
(
java
.
sql
.
Clob
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
CLOB
;
}
else
if
(
java
.
io
.
InputStream
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
BLOB
;
}
else
if
(
java
.
sql
.
Blob
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
BLOB
;
}
else
if
(
Object
[].
class
.
isAssignableFrom
(
x
))
{
return
Value
.
ARRAY
;
}
else
if
(
Void
.
TYPE
==
x
)
{
return
Value
.
NULL
;
}
else
{
return
Value
.
JAVA_OBJECT
;
}
}
public
static
Value
convertToValue
(
SessionInterface
session
,
Object
x
,
int
type
)
throws
SQLException
{
if
(
x
==
null
)
{
return
ValueNull
.
INSTANCE
;
}
if
(
type
==
Value
.
JAVA_OBJECT
)
{
// serialize JAVA_OBJECTs, even if the type is known
if
(
Constants
.
SERIALIZE_JAVA_OBJECTS
)
{
return
ValueJavaObject
.
get
(
TypeConverter
.
serialize
(
x
));
}
}
if
(
x
instanceof
String
)
{
return
ValueString
.
get
((
String
)
x
);
}
else
if
(
x
instanceof
BigDecimal
)
{
return
ValueDecimal
.
get
((
BigDecimal
)
x
);
}
else
if
(
x
instanceof
Boolean
)
{
return
ValueBoolean
.
get
(((
Boolean
)
x
).
booleanValue
());
}
else
if
(
x
instanceof
Byte
)
{
return
ValueByte
.
get
(((
Byte
)
x
).
byteValue
());
}
else
if
(
x
instanceof
Short
)
{
return
ValueShort
.
get
(((
Short
)
x
).
shortValue
());
}
else
if
(
x
instanceof
Integer
)
{
return
ValueInt
.
get
(((
Integer
)
x
).
intValue
());
}
else
if
(
x
instanceof
Long
)
{
return
ValueLong
.
get
(((
Long
)
x
).
longValue
());
}
else
if
(
x
instanceof
Float
)
{
return
ValueFloat
.
get
(((
Float
)
x
).
floatValue
());
}
else
if
(
x
instanceof
Double
)
{
return
ValueDouble
.
get
(((
Double
)
x
).
doubleValue
());
}
else
if
(
x
instanceof
byte
[])
{
return
ValueBytes
.
get
((
byte
[])
x
);
}
else
if
(
x
instanceof
Date
)
{
return
ValueDate
.
get
((
Date
)
x
);
}
else
if
(
x
instanceof
Time
)
{
return
ValueTime
.
get
((
Time
)
x
);
}
else
if
(
x
instanceof
Timestamp
)
{
return
ValueTimestamp
.
get
((
Timestamp
)
x
);
}
else
if
(
x
instanceof
java
.
util
.
Date
)
{
return
ValueDate
.
get
(
new
Date
(((
java
.
util
.
Date
)
x
).
getTime
()));
}
else
if
(
x
instanceof
java
.
io
.
Reader
)
{
return
ValueLob
.
createClob
((
java
.
io
.
Reader
)
x
,
-
1
,
session
.
getDataHandler
());
}
else
if
(
x
instanceof
java
.
sql
.
Clob
)
{
return
ValueLob
.
createClob
(((
java
.
sql
.
Clob
)
x
).
getCharacterStream
(),
-
1
,
session
.
getDataHandler
());
}
else
if
(
x
instanceof
java
.
io
.
InputStream
)
{
return
ValueLob
.
createBlob
((
java
.
io
.
InputStream
)
x
,
-
1
,
session
.
getDataHandler
());
}
else
if
(
x
instanceof
java
.
sql
.
Blob
)
{
return
ValueLob
.
createBlob
(((
java
.
sql
.
Blob
)
x
).
getBinaryStream
(),
-
1
,
session
.
getDataHandler
());
}
else
if
(
x
instanceof
ResultSet
)
{
return
ValueResultSet
.
get
((
ResultSet
)
x
);
}
else
if
(
x
instanceof
Object
[])
{
// (a.getClass().isArray());
// (a.getClass().getComponentType().isPrimitive());
Object
[]
o
=
(
Object
[])
x
;
int
len
=
o
.
length
;
Value
[]
v
=
new
Value
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
v
[
i
]
=
convertToValue
(
session
,
o
[
i
],
type
);
}
return
ValueArray
.
get
(
v
);
}
else
{
if
(
Constants
.
SERIALIZE_JAVA_OBJECTS
)
{
return
ValueJavaObject
.
get
(
TypeConverter
.
serialize
(
x
));
}
else
{
throw
Message
.
getSQLException
(
Message
.
UNKNOWN_DATA_TYPE_1
,
x
.
getClass
().
getName
());
}
}
}
public
static
DataType
getTypeByName
(
String
s
)
{
return
(
DataType
)
typesByName
.
get
(
s
);
}
public
static
boolean
isLargeObject
(
int
type
)
{
if
(
type
==
Value
.
BLOB
||
type
==
Value
.
CLOB
)
{
return
true
;
}
return
false
;
}
public
static
boolean
supportsAdd
(
int
type
)
{
switch
(
type
)
{
case
Value
.
BYTE
:
case
Value
.
DECIMAL
:
case
Value
.
DOUBLE
:
case
Value
.
FLOAT
:
case
Value
.
INT
:
case
Value
.
LONG
:
case
Value
.
SHORT
:
return
true
;
}
return
false
;
}
public
static
java
.
util
.
Date
parseDateTime
(
String
s
,
int
type
,
int
errorCode
)
throws
SQLException
{
if
(
s
==
null
)
{
return
null
;
}
try
{
int
timeStart
;
if
(
type
==
Value
.
TIME
)
{
timeStart
=
0
;
}
else
{
timeStart
=
s
.
indexOf
(
' '
)
+
1
;
if
(
timeStart
<=
0
)
{
// PostgreSQL compatibility
timeStart
=
s
.
indexOf
(
'T'
)
+
1
;
}
}
int
year
=
1970
,
month
=
1
,
day
=
1
;
if
(
type
!=
Value
.
TIME
)
{
int
s1
=
s
.
indexOf
(
'-'
);
int
s2
=
s
.
indexOf
(
'-'
,
s1
+
1
);
if
(
s1
<=
0
||
s2
<=
s1
)
{
throw
Message
.
getSQLException
(
errorCode
,
s
);
}
year
=
Integer
.
parseInt
(
s
.
substring
(
0
,
s1
));
month
=
Integer
.
parseInt
(
s
.
substring
(
s1
+
1
,
s2
));
int
end
=
timeStart
==
0
?
s
.
length
()
:
timeStart
-
1
;
day
=
Integer
.
parseInt
(
s
.
substring
(
s2
+
1
,
end
));
}
int
hour
=
0
,
minute
=
0
,
second
=
0
,
nano
=
0
;
if
(
type
!=
Value
.
DATE
)
{
int
s1
=
s
.
indexOf
(
':'
,
timeStart
);
int
s2
=
s
.
indexOf
(
':'
,
s1
+
1
);
int
s3
=
s
.
indexOf
(
'.'
,
s2
+
1
);
if
(
s1
<=
0
||
s2
<=
s1
)
{
throw
Message
.
getSQLException
(
errorCode
,
s
);
}
hour
=
Integer
.
parseInt
(
s
.
substring
(
timeStart
,
s1
));
minute
=
Integer
.
parseInt
(
s
.
substring
(
s1
+
1
,
s2
));
if
(
s3
<
0
)
{
second
=
Integer
.
parseInt
(
s
.
substring
(
s2
+
1
));
}
else
{
second
=
Integer
.
parseInt
(
s
.
substring
(
s2
+
1
,
s3
));
String
n
=
(
s
+
"000000000"
).
substring
(
s3
+
1
,
s3
+
10
);
nano
=
Integer
.
parseInt
(
n
);
}
}
Calendar
c
=
Calendar
.
getInstance
();
c
.
setLenient
(
false
);
long
time
;
c
.
set
(
Calendar
.
YEAR
,
year
);
c
.
set
(
Calendar
.
MONTH
,
month
-
1
);
// january is 0
c
.
set
(
Calendar
.
DAY_OF_MONTH
,
day
);
c
.
set
(
Calendar
.
HOUR_OF_DAY
,
hour
);
c
.
set
(
Calendar
.
MINUTE
,
minute
);
c
.
set
(
Calendar
.
SECOND
,
second
);
if
(
type
!=
Value
.
TIMESTAMP
)
{
c
.
set
(
Calendar
.
MILLISECOND
,
nano
/
1000000
);
}
time
=
c
.
getTime
().
getTime
();
switch
(
type
)
{
case
Value
.
DATE
:
return
new
java
.
sql
.
Date
(
time
);
case
Value
.
TIME
:
return
new
java
.
sql
.
Time
(
time
);
case
Value
.
TIMESTAMP
:
{
Timestamp
ts
=
new
Timestamp
(
time
);
ts
.
setNanos
(
nano
);
return
ts
;
}
default
:
throw
Message
.
getInternalError
(
"type:"
+
type
);
}
}
catch
(
IllegalArgumentException
e
)
{
throw
Message
.
getSQLException
(
errorCode
,
s
);
}
}
}
h2/src/main/org/h2/value/Transfer.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* */
package
org
.
h2
.
value
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.DataInputStream
;
import
java.io.DataOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStreamWriter
;
import
java.io.Reader
;
import
java.io.Writer
;
import
java.math.BigDecimal
;
import
java.net.Socket
;
import
java.sql.Date
;
import
java.sql.ResultSet
;
import
java.sql.ResultSetMetaData
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SessionInterface
;
import
org.h2.message.Message
;
import
org.h2.message.TraceSystem
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.ExactUTF8InputStreamReader
;
import
org.h2.util.IOUtils
;
import
org.h2.util.StringCache
;
/**
* @author Thomas
*/
public
class
Transfer
{
private
static
final
int
BUFFER_SIZE
=
16
*
1024
;
private
static
final
int
LOB_MAGIC
=
0x1234
;
protected
Socket
socket
;
protected
DataInputStream
in
;
protected
DataOutputStream
out
;
private
Exception
stackTrace
=
new
Exception
();
private
SessionInterface
session
;
public
Transfer
(
SessionInterface
session
)
{
this
.
session
=
session
;
}
public
void
finalize
()
{
if
(!
Constants
.
RUN_FINALIZERS
)
{
return
;
}
if
(
socket
!=
null
)
{
throw
Message
.
getInternalError
(
"not closed"
,
stackTrace
);
}
}
public
void
setSocket
(
Socket
s
)
{
socket
=
s
;
}
public
void
init
()
throws
IOException
{
in
=
new
DataInputStream
(
new
BufferedInputStream
(
socket
.
getInputStream
(),
Transfer
.
BUFFER_SIZE
));
out
=
new
DataOutputStream
(
new
BufferedOutputStream
(
socket
.
getOutputStream
(),
Transfer
.
BUFFER_SIZE
));
}
public
void
flush
()
throws
IOException
{
out
.
flush
();
}
public
Transfer
writeBoolean
(
boolean
x
)
throws
IOException
{
out
.
writeByte
((
byte
)(
x
?
1
:
0
));
return
this
;
}
public
boolean
readBoolean
()
throws
IOException
{
return
in
.
readByte
()
==
1
;
}
public
Transfer
writeByte
(
byte
x
)
throws
IOException
{
out
.
writeByte
(
x
);
return
this
;
}
public
byte
readByte
()
throws
IOException
{
return
in
.
readByte
();
}
public
Transfer
writeInt
(
int
i
)
throws
IOException
{
out
.
writeInt
(
i
);
return
this
;
}
public
int
readInt
()
throws
IOException
{
return
in
.
readInt
();
}
public
Transfer
writeLong
(
long
i
)
throws
IOException
{
out
.
writeLong
(
i
);
return
this
;
}
public
long
readLong
()
throws
IOException
{
return
in
.
readLong
();
}
public
Transfer
writeDouble
(
double
i
)
throws
IOException
{
out
.
writeDouble
(
i
);
return
this
;
}
public
Transfer
writeFloat
(
float
i
)
throws
IOException
{
out
.
writeFloat
(
i
);
return
this
;
}
public
double
readDouble
()
throws
IOException
{
return
in
.
readDouble
();
}
public
float
readFloat
()
throws
IOException
{
return
in
.
readFloat
();
}
public
Transfer
writeString
(
String
s
)
throws
IOException
{
if
(
s
==
null
)
{
out
.
writeInt
(-
1
);
}
else
{
int
len
=
s
.
length
();
out
.
writeInt
(
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
out
.
writeChar
(
s
.
charAt
(
i
));
}
}
return
this
;
}
public
String
readString
()
throws
IOException
{
int
len
=
in
.
readInt
();
if
(
len
==
-
1
)
{
return
null
;
}
// TODO optimize: StringBuffer is synchronized, maybe use a char array (but that means more memory)
StringBuffer
buff
=
new
StringBuffer
(
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
buff
.
append
(
in
.
readChar
());
}
String
s
=
buff
.
toString
();
s
=
StringCache
.
get
(
s
);
return
s
;
}
public
Transfer
writeBytes
(
byte
[]
data
)
throws
IOException
{
if
(
data
==
null
)
{
writeInt
(-
1
);
}
else
{
writeInt
(
data
.
length
);
out
.
write
(
data
);
}
return
this
;
}
public
byte
[]
readBytes
()
throws
IOException
{
int
len
=
readInt
();
if
(
len
==
-
1
)
{
return
null
;
}
byte
[]
b
=
new
byte
[
len
];
in
.
readFully
(
b
);
return
b
;
}
public
void
close
()
{
if
(
socket
!=
null
)
{
try
{
out
.
flush
();
if
(
socket
!=
null
)
{
socket
.
close
();
}
}
catch
(
IOException
e
)
{
TraceSystem
.
traceThrowable
(
e
);
}
finally
{
socket
=
null
;
}
}
}
public
void
writeValue
(
Value
v
)
throws
IOException
,
SQLException
{
int
type
=
v
.
getType
();
writeInt
(
type
);
switch
(
type
)
{
case
Value
.
NULL
:
break
;
case
Value
.
BYTES
:
case
Value
.
JAVA_OBJECT
:
writeBytes
(
v
.
getBytes
());
break
;
case
Value
.
UUID
:
{
ValueUuid
uuid
=
(
ValueUuid
)
v
;
writeLong
(
uuid
.
getHigh
());
writeLong
(
uuid
.
getLow
());
break
;
}
case
Value
.
BOOLEAN
:
writeBoolean
(
v
.
getBoolean
().
booleanValue
());
break
;
case
Value
.
BYTE
:
writeByte
(
v
.
getByte
());
break
;
case
Value
.
TIME
:
writeLong
(
v
.
getTime
().
getTime
());
break
;
case
Value
.
DATE
:
writeLong
(
v
.
getDate
().
getTime
());
break
;
case
Value
.
TIMESTAMP
:
{
Timestamp
ts
=
v
.
getTimestamp
();
writeLong
(
ts
.
getTime
());
writeInt
(
ts
.
getNanos
());
break
;
}
case
Value
.
DECIMAL
:
writeString
(
v
.
getString
());
break
;
case
Value
.
DOUBLE
:
writeDouble
(
v
.
getDouble
());
break
;
case
Value
.
FLOAT
:
writeFloat
(
v
.
getFloat
());
break
;
case
Value
.
INT
:
writeInt
(
v
.
getInt
());
break
;
case
Value
.
LONG
:
writeLong
(
v
.
getLong
());
break
;
case
Value
.
SHORT
:
writeInt
(
v
.
getShort
());
break
;
case
Value
.
STRING
:
case
Value
.
STRING_IGNORECASE
:
writeString
(
v
.
getString
());
break
;
case
Value
.
BLOB
:
{
long
length
=
v
.
getPrecision
();
if
(
Constants
.
CHECK
&&
length
<
0
)
{
throw
Message
.
getInternalError
(
"length: "
+
length
);
}
writeLong
(
length
);
InputStream
in
=
v
.
getInputStream
();
long
written
=
IOUtils
.
copyAndCloseInput
(
in
,
out
);
if
(
Constants
.
CHECK
&&
written
!=
length
)
{
Message
.
getInternalError
(
"length:"
+
length
+
" written:"
+
written
);
}
writeInt
(
LOB_MAGIC
);
break
;
}
case
Value
.
CLOB
:
{
long
length
=
v
.
getPrecision
();
if
(
Constants
.
CHECK
&&
length
<
0
)
{
throw
Message
.
getInternalError
(
"length: "
+
length
);
}
writeLong
(
length
);
Reader
reader
=
v
.
getReader
();
Writer
writer
=
new
OutputStreamWriter
(
out
,
Constants
.
UTF8
);
long
written
=
IOUtils
.
copyAndCloseInput
(
reader
,
writer
);
if
(
Constants
.
CHECK
&&
written
!=
length
)
{
Message
.
getInternalError
(
"length:"
+
length
+
" written:"
+
written
);
}
writer
.
flush
();
writeInt
(
LOB_MAGIC
);
break
;
}
case
Value
.
ARRAY
:
{
Value
[]
list
=
((
ValueArray
)
v
).
getList
();
writeInt
(
list
.
length
);
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
writeValue
(
list
[
i
]);
}
break
;
}
case
Value
.
RESULT_SET
:
{
ResultSet
rs
=
((
ValueResultSet
)
v
).
getResultSet
();
rs
.
beforeFirst
();
ResultSetMetaData
meta
=
rs
.
getMetaData
();
int
columnCount
=
meta
.
getColumnCount
();
writeInt
(
columnCount
);
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
writeString
(
meta
.
getColumnName
(
i
+
1
));
writeInt
(
meta
.
getColumnType
(
i
+
1
));
writeInt
(
meta
.
getPrecision
(
i
+
1
));
writeInt
(
meta
.
getScale
(
i
+
1
));
}
while
(
rs
.
next
())
{
writeBoolean
(
true
);
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
int
t
=
DataType
.
convertSQLTypeToValueType
(
meta
.
getColumnType
(
i
+
1
));
Value
val
=
DataType
.
readValue
(
session
,
rs
,
i
+
1
,
t
);
writeValue
(
val
);
}
}
writeBoolean
(
false
);
rs
.
beforeFirst
();
break
;
}
default
:
throw
Message
.
getInternalError
(
"type="
+
type
);
}
}
public
Value
readValue
()
throws
IOException
,
SQLException
{
int
type
=
readInt
();
switch
(
type
)
{
case
Value
.
NULL
:
return
ValueNull
.
INSTANCE
;
case
Value
.
BYTES
:
return
ValueBytes
.
get
(
readBytes
());
case
Value
.
UUID
:
return
ValueUuid
.
get
(
readLong
(),
readLong
());
case
Value
.
JAVA_OBJECT
:
return
ValueJavaObject
.
get
(
readBytes
());
case
Value
.
BOOLEAN
:
return
ValueBoolean
.
get
(
readBoolean
());
case
Value
.
BYTE
:
return
ValueByte
.
get
(
readByte
());
case
Value
.
DATE
:
return
ValueDate
.
get
(
new
Date
(
readLong
()));
case
Value
.
TIME
:
return
ValueTime
.
get
(
new
Time
(
readLong
()));
case
Value
.
TIMESTAMP
:
{
Timestamp
ts
=
new
Timestamp
(
readLong
());
ts
.
setNanos
(
readInt
());
return
ValueTimestamp
.
get
(
ts
);
}
case
Value
.
DECIMAL
:
return
ValueDecimal
.
get
(
new
BigDecimal
(
readString
()));
case
Value
.
DOUBLE
:
return
ValueDouble
.
get
(
readDouble
());
case
Value
.
FLOAT
:
return
ValueFloat
.
get
(
readFloat
());
case
Value
.
INT
:
return
ValueInt
.
get
(
readInt
());
case
Value
.
LONG
:
return
ValueLong
.
get
(
readLong
());
case
Value
.
SHORT
:
return
ValueShort
.
get
((
short
)
readInt
());
case
Value
.
STRING
:
return
ValueString
.
get
(
readString
());
case
Value
.
STRING_IGNORECASE
:
return
ValueStringIgnoreCase
.
get
(
readString
());
case
Value
.
BLOB
:
{
long
length
=
readLong
();
ValueLob
v
=
ValueLob
.
createBlob
(
in
,
length
,
session
.
getDataHandler
());
if
(
readInt
()
!=
LOB_MAGIC
)
{
throw
Message
.
getSQLException
(
Message
.
CONNECTION_BROKEN
);
}
return
v
;
}
case
Value
.
CLOB
:
{
long
length
=
readLong
();
ValueLob
v
=
ValueLob
.
createClob
(
new
ExactUTF8InputStreamReader
(
in
),
length
,
session
.
getDataHandler
());
if
(
readInt
()
!=
LOB_MAGIC
)
{
throw
Message
.
getSQLException
(
Message
.
CONNECTION_BROKEN
);
}
return
v
;
}
case
Value
.
ARRAY
:
{
int
len
=
readInt
();
Value
[]
list
=
new
Value
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
list
[
i
]
=
readValue
();
}
return
ValueArray
.
get
(
list
);
}
case
Value
.
RESULT_SET
:
{
SimpleResultSet
rs
=
new
SimpleResultSet
();
int
columns
=
readInt
();
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
rs
.
addColumn
(
readString
(),
readInt
(),
readInt
(),
readInt
());
}
while
(
true
)
{
if
(!
readBoolean
())
{
break
;
}
Object
[]
o
=
new
Object
[
columns
];
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
o
[
i
]
=
readValue
().
getObject
();
}
rs
.
addRow
(
o
);
}
return
ValueResultSet
.
get
(
rs
);
}
default
:
throw
Message
.
getInternalError
(
"type="
+
type
);
}
}
public
Socket
getSocket
()
{
return
socket
;
}
public
void
setSession
(
SessionInterface
session
)
{
this
.
session
=
session
;
}
}
h2/src/main/org/h2/value/Value.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.lang.ref.WeakReference
;
import
java.math.BigDecimal
;
import
java.sql.Date
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
java.sql.Types
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.message.Message
;
import
org.h2.store.DataHandler
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.ByteUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.TypeConverter
;
/**
* @author Thomas
*/
public
abstract
class
Value
{
// TODO value: float is missing
// remember to keep the order
public
static
final
int
UNKNOWN
=
-
1
;
public
static
final
int
NULL
=
0
,
BOOLEAN
=
1
,
BYTE
=
2
,
SHORT
=
3
,
INT
=
4
,
LONG
=
5
,
DECIMAL
=
6
;
public
static
final
int
DOUBLE
=
7
,
FLOAT
=
8
,
TIME
=
9
,
DATE
=
10
,
TIMESTAMP
=
11
,
BYTES
=
12
;
public
static
final
int
STRING
=
13
,
STRING_IGNORECASE
=
14
,
BLOB
=
15
,
CLOB
=
16
;
public
static
final
int
ARRAY
=
17
,
RESULT_SET
=
18
,
JAVA_OBJECT
=
19
,
UUID
=
20
;
public
static
final
int
TYPE_COUNT
=
UUID
+
1
;
private
static
WeakReference
weakCache
=
new
WeakReference
(
null
);
// private static int cacheCleaner = 0;
// testing: cacheHit / miss are public!
// public static int cacheHit = 0, cacheMiss = 0;
// private static Value[] cache = new Value[Constants.OBJECT_CACHE_SIZE];
private
static
final
BigDecimal
MAX_LONG_DECIMAL
=
new
BigDecimal
(
""
+
Long
.
MAX_VALUE
);
private
static
final
BigDecimal
MIN_LONG_DECIMAL
=
new
BigDecimal
(
""
+
Long
.
MIN_VALUE
);
static
Value
cache
(
Value
v
)
{
if
(
Constants
.
USE_OBJECT_CACHE
)
{
Value
[]
cache
=
(
Value
[])
weakCache
.
get
();
int
hash
=
v
.
hashCode
();
if
(
cache
==
null
)
{
cache
=
new
Value
[
Constants
.
OBJECT_CACHE_SIZE
];
weakCache
=
new
WeakReference
(
cache
);
}
int
index
=
hash
&
(
Constants
.
OBJECT_CACHE_SIZE
-
1
);
Value
cached
=
cache
[
index
];
if
(
cached
!=
null
)
{
if
(
cached
.
getType
()
==
v
.
getType
()
&&
v
.
isEqual
(
cached
))
{
// cacheHit++;
return
cached
;
}
}
// cacheMiss++;
// cache[cacheCleaner] = null;
// cacheCleaner = (cacheCleaner + 1) & (Constants.OBJECT_CACHE_SIZE - 1);
cache
[
index
]
=
v
;
}
return
v
;
}
public
abstract
String
getSQL
();
public
abstract
int
getType
();
public
abstract
long
getPrecision
();
public
abstract
int
getDisplaySize
();
public
abstract
String
getString
()
throws
SQLException
;
// public abstract String getJavaString();
protected
abstract
int
compareSecure
(
Value
v
,
CompareMode
mode
)
throws
SQLException
;
protected
abstract
boolean
isEqual
(
Value
v
);
public
abstract
Object
getObject
()
throws
SQLException
;
public
abstract
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
;
public
Boolean
getBoolean
()
throws
SQLException
{
return
((
ValueBoolean
)
convertTo
(
Value
.
BOOLEAN
)).
getBoolean
();
}
public
Date
getDate
()
throws
SQLException
{
return
((
ValueDate
)
convertTo
(
Value
.
DATE
)).
getDate
();
}
public
Time
getTime
()
throws
SQLException
{
return
((
ValueTime
)
convertTo
(
Value
.
TIME
)).
getTime
();
}
public
Timestamp
getTimestamp
()
throws
SQLException
{
return
((
ValueTimestamp
)
convertTo
(
Value
.
TIMESTAMP
)).
getTimestamp
();
}
public
byte
[]
getBytes
()
throws
SQLException
{
return
((
ValueBytes
)
convertTo
(
Value
.
BYTES
)).
getBytes
();
}
public
byte
getByte
()
throws
SQLException
{
return
((
ValueByte
)
convertTo
(
Value
.
BYTE
)).
getByte
();
}
public
short
getShort
()
throws
SQLException
{
return
((
ValueShort
)
convertTo
(
Value
.
SHORT
)).
getShort
();
}
public
BigDecimal
getBigDecimal
()
throws
SQLException
{
return
((
ValueDecimal
)
convertTo
(
Value
.
DECIMAL
)).
getBigDecimal
();
}
public
double
getDouble
()
throws
SQLException
{
return
((
ValueDouble
)
convertTo
(
Value
.
DOUBLE
)).
getDouble
();
}
public
float
getFloat
()
throws
SQLException
{
return
((
ValueFloat
)
convertTo
(
Value
.
FLOAT
)).
getFloat
();
}
public
int
getInt
()
throws
SQLException
{
return
((
ValueInt
)
convertTo
(
Value
.
INT
)).
getInt
();
}
public
long
getLong
()
throws
SQLException
{
return
((
ValueLong
)
convertTo
(
Value
.
LONG
)).
getLong
();
}
public
InputStream
getInputStream
()
throws
SQLException
{
return
new
ByteArrayInputStream
(
getBytes
());
}
public
Reader
getReader
()
throws
SQLException
{
return
TypeConverter
.
getReader
(
getString
());
}
public
Value
add
(
Value
v
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
int
getSignum
()
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
Value
negate
()
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
Value
subtract
(
Value
v
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
Value
multiply
(
Value
v
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
static
int
getHigherOrder
(
int
t1
,
int
t2
)
throws
SQLException
{
if
(
t1
==
t2
)
{
if
(
t1
==
Value
.
UNKNOWN
)
{
throw
Message
.
getSQLException
(
Message
.
UNKNOWN_DATA_TYPE_1
,
"?, ?"
);
}
return
t1
;
}
int
type
=
Math
.
max
(
t1
,
t2
);
switch
(
type
)
{
case
Value
.
STRING
:
case
Value
.
STRING_IGNORECASE
:
{
int
b
=
Math
.
min
(
t1
,
t2
);
switch
(
b
)
{
case
Value
.
BLOB
:
case
Value
.
BYTES
:
case
Value
.
DATE
:
case
Value
.
JAVA_OBJECT
:
case
Value
.
TIME
:
case
Value
.
TIMESTAMP
:
case
Value
.
UUID
:
return
b
;
}
}
}
return
type
;
}
public
Value
convertTo
(
int
type
)
throws
SQLException
{
// converting NULL done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob
if
(
getType
()
==
type
)
{
return
this
;
}
// decimal conversion
switch
(
type
)
{
case
BOOLEAN:
{
switch
(
getType
())
{
case
BYTE:
case
SHORT:
case
INT:
case
LONG:
case
DECIMAL:
case
DOUBLE:
case
FLOAT:
return
ValueBoolean
.
get
(
getSignum
()
!=
0
);
case
TIME:
case
DATE:
case
TIMESTAMP:
case
BYTES:
case
JAVA_OBJECT:
case
UUID:
throw
Message
.
getSQLException
(
Message
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
case
BYTE:
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueByte
.
get
(
getBoolean
().
booleanValue
()
?
(
byte
)
1
:
(
byte
)
0
);
case
SHORT:
return
ValueByte
.
get
(
convertToByte
(
getShort
()));
case
INT:
return
ValueByte
.
get
(
convertToByte
(
getInt
()));
case
LONG:
return
ValueByte
.
get
(
convertToByte
(
getLong
()));
case
DECIMAL:
return
ValueByte
.
get
(
convertToByte
(
convertToLong
(
getBigDecimal
())));
case
DOUBLE:
return
ValueByte
.
get
(
convertToByte
(
convertToLong
(
getDouble
())));
case
FLOAT:
return
ValueByte
.
get
(
convertToByte
(
convertToLong
(
getFloat
())));
}
break
;
}
case
SHORT:
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueShort
.
get
(
getBoolean
().
booleanValue
()
?
(
short
)
1
:
(
short
)
0
);
case
BYTE:
return
ValueShort
.
get
(
getByte
());
case
INT:
return
ValueShort
.
get
(
convertToShort
(
getInt
()));
case
LONG:
return
ValueShort
.
get
(
convertToShort
(
getLong
()));
case
DECIMAL:
return
ValueShort
.
get
(
convertToShort
(
convertToLong
(
getBigDecimal
())));
case
DOUBLE:
return
ValueShort
.
get
(
convertToShort
(
convertToLong
(
getDouble
())));
case
FLOAT:
return
ValueShort
.
get
(
convertToShort
(
convertToLong
(
getFloat
())));
}
break
;
}
case
INT:
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueInt
.
get
(
getBoolean
().
booleanValue
()
?
1
:
0
);
case
BYTE:
return
ValueInt
.
get
(
getByte
());
case
SHORT:
return
ValueInt
.
get
(
getShort
());
case
LONG:
return
ValueInt
.
get
(
convertToInt
(
getLong
()));
case
DECIMAL:
return
ValueInt
.
get
(
convertToInt
(
convertToLong
(
getBigDecimal
())));
case
DOUBLE:
return
ValueInt
.
get
(
convertToInt
(
convertToLong
(
getDouble
())));
case
FLOAT:
return
ValueInt
.
get
(
convertToInt
(
convertToLong
(
getFloat
())));
}
break
;
}
case
LONG:
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueLong
.
get
(
getBoolean
().
booleanValue
()
?
1
:
0
);
case
BYTE:
return
ValueLong
.
get
(
getByte
());
case
SHORT:
return
ValueLong
.
get
(
getShort
());
case
INT:
return
ValueLong
.
get
(
getInt
());
case
DECIMAL:
return
ValueLong
.
get
(
convertToLong
(
getBigDecimal
()));
case
DOUBLE:
return
ValueLong
.
get
(
convertToLong
(
getDouble
()));
case
FLOAT:
return
ValueLong
.
get
(
convertToLong
(
getFloat
()));
}
break
;
}
case
DECIMAL:
{
// convert to string is required for JDK 1.4
switch
(
getType
())
{
case
BOOLEAN:
return
ValueDecimal
.
get
(
new
BigDecimal
(
getBoolean
().
booleanValue
()
?
"1"
:
"0"
));
case
BYTE:
return
ValueDecimal
.
get
(
new
BigDecimal
(
""
+
getByte
()));
case
SHORT:
return
ValueDecimal
.
get
(
new
BigDecimal
(
""
+
getShort
()));
case
INT:
return
ValueDecimal
.
get
(
new
BigDecimal
(
""
+
getInt
()));
case
LONG:
return
ValueDecimal
.
get
(
new
BigDecimal
(
""
+
getLong
()));
case
DOUBLE:
{
double
d
=
getDouble
();
if
(
Double
.
isInfinite
(
d
)
||
Double
.
isNaN
(
d
))
{
throw
Message
.
getSQLException
(
Message
.
DATA_CONVERSION_ERROR_1
,
""
+
d
);
}
return
ValueDecimal
.
get
(
new
BigDecimal
(
d
));
}
case
FLOAT:
{
float
f
=
getFloat
();
if
(
Float
.
isInfinite
(
f
)
||
Float
.
isNaN
(
f
))
{
throw
Message
.
getSQLException
(
Message
.
DATA_CONVERSION_ERROR_1
,
""
+
f
);
}
return
ValueDecimal
.
get
(
new
BigDecimal
(
f
));
}
}
break
;
}
case
DOUBLE:
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueDouble
.
get
(
getBoolean
().
booleanValue
()
?
1
:
0
);
case
BYTE:
return
ValueDouble
.
get
(
getByte
());
case
SHORT:
return
ValueDouble
.
get
(
getShort
());
case
INT:
return
ValueDouble
.
get
(
getInt
());
case
LONG:
return
ValueDouble
.
get
(
getLong
());
case
DECIMAL:
return
ValueDouble
.
get
(
getBigDecimal
().
doubleValue
());
case
FLOAT:
return
ValueDouble
.
get
(
getFloat
());
}
break
;
}
case
FLOAT:
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueFloat
.
get
(
getBoolean
().
booleanValue
()
?
1
:
0
);
case
BYTE:
return
ValueFloat
.
get
(
getByte
());
case
SHORT:
return
ValueFloat
.
get
(
getShort
());
case
INT:
return
ValueFloat
.
get
(
getInt
());
case
LONG:
return
ValueFloat
.
get
(
getLong
());
case
DECIMAL:
return
ValueFloat
.
get
(
getBigDecimal
().
floatValue
());
case
DOUBLE:
return
ValueFloat
.
get
((
float
)
getDouble
());
}
break
;
}
case
DATE:
{
switch
(
getType
())
{
case
TIME:
return
ValueDate
.
get
(
new
Date
(
getTime
().
getTime
()));
case
TIMESTAMP:
return
ValueDate
.
get
(
new
Date
(
getTimestamp
().
getTime
()));
}
break
;
}
case
TIME:
{
switch
(
getType
())
{
case
DATE:
return
ValueTime
.
get
(
new
Time
(
getDate
().
getTime
()));
case
TIMESTAMP:
return
ValueTime
.
get
(
new
Time
(
getTimestamp
().
getTime
()));
}
break
;
}
case
TIMESTAMP:
{
switch
(
getType
())
{
case
TIME:
return
ValueTimestamp
.
get
(
new
Timestamp
(
getTime
().
getTime
()));
case
DATE:
return
ValueTimestamp
.
get
(
new
Timestamp
(
getDate
().
getTime
()));
}
break
;
}
case
BYTES:
{
switch
(
getType
())
{
case
JAVA_OBJECT:
case
BLOB:
case
UUID:
return
ValueBytes
.
get
(
getBytes
());
}
break
;
}
case
JAVA_OBJECT:
{
switch
(
getType
())
{
case
BYTES:
case
BLOB:
return
ValueBytes
.
get
(
getBytes
());
}
break
;
}
case
BLOB:
{
switch
(
getType
())
{
case
BYTES:
return
ValueLob
.
createSmallLob
(
Value
.
BLOB
,
getBytes
());
}
break
;
}
case
UUID:
{
switch
(
getType
())
{
case
BYTES:
return
ValueUuid
.
get
(
getBytes
());
}
}
}
// conversion by parsing the string value
String
s
=
getString
();
try
{
switch
(
type
)
{
case
NULL:
return
ValueNull
.
INSTANCE
;
case
BOOLEAN:
{
if
(
s
.
equalsIgnoreCase
(
"true"
)
||
s
.
equalsIgnoreCase
(
"t"
)
||
s
.
equalsIgnoreCase
(
"yes"
)
||
s
.
equalsIgnoreCase
(
"y"
))
{
return
ValueBoolean
.
get
(
true
);
}
else
if
(
s
.
equalsIgnoreCase
(
"false"
)
||
s
.
equalsIgnoreCase
(
"f"
)
||
s
.
equalsIgnoreCase
(
"no"
)
||
s
.
equalsIgnoreCase
(
"n"
))
{
return
ValueBoolean
.
get
(
false
);
}
else
{
// convert to a number, and if it is not 0 then it is true
return
ValueBoolean
.
get
(
new
BigDecimal
(
s
).
signum
()
!=
0
);
}
}
case
BYTE:
return
ValueByte
.
get
(
MathUtils
.
decodeByte
(
s
.
trim
()));
case
SHORT:
return
ValueShort
.
get
(
MathUtils
.
decodeShort
(
s
.
trim
()));
case
INT:
return
ValueInt
.
get
(
MathUtils
.
decodeInt
(
s
.
trim
()));
case
LONG:
return
ValueLong
.
get
(
MathUtils
.
decodeLong
(
s
.
trim
()));
case
DECIMAL:
return
ValueDecimal
.
get
(
new
BigDecimal
(
s
.
trim
()));
case
TIME:
return
ValueTime
.
get
(
ValueTime
.
parseTime
(
s
.
trim
()));
case
DATE:
return
ValueDate
.
get
(
ValueDate
.
parseDate
(
s
.
trim
()));
case
TIMESTAMP:
return
ValueTimestamp
.
get
(
ValueTimestamp
.
parseTimestamp
(
s
.
trim
()));
case
BYTES:
return
ValueBytes
.
get
(
ByteUtils
.
convertStringToBytes
(
s
.
trim
()));
case
JAVA_OBJECT:
return
ValueJavaObject
.
get
(
ByteUtils
.
convertStringToBytes
(
s
.
trim
()));
case
STRING:
return
ValueString
.
get
(
s
);
case
STRING_IGNORECASE:
return
ValueStringIgnoreCase
.
get
(
s
);
case
DOUBLE:
return
ValueDouble
.
get
(
Double
.
parseDouble
(
s
.
trim
()));
case
FLOAT:
return
ValueFloat
.
get
(
Float
.
parseFloat
(
s
.
trim
()));
case
CLOB:
return
ValueLob
.
createSmallLob
(
CLOB
,
StringUtils
.
utf8Encode
(
s
));
case
BLOB:
return
ValueLob
.
createSmallLob
(
BLOB
,
ByteUtils
.
convertStringToBytes
(
s
.
trim
()));
case
ARRAY:
return
ValueArray
.
get
(
new
Value
[]{
ValueString
.
get
(
s
)});
case
RESULT_SET:
{
SimpleResultSet
rs
=
new
SimpleResultSet
();
rs
.
addColumn
(
"X"
,
Types
.
VARCHAR
,
s
.
length
(),
0
);
rs
.
addRow
(
new
String
[]{
s
});
return
ValueResultSet
.
get
(
rs
);
}
case
UUID:
return
ValueUuid
.
get
(
s
);
default
:
throw
Message
.
getInternalError
(
"type="
+
type
);
}
}
catch
(
NumberFormatException
e
)
{
throw
Message
.
getSQLException
(
Message
.
DATA_CONVERSION_ERROR_1
,
new
String
[]
{
s
},
e
);
}
}
public
final
int
compareTypeSave
(
Value
v
,
CompareMode
mode
)
throws
SQLException
{
if
(
this
==
ValueNull
.
INSTANCE
)
{
return
v
==
ValueNull
.
INSTANCE
?
0
:
-
1
;
}
else
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
1
;
}
return
compareSecure
(
v
,
mode
);
}
public
final
boolean
compareEqual
(
Value
v
)
throws
SQLException
{
if
(
this
==
ValueNull
.
INSTANCE
)
{
return
v
==
ValueNull
.
INSTANCE
;
}
else
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
false
;
}
if
(
getType
()
==
v
.
getType
())
{
return
isEqual
(
v
);
}
int
t2
=
Value
.
getHigherOrder
(
getType
(),
v
.
getType
());
return
convertTo
(
t2
).
isEqual
(
v
.
convertTo
(
t2
));
}
public
final
int
compareTo
(
Value
v
,
CompareMode
mode
)
throws
SQLException
{
if
(
this
==
ValueNull
.
INSTANCE
)
{
return
v
==
ValueNull
.
INSTANCE
?
0
:
-
1
;
}
else
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
1
;
}
if
(
getType
()
==
v
.
getType
())
{
return
compareSecure
(
v
,
mode
);
}
int
t2
=
Value
.
getHigherOrder
(
getType
(),
v
.
getType
());
return
convertTo
(
t2
).
compareSecure
(
v
.
convertTo
(
t2
),
mode
);
}
public
int
getScale
()
{
return
0
;
}
public
Value
convertScale
(
boolean
onlyToSmallerScale
,
int
targetScale
)
throws
SQLException
{
return
this
;
}
public
Value
convertPrecision
(
long
precision
)
throws
SQLException
{
return
this
;
}
private
byte
convertToByte
(
long
x
)
throws
SQLException
{
if
(
x
>
Byte
.
MAX_VALUE
||
x
<
Byte
.
MIN_VALUE
)
{
throw
Message
.
getSQLException
(
Message
.
NUMERIC_VALUE_OUT_OF_RANGE
);
}
return
(
byte
)
x
;
}
private
short
convertToShort
(
long
x
)
throws
SQLException
{
if
(
x
>
Short
.
MAX_VALUE
||
x
<
Short
.
MIN_VALUE
)
{
throw
Message
.
getSQLException
(
Message
.
NUMERIC_VALUE_OUT_OF_RANGE
);
}
return
(
short
)
x
;
}
private
int
convertToInt
(
long
x
)
throws
SQLException
{
if
(
x
>
Integer
.
MAX_VALUE
||
x
<
Integer
.
MIN_VALUE
)
{
throw
Message
.
getSQLException
(
Message
.
NUMERIC_VALUE_OUT_OF_RANGE
);
}
return
(
int
)
x
;
}
private
long
convertToLong
(
double
x
)
throws
SQLException
{
if
(
x
>
Long
.
MAX_VALUE
||
x
<
Long
.
MIN_VALUE
)
{
// TODO document that +Infinity, -Infinity throw an exception and NaN returns 0
throw
Message
.
getSQLException
(
Message
.
NUMERIC_VALUE_OUT_OF_RANGE
);
}
if
(
Mode
.
getCurrentMode
().
roundWhenConvertToLong
)
{
return
Math
.
round
(
x
);
}
else
{
return
(
long
)
x
;
}
}
private
long
convertToLong
(
BigDecimal
x
)
throws
SQLException
{
if
(
x
.
compareTo
(
MAX_LONG_DECIMAL
)
>
0
||
x
.
compareTo
(
Value
.
MIN_LONG_DECIMAL
)
<
0
)
{
throw
Message
.
getSQLException
(
Message
.
NUMERIC_VALUE_OUT_OF_RANGE
);
}
if
(
Mode
.
getCurrentMode
().
roundWhenConvertToLong
)
{
return
Math
.
round
(
x
.
doubleValue
());
}
else
{
return
x
.
longValue
();
}
}
public
Value
link
(
DataHandler
handler
,
int
tableId
)
throws
SQLException
{
return
this
;
}
public
void
unlink
(
DataHandler
handler
)
throws
SQLException
{
}
}
h2/src/main/org/h2/value/ValueArray.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
public
class
ValueArray
extends
Value
{
private
Value
[]
values
;
private
int
hash
;
public
static
ValueArray
get
(
Value
[]
list
)
{
return
new
ValueArray
(
list
);
}
private
ValueArray
(
Value
[]
list
)
{
this
.
values
=
list
;
}
public
int
hashCode
()
{
if
(
hash
!=
0
)
{
return
hash
;
}
int
h
=
1
;
for
(
int
i
=
0
;
i
<
values
.
length
;)
{
h
=
h
*
31
+
values
[
i
++].
hashCode
();
}
return
hash
=
h
;
}
public
Value
[]
getList
()
{
return
values
;
}
public
int
compareTo
(
ValueArray
other
,
CompareMode
mode
)
throws
SQLException
{
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
Value
v1
=
values
[
i
];
Value
v2
=
other
.
values
[
i
];
int
comp
=
v1
.
compareTo
(
v2
,
mode
);
if
(
comp
!=
0
)
{
return
comp
;
}
}
return
0
;
}
public
int
getType
()
{
return
Value
.
ARRAY
;
}
public
long
getPrecision
()
{
return
0
;
}
public
String
getString
()
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
'('
);
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
", "
);
}
buff
.
append
(
values
[
i
].
getString
());
}
buff
.
append
(
')'
);
return
buff
.
toString
();
}
// public String getJavaString() {
// StringBuffer buff = new StringBuffer();
// buff.append('{');
// for (int i = 0; i < values.length; i++) {
// if (i > 0) {
// buff.append(", ");
// }
// buff.append(values[i].getJavaString());
// }
// buff.append('}');
// return buff.toString();
// }
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
throws
SQLException
{
ValueArray
v
=
(
ValueArray
)
o
;
if
(
values
==
v
.
values
)
{
return
0
;
}
if
(
values
.
length
!=
v
.
values
.
length
)
{
return
values
.
length
>
v
.
values
.
length
?
1
:
-
1
;
}
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
Value
v1
=
values
[
i
];
Value
v2
=
v
.
values
[
i
];
int
c
;
if
(
v1
==
ValueNull
.
INSTANCE
)
{
c
=
v2
==
ValueNull
.
INSTANCE
?
0
:
-
1
;
}
else
if
(
v2
==
ValueNull
.
INSTANCE
)
{
c
=
1
;
}
else
{
c
=
v1
.
compareSecure
(
v2
,
mode
);
}
if
(
c
!=
0
)
{
return
c
;
}
}
return
0
;
}
public
Object
getObject
()
throws
SQLException
{
Object
[]
list
=
new
Object
[
values
.
length
];
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
list
[
i
]
=
values
[
i
].
getObject
();
}
return
list
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
String
getSQL
()
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
'('
);
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
", "
);
}
buff
.
append
(
values
[
i
].
getSQL
());
}
buff
.
append
(
')'
);
return
buff
.
toString
();
}
public
int
getDisplaySize
()
{
int
size
=
0
;
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
size
+=
values
[
i
].
getDisplaySize
();
}
return
size
;
}
protected
boolean
isEqual
(
Value
o
)
{
if
(!(
o
instanceof
ValueArray
))
{
return
false
;
}
ValueArray
v
=
(
ValueArray
)
o
;
if
(
values
==
v
.
values
)
{
return
true
;
}
if
(
values
.
length
!=
v
.
values
.
length
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
if
(!
values
[
i
].
isEqual
(
v
.
values
[
i
]))
{
return
false
;
}
}
return
true
;
}
}
h2/src/main/org/h2/value/ValueBoolean.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
/**
* @author Thomas
*/
public
class
ValueBoolean
extends
Value
{
public
static
final
int
PRECISION
=
1
;
private
Boolean
value
;
private
static
final
ValueBoolean
TRUE
=
new
ValueBoolean
(
true
);
private
static
final
ValueBoolean
FALSE
=
new
ValueBoolean
(
false
);
private
ValueBoolean
(
boolean
value
)
{
this
.
value
=
Boolean
.
valueOf
(
""
+
value
);
}
public
int
getType
()
{
return
Value
.
BOOLEAN
;
}
public
String
getSQL
()
{
return
getString
();
}
public
String
getString
()
{
return
value
.
booleanValue
()
?
"TRUE"
:
"FALSE"
;
}
public
Value
negate
()
throws
SQLException
{
return
value
.
booleanValue
()
?
FALSE
:
TRUE
;
}
public
Boolean
getBoolean
()
{
return
value
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
boolean
v2
=
((
ValueBoolean
)
o
).
value
.
booleanValue
();
boolean
v
=
value
.
booleanValue
();
return
(
v
==
v2
)
?
0
:
(
v
?
1
:
-
1
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
value
.
booleanValue
()
?
1
:
0
;
}
public
Object
getObject
()
{
return
value
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setBoolean
(
parameterIndex
,
value
.
booleanValue
());
}
public
static
ValueBoolean
get
(
boolean
b
)
{
return
b
?
TRUE
:
FALSE
;
}
// public String getJavaString() {
// return value.booleanValue() ? "true" : "false";
// }
public
int
getDisplaySize
()
{
return
"FALSE"
.
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueBoolean
&&
value
==
((
ValueBoolean
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueByte.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
public
class
ValueByte
extends
Value
{
public
static
final
int
PRECISION
=
3
;
private
byte
value
;
private
ValueByte
(
byte
value
)
{
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
throws
SQLException
{
ValueByte
other
=
(
ValueByte
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(
value
+
other
.
value
);
}
return
ValueByte
.
get
((
byte
)
(
value
+
other
.
value
));
}
private
ValueByte
checkRange
(
int
value
)
throws
SQLException
{
if
(
value
<
Byte
.
MIN_VALUE
||
value
>
Byte
.
MAX_VALUE
)
{
throw
Message
.
getSQLException
(
Message
.
OVERFLOW_FOR_TYPE_1
,
DataType
.
getDataType
(
Value
.
BYTE
).
name
);
}
else
{
return
ValueByte
.
get
((
byte
)
value
);
}
}
public
int
getSignum
()
{
return
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
}
public
Value
negate
()
throws
SQLException
{
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(-(
int
)
value
);
}
return
ValueByte
.
get
((
byte
)
(-
value
));
}
public
Value
subtract
(
Value
v
)
throws
SQLException
{
ValueByte
other
=
(
ValueByte
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(
value
-
other
.
value
);
}
return
ValueByte
.
get
((
byte
)
(
value
-
other
.
value
));
}
public
Value
multiply
(
Value
v
)
throws
SQLException
{
ValueByte
other
=
(
ValueByte
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(
value
*
other
.
value
);
}
return
ValueByte
.
get
((
byte
)
(
value
*
other
.
value
));
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueByte
other
=
(
ValueByte
)
v
;
if
(
other
.
value
==
0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueByte
.
get
((
byte
)
(
value
/
other
.
value
));
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
BYTE
;
}
public
byte
getByte
()
{
return
value
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueByte
v
=
(
ValueByte
)
o
;
if
(
value
==
v
.
value
)
{
return
0
;
}
return
value
>
v
.
value
?
1
:
-
1
;
}
public
String
getString
()
{
return
String
.
valueOf
(
value
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
value
;
}
public
Object
getObject
()
{
return
new
Byte
(
value
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setByte
(
parameterIndex
,
value
);
}
public
static
ValueByte
get
(
byte
i
)
{
return
(
ValueByte
)
Value
.
cache
(
new
ValueByte
(
i
));
}
// public String getJavaString() {
// return "(byte)" + toString();
// }
public
int
getDisplaySize
()
{
return
PRECISION
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueByte
&&
value
==
((
ValueByte
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueBytes.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
org.h2.engine.Constants
;
/**
* @author Thomas
*/
public
class
ValueBytes
extends
ValueBytesBase
{
private
static
final
ValueBytes
EMPTY
=
new
ValueBytes
(
new
byte
[
0
]);
protected
ValueBytes
(
byte
[]
v
)
{
super
(
v
);
}
public
static
ValueBytes
get
(
byte
[]
b
)
{
if
(
b
.
length
==
0
)
{
return
EMPTY
;
}
ValueBytes
obj
=
new
ValueBytes
(
b
);
if
(
b
.
length
>
Constants
.
OBJECT_CACHE_MAX_PER_ELEMENT_SIZE
)
{
return
obj
;
}
return
(
ValueBytes
)
Value
.
cache
(
obj
);
}
public
int
getType
()
{
return
Value
.
BYTES
;
}
}
h2/src/main/org/h2/value/ValueBytesBase.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.util.ByteUtils
;
abstract
class
ValueBytesBase
extends
Value
{
private
byte
[]
value
;
private
int
hash
;
protected
ValueBytesBase
(
byte
[]
v
)
{
this
.
value
=
v
;
}
public
String
getSQL
()
{
return
"X'"
+
getString
()
+
"'"
;
}
public
byte
[]
getBytes
()
{
return
value
;
}
protected
int
compareSecure
(
Value
v
,
CompareMode
mode
)
{
byte
[]
v2
=
((
ValueBytesBase
)
v
).
value
;
return
ByteUtils
.
compareNotNull
(
value
,
v2
);
}
public
String
getString
()
{
return
ByteUtils
.
convertBytesToString
(
value
);
}
public
long
getPrecision
()
{
return
value
.
length
;
}
public
int
hashCode
()
{
if
(
hash
==
0
)
{
hash
=
ByteUtils
.
getByteArrayHash
(
value
);
}
return
hash
;
}
public
Object
getObject
()
{
return
getBytes
();
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setBytes
(
parameterIndex
,
value
);
}
public
int
getDisplaySize
()
{
return
value
.
length
*
2
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueBytesBase
&&
ByteUtils
.
compareNotNull
(
value
,
((
ValueBytesBase
)
v
).
value
)
==
0
;
}
// public String getJavaString() {
// return "ByteUtils.convertStringToBytes(\"" + toString() + "\")";
//}
}
h2/src/main/org/h2/value/ValueDate.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.Date
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.util.Calendar
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
ValueDate
extends
Value
{
public
static
final
int
PRECISION
=
8
;
private
Date
value
;
private
ValueDate
(
Date
value
)
{
// this class is mutable - must copy the object
Calendar
cal
=
Calendar
.
getInstance
();
cal
.
setTime
(
value
);
// TODO gcj: required so that the millis are calculated?
cal
.
get
(
Calendar
.
YEAR
);
cal
.
set
(
Calendar
.
MILLISECOND
,
0
);
cal
.
set
(
Calendar
.
SECOND
,
0
);
cal
.
set
(
Calendar
.
MINUTE
,
0
);
cal
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
this
.
value
=
new
Date
(
cal
.
getTime
().
getTime
());
}
public
static
Date
parseDate
(
String
s
)
throws
SQLException
{
return
(
Date
)
DataType
.
parseDateTime
(
s
,
Value
.
DATE
,
Message
.
DATE_CONSTANT_1
);
}
public
Date
getDate
()
{
// this class is mutable - must copy the object
return
(
Date
)
value
.
clone
();
}
public
String
getSQL
()
{
return
"DATE '"
+
getString
()
+
"'"
;
}
public
int
getType
()
{
return
Value
.
DATE
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueDate
v
=
(
ValueDate
)
o
;
int
c
=
value
.
compareTo
(
v
.
value
);
return
c
==
0
?
0
:
(
c
<
0
?
-
1
:
1
);
}
public
String
getString
()
{
return
value
.
toString
();
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
value
.
hashCode
();
}
public
Object
getObject
()
{
// this class is mutable - must copy the object
return
getDate
();
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setDate
(
parameterIndex
,
value
);
}
public
static
ValueDate
get
(
Date
date
)
{
return
(
ValueDate
)
Value
.
cache
(
new
ValueDate
(
date
));
}
// public String getJavaString() {
// return "Date.valueOf(\"" + toString() + "\")";
// }
public
int
getDisplaySize
()
{
return
"2001-01-01"
.
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueDate
&&
value
.
equals
(((
ValueDate
)
v
).
value
);
}
}
h2/src/main/org/h2/value/ValueDecimal.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.math.BigDecimal
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
import
org.h2.util.MathUtils
;
/**
* @author Thomas
*/
public
class
ValueDecimal
extends
Value
{
// TODO doc: document differences for BigDecimal 1.5 <> 1.4
private
BigDecimal
value
;
private
String
valueString
;
private
int
precision
;
private
static
final
BigDecimal
DEC_ZERO
=
new
BigDecimal
(
"0"
);
private
static
final
BigDecimal
DEC_ONE
=
new
BigDecimal
(
"1"
);
private
static
final
ValueDecimal
ZERO
=
new
ValueDecimal
(
DEC_ZERO
);
private
static
final
ValueDecimal
ONE
=
new
ValueDecimal
(
DEC_ONE
);
public
static
final
int
DEFAULT_PRECISION
=
65535
;
public
static
final
int
DEFAULT_SCALE
=
32767
;
private
static
final
int
DIVIDE_SCALE_ADD
=
25
;
private
ValueDecimal
(
BigDecimal
value
)
{
if
(
value
==
null
)
{
throw
new
NullPointerException
();
}
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
{
ValueDecimal
dec
=
(
ValueDecimal
)
v
;
return
ValueDecimal
.
get
(
value
.
add
(
dec
.
value
));
}
public
Value
subtract
(
Value
v
)
{
ValueDecimal
dec
=
(
ValueDecimal
)
v
;
return
ValueDecimal
.
get
(
value
.
subtract
(
dec
.
value
));
}
public
Value
negate
()
{
return
ValueDecimal
.
get
(
value
.
negate
());
}
public
Value
multiply
(
Value
v
)
{
ValueDecimal
dec
=
(
ValueDecimal
)
v
;
return
ValueDecimal
.
get
(
value
.
multiply
(
dec
.
value
));
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueDecimal
dec
=
(
ValueDecimal
)
v
;
// TODO value: divide decimal: rounding?
if
(
dec
.
value
.
signum
()
==
0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
BigDecimal
bd
=
value
.
divide
(
dec
.
value
,
value
.
scale
()+
DIVIDE_SCALE_ADD
,
BigDecimal
.
ROUND_HALF_DOWN
);
if
(
bd
.
signum
()==
0
)
{
bd
=
DEC_ZERO
;
}
else
if
(
bd
.
scale
()>
0
)
{
if
(!
bd
.
unscaledValue
().
testBit
(
0
))
{
String
s
=
bd
.
toString
();
int
i
=
s
.
length
()
-
1
;
while
(
i
>=
0
&&
s
.
charAt
(
i
)
==
'0'
)
{
i
--;
}
if
(
i
<
s
.
length
()
-
1
)
{
s
=
s
.
substring
(
0
,
i
+
1
);
bd
=
new
BigDecimal
(
s
);
}
}
}
return
ValueDecimal
.
get
(
bd
);
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
DECIMAL
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueDecimal
v
=
(
ValueDecimal
)
o
;
int
c
=
value
.
compareTo
(
v
.
value
);
return
c
==
0
?
0
:
(
c
<
0
?
-
1
:
1
);
}
public
int
getSignum
()
{
return
value
.
signum
();
}
public
BigDecimal
getBigDecimal
()
{
return
value
;
}
public
String
getString
()
{
if
(
valueString
==
null
)
{
valueString
=
value
.
toString
();
}
return
valueString
;
}
public
long
getPrecision
()
{
if
(
precision
==
0
)
{
precision
=
value
.
unscaledValue
().
abs
().
toString
().
length
();
}
return
precision
;
}
public
int
getScale
()
{
return
value
.
scale
();
}
public
int
hashCode
()
{
return
value
.
hashCode
();
}
public
Object
getObject
()
{
return
value
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setBigDecimal
(
parameterIndex
,
value
);
}
public
Value
convertScale
(
boolean
onlyToSmallerScale
,
int
targetScale
)
throws
SQLException
{
if
(
value
.
scale
()
==
targetScale
)
{
return
this
;
}
if
(
onlyToSmallerScale
||
targetScale
>=
DEFAULT_SCALE
)
{
if
(
value
.
scale
()
<
targetScale
)
{
return
this
;
}
}
BigDecimal
bd
=
MathUtils
.
setScale
(
value
,
targetScale
);
return
ValueDecimal
.
get
(
bd
);
}
public
Value
convertPrecision
(
long
precision
)
throws
SQLException
{
if
(
getPrecision
()
<=
precision
)
{
return
this
;
}
throw
Message
.
getSQLException
(
Message
.
VALUE_TOO_LARGE_FOR_PRECISION_1
,
""
+
precision
);
}
public
static
ValueDecimal
get
(
BigDecimal
dec
)
{
if
(
DEC_ZERO
.
equals
(
dec
))
{
return
ZERO
;
}
else
if
(
DEC_ONE
.
equals
(
dec
))
{
return
ONE
;
}
// TODO value optimization: find a way to find out size of bigdecimal,
// check max cache size
return
(
ValueDecimal
)
Value
.
cache
(
new
ValueDecimal
(
dec
));
}
// public String getJavaString() {
// return toString();
// }
public
int
getDisplaySize
()
{
// TODO displaySize: this is probably very slow
return
getString
().
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueDecimal
&&
value
.
equals
(((
ValueDecimal
)
v
).
value
);
}
}
h2/src/main/org/h2/value/ValueDouble.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
ValueDouble
extends
Value
{
public
static
final
int
PRECISION
=
17
;
private
double
value
;
private
static
final
double
DOUBLE_ZERO
=
0.0
;
private
static
final
double
DOUBLE_ONE
=
1.0
;
private
static
final
ValueDouble
ZERO
=
new
ValueDouble
(
DOUBLE_ZERO
);
private
static
final
ValueDouble
ONE
=
new
ValueDouble
(
DOUBLE_ONE
);
private
ValueDouble
(
double
value
)
{
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
return
ValueDouble
.
get
(
value
+
v2
.
value
);
}
public
Value
subtract
(
Value
v
)
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
return
ValueDouble
.
get
(
value
-
v2
.
value
);
}
public
Value
negate
()
{
return
ValueDouble
.
get
(-
value
);
}
public
Value
multiply
(
Value
v
)
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
return
ValueDouble
.
get
(
value
*
v2
.
value
);
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
if
(
v2
.
value
==
0.0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueDouble
.
get
(
value
/
v2
.
value
);
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
DOUBLE
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueDouble
v
=
(
ValueDouble
)
o
;
if
(
value
==
v
.
value
)
{
return
0
;
}
return
value
>
v
.
value
?
1
:
-
1
;
}
public
int
getSignum
()
{
return
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
}
public
double
getDouble
()
{
return
value
;
}
public
String
getString
()
{
return
String
.
valueOf
(
value
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
getScale
()
{
// TODO value: what is the scale of a double?
return
0
;
}
public
int
hashCode
()
{
long
hash
=
Double
.
doubleToLongBits
(
value
);
return
(
int
)
(
hash
^
(
hash
>>
32
));
}
public
Object
getObject
()
{
return
new
Double
(
value
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setDouble
(
parameterIndex
,
value
);
}
public
static
ValueDouble
get
(
double
d
)
{
if
(
DOUBLE_ZERO
==
d
)
{
return
ZERO
;
}
else
if
(
DOUBLE_ONE
==
d
)
{
return
ONE
;
}
return
(
ValueDouble
)
Value
.
cache
(
new
ValueDouble
(
d
));
}
// public String getJavaString() {
// return getString();
// }
public
int
getDisplaySize
()
{
return
PRECISION
+
2
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueDouble
&&
value
==
((
ValueDouble
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueFloat.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
ValueFloat
extends
Value
{
public
static
final
int
PRECISION
=
7
;
private
float
value
;
private
static
final
float
FLOAT_ZERO
=
0.0
F
;
private
static
final
float
FLOAT_ONE
=
1.0
F
;
private
static
final
ValueFloat
ZERO
=
new
ValueFloat
(
FLOAT_ZERO
);
private
static
final
ValueFloat
ONE
=
new
ValueFloat
(
FLOAT_ONE
);
private
ValueFloat
(
float
value
)
{
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
return
ValueFloat
.
get
(
value
+
v2
.
value
);
}
public
Value
subtract
(
Value
v
)
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
return
ValueFloat
.
get
(
value
-
v2
.
value
);
}
public
Value
negate
()
{
return
ValueFloat
.
get
(-
value
);
}
public
Value
multiply
(
Value
v
)
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
return
ValueFloat
.
get
(
value
*
v2
.
value
);
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
if
(
v2
.
value
==
0.0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueFloat
.
get
(
value
/
v2
.
value
);
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
FLOAT
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueFloat
v
=
(
ValueFloat
)
o
;
if
(
value
==
v
.
value
)
{
return
0
;
}
return
value
>
v
.
value
?
1
:
-
1
;
}
public
int
getSignum
()
{
return
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
}
public
float
getFloat
()
{
return
value
;
}
public
String
getString
()
{
return
String
.
valueOf
(
value
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
getScale
()
{
// TODO value: what is the scale of a float?
return
0
;
}
public
int
hashCode
()
{
long
hash
=
Float
.
floatToIntBits
(
value
);
return
(
int
)
(
hash
^
(
hash
>>
32
));
}
public
Object
getObject
()
{
return
new
Float
(
value
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setFloat
(
parameterIndex
,
value
);
}
public
static
ValueFloat
get
(
float
d
)
{
if
(
FLOAT_ZERO
==
d
)
{
return
ZERO
;
}
else
if
(
FLOAT_ONE
==
d
)
{
return
ONE
;
}
return
(
ValueFloat
)
Value
.
cache
(
new
ValueFloat
(
d
));
}
// public String getJavaString() {
// return getString();
// }
public
int
getDisplaySize
()
{
return
PRECISION
+
2
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueFloat
&&
value
==
((
ValueFloat
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueInt.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
ValueInt
extends
Value
{
public
static
final
int
PRECISION
=
10
;
private
int
value
;
private
static
final
int
STATIC_SIZE
=
100
;
private
static
final
int
DYNAMIC_SIZE
=
256
;
// must be a power of 2
// TODO check performance of final static!
private
static
ValueInt
[]
staticCache
;
private
static
ValueInt
[]
dynamicCache
;
static
{
staticCache
=
new
ValueInt
[
STATIC_SIZE
];
dynamicCache
=
new
ValueInt
[
DYNAMIC_SIZE
];
for
(
int
i
=
0
;
i
<
STATIC_SIZE
;
i
++)
{
staticCache
[
i
]
=
new
ValueInt
(
i
);
}
}
public
static
ValueInt
get
(
int
i
)
{
if
(
i
>=
0
&&
i
<
STATIC_SIZE
)
{
return
staticCache
[
i
];
}
ValueInt
v
=
dynamicCache
[
i
&
DYNAMIC_SIZE
-
1
];
if
(
v
==
null
||
v
.
value
!=
i
)
{
v
=
new
ValueInt
(
i
);
dynamicCache
[
i
&
DYNAMIC_SIZE
-
1
]
=
v
;
}
return
v
;
}
private
ValueInt
(
int
value
)
{
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
throws
SQLException
{
ValueInt
other
=
(
ValueInt
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
((
long
)
value
+
(
long
)
other
.
value
);
}
return
ValueInt
.
get
(
value
+
other
.
value
);
}
private
ValueInt
checkRange
(
long
value
)
throws
SQLException
{
if
(
value
<
Integer
.
MIN_VALUE
||
value
>
Integer
.
MAX_VALUE
)
{
throw
Message
.
getSQLException
(
Message
.
OVERFLOW_FOR_TYPE_1
,
DataType
.
getDataType
(
Value
.
INT
).
name
);
}
else
{
return
ValueInt
.
get
((
int
)
value
);
}
}
public
int
getSignum
()
{
return
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
}
public
Value
negate
()
throws
SQLException
{
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(-(
long
)
value
);
}
return
ValueInt
.
get
(-
value
);
}
public
Value
subtract
(
Value
v
)
throws
SQLException
{
ValueInt
other
=
(
ValueInt
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
((
long
)
value
-
(
long
)
other
.
value
);
}
return
ValueInt
.
get
(
value
-
other
.
value
);
}
public
Value
multiply
(
Value
v
)
throws
SQLException
{
ValueInt
other
=
(
ValueInt
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
((
long
)
value
*
(
long
)
other
.
value
);
}
return
ValueInt
.
get
(
value
*
other
.
value
);
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueInt
other
=
(
ValueInt
)
v
;
if
(
other
.
value
==
0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueInt
.
get
(
value
/
other
.
value
);
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
INT
;
}
public
int
getInt
()
{
return
value
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueInt
v
=
(
ValueInt
)
o
;
if
(
value
==
v
.
value
)
{
return
0
;
}
return
value
>
v
.
value
?
1
:
-
1
;
}
public
String
getString
()
{
return
String
.
valueOf
(
value
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
value
;
}
public
Object
getObject
()
{
return
new
Integer
(
value
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setInt
(
parameterIndex
,
value
);
}
// public String getJavaString() {
// return getString();
// }
public
int
getDisplaySize
()
{
return
PRECISION
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueInt
&&
value
==
((
ValueInt
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueJavaObject.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
org.h2.engine.Constants
;
public
class
ValueJavaObject
extends
ValueBytesBase
{
private
static
final
ValueJavaObject
EMPTY
=
new
ValueJavaObject
(
new
byte
[
0
]);
protected
ValueJavaObject
(
byte
[]
v
)
{
super
(
v
);
}
public
static
ValueJavaObject
get
(
byte
[]
b
)
{
if
(
b
.
length
==
0
)
{
return
EMPTY
;
}
ValueJavaObject
obj
=
new
ValueJavaObject
(
b
);
if
(
b
.
length
>
Constants
.
OBJECT_CACHE_MAX_PER_ELEMENT_SIZE
)
{
return
obj
;
}
return
(
ValueJavaObject
)
Value
.
cache
(
obj
);
}
public
int
getType
()
{
return
Value
.
JAVA_OBJECT
;
}
}
h2/src/main/org/h2/value/ValueLob.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.io.BufferedInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
import
org.h2.store.DataHandler
;
import
org.h2.store.FileStore
;
import
org.h2.store.FileStoreInputStream
;
import
org.h2.store.FileStoreOutputStream
;
import
org.h2.util.ByteUtils
;
import
org.h2.util.FileUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.RandomUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.TypeConverter
;
/**
* @author Thomas
*/
public
class
ValueLob
extends
Value
{
// TODO lob: concatenate function for blob and clob (to create a large blob from pieces)
// and a getpart function (to get it in pieces) and make sure a file is created!
private
int
type
;
private
long
precision
;
private
DataHandler
handler
;
private
int
tableId
;
private
int
objectId
;
private
String
fileName
;
private
boolean
linked
;
private
byte
[]
small
;
private
int
hash
;
private
boolean
compression
;
private
FileStore
tempFile
;
private
ValueLob
(
int
type
,
DataHandler
handler
,
String
fileName
,
int
tableId
,
int
objectId
,
boolean
linked
,
long
precision
,
boolean
compression
)
{
this
.
type
=
type
;
this
.
handler
=
handler
;
this
.
fileName
=
fileName
;
this
.
tableId
=
tableId
;
this
.
objectId
=
objectId
;
this
.
linked
=
linked
;
this
.
precision
=
precision
;
this
.
compression
=
compression
;
}
private
static
ValueLob
copy
(
ValueLob
lob
)
{
ValueLob
copy
=
new
ValueLob
(
lob
.
type
,
lob
.
handler
,
lob
.
fileName
,
lob
.
tableId
,
lob
.
objectId
,
lob
.
linked
,
lob
.
precision
,
lob
.
compression
);
copy
.
small
=
lob
.
small
;
copy
.
hash
=
lob
.
hash
;
return
copy
;
}
private
ValueLob
(
int
type
,
byte
[]
small
)
throws
SQLException
{
this
.
type
=
type
;
this
.
small
=
small
;
if
(
small
!=
null
)
{
if
(
type
==
Value
.
BLOB
)
{
this
.
precision
=
small
.
length
;
}
else
{
this
.
precision
=
getString
().
length
();
}
}
}
public
static
ValueLob
createSmallLob
(
int
type
,
byte
[]
small
)
throws
SQLException
{
return
new
ValueLob
(
type
,
small
);
}
private
static
String
getFileName
(
DataHandler
handler
,
int
tableId
,
int
objectId
)
{
if
(
Constants
.
CHECK
&&
tableId
==
0
&&
objectId
==
0
)
{
throw
Message
.
getInternalError
(
"0 LOB"
);
}
if
(
Constants
.
LOB_FILES_IN_DIRECTORIES
)
{
String
table
=
tableId
<
0
?
".temp"
:
".t"
+
tableId
;
return
getFileNamePrefix
(
handler
.
getDatabasePath
(),
objectId
)
+
table
+
Constants
.
SUFFIX_LOB_FILE
;
}
else
{
return
handler
.
getDatabasePath
()
+
"."
+
tableId
+
"."
+
objectId
+
Constants
.
SUFFIX_LOB_FILE
;
}
}
public
static
ValueLob
open
(
int
type
,
DataHandler
handler
,
int
tableId
,
int
objectId
,
long
precision
,
boolean
compression
)
{
String
fileName
=
getFileName
(
handler
,
tableId
,
objectId
);
return
new
ValueLob
(
type
,
handler
,
fileName
,
tableId
,
objectId
,
true
,
precision
,
compression
);
}
// public static ValueLob createClobFromReader(Reader in, long length) throws SQLException {
// try {
// String s = IOUtils.readStringAndClose(in, (int)length);
// byte[] buff = StringUtils.utf8Encode(s);
// return new ValueLob(CLOB, buff);
// } catch (IOException e) {
// throw Message.convert(e);
// }
// }
// public static ValueLob createBlobFromInputStream(InputStream in, long length) throws SQLException {
// try {
// byte[] buff = IOUtils.readBytesAndClose(in, (int)length);
// return new ValueLob(BLOB, buff);
// } catch (IOException e) {
// throw Message.convert(e);
// }
// }
public
static
ValueLob
createClob
(
Reader
in
,
long
length
,
DataHandler
handler
)
throws
SQLException
{
try
{
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
Value
.
CLOB
)
!=
null
;
long
remaining
=
Long
.
MAX_VALUE
;
if
(
length
>=
0
&&
length
<
remaining
)
{
remaining
=
length
;
}
int
len
=
getBufferSize
(
handler
,
compress
,
remaining
);
char
[]
buff
=
new
char
[
len
];
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
len
=
len
<
0
?
0
:
len
;
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
StringUtils
.
utf8Encode
(
new
String
(
buff
,
0
,
len
));
return
ValueLob
.
createSmallLob
(
Value
.
CLOB
,
small
);
}
ValueLob
lob
=
new
ValueLob
(
Value
.
CLOB
,
null
);
lob
.
createFromReader
(
buff
,
len
,
in
,
remaining
,
handler
);
return
lob
;
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
private
static
int
getBufferSize
(
DataHandler
handler
,
boolean
compress
,
long
remaining
)
{
int
bufferSize
=
compress
?
Constants
.
IO_BUFFER_SIZE_COMPRESS
:
Constants
.
IO_BUFFER_SIZE
;
while
(
bufferSize
<
remaining
&&
bufferSize
<=
handler
.
getMaxLengthInplaceLob
())
{
// the buffer size must be bigger than the inplace lob, otherwise we can't
// know if it must be stored in-place or not
bufferSize
+=
Constants
.
IO_BUFFER_SIZE
;
}
bufferSize
=
(
int
)
Math
.
min
(
remaining
,
bufferSize
);
return
bufferSize
;
}
private
void
createFromReader
(
char
[]
buff
,
int
len
,
Reader
in
,
long
remaining
,
DataHandler
handler
)
throws
SQLException
{
try
{
FileStoreOutputStream
out
=
initLarge
(
handler
);
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
Value
.
CLOB
)
!=
null
;
try
{
while
(
true
)
{
precision
+=
len
;
byte
[]
b
=
StringUtils
.
utf8Encode
(
new
String
(
buff
,
0
,
len
));
out
.
write
(
b
,
0
,
b
.
length
);
remaining
-=
len
;
if
(
remaining
<=
0
)
{
break
;
}
len
=
getBufferSize
(
handler
,
compress
,
remaining
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
if
(
len
<=
0
)
{
break
;
}
}
}
finally
{
out
.
close
();
}
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
private
static
String
getFileNamePrefix
(
String
path
,
int
objectId
)
{
String
name
;
int
f
=
objectId
%
Constants
.
LOB_FILES_PER_DIRECTORY
;
if
(
f
>
0
)
{
name
=
File
.
separator
+
objectId
;
}
else
{
name
=
""
;
}
objectId
/=
Constants
.
LOB_FILES_PER_DIRECTORY
;
while
(
objectId
>
0
)
{
f
=
objectId
%
Constants
.
LOB_FILES_PER_DIRECTORY
;
name
=
File
.
separator
+
f
+
Constants
.
SUFFIX_LOBS_DIRECTORY
+
name
;
objectId
/=
Constants
.
LOB_FILES_PER_DIRECTORY
;
}
name
=
path
+
Constants
.
SUFFIX_LOBS_DIRECTORY
+
name
;
return
name
;
}
private
static
int
getNewObjectId
(
String
path
)
throws
SQLException
{
int
objectId
;
objectId
=
0
;
while
(
true
)
{
String
dir
=
getFileNamePrefix
(
path
,
objectId
);
String
[]
list
=
FileUtils
.
listFiles
(
dir
);
int
fileCount
=
0
;
boolean
[]
used
=
new
boolean
[
Constants
.
LOB_FILES_PER_DIRECTORY
];
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
String
name
=
list
[
i
];
if
(
name
.
endsWith
(
".db"
))
{
name
=
name
.
substring
(
name
.
lastIndexOf
(
File
.
separatorChar
)
+
1
);
String
n
=
name
.
substring
(
0
,
name
.
indexOf
(
'.'
));
int
id
;
try
{
id
=
Integer
.
parseInt
(
n
);
}
catch
(
NumberFormatException
e
)
{
id
=
-
1
;
}
if
(
id
>
0
)
{
fileCount
++;
used
[
id
%
Constants
.
LOB_FILES_PER_DIRECTORY
]
=
true
;
}
}
}
int
fileId
=
-
1
;
if
(
fileCount
<
Constants
.
LOB_FILES_PER_DIRECTORY
)
{
for
(
int
i
=
1
;
i
<
Constants
.
LOB_FILES_PER_DIRECTORY
;
i
++)
{
if
(!
used
[
i
])
{
fileId
=
i
;
break
;
}
}
}
if
(
fileId
>
0
)
{
objectId
+=
fileId
;
break
;
}
else
{
if
(
objectId
>
Integer
.
MAX_VALUE
/
Constants
.
LOB_FILES_PER_DIRECTORY
)
{
// this directory path is full: start from zero
// (this can happen only theoretically, for example if the random number generator is broken)
objectId
=
0
;
}
else
{
// start with 1 (otherwise we don't know the number of directories)
int
dirId
=
RandomUtils
.
nextInt
(
Constants
.
LOB_FILES_PER_DIRECTORY
-
1
)
+
1
;
objectId
=
objectId
*
Constants
.
LOB_FILES_PER_DIRECTORY
;
objectId
+=
dirId
*
Constants
.
LOB_FILES_PER_DIRECTORY
;
}
}
}
return
objectId
;
}
public
static
ValueLob
createBlob
(
InputStream
in
,
long
length
,
DataHandler
handler
)
throws
SQLException
{
try
{
long
remaining
=
Long
.
MAX_VALUE
;
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
Value
.
BLOB
)
!=
null
;
if
(
length
>=
0
&&
length
<
remaining
)
{
remaining
=
length
;
}
int
len
=
getBufferSize
(
handler
,
compress
,
remaining
);
byte
[]
buff
=
new
byte
[
len
];
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
len
=
len
<
0
?
0
:
len
;
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
new
byte
[
len
];
System
.
arraycopy
(
buff
,
0
,
small
,
0
,
len
);
return
ValueLob
.
createSmallLob
(
Value
.
BLOB
,
small
);
}
ValueLob
lob
=
new
ValueLob
(
Value
.
BLOB
,
null
);
lob
.
createFromStream
(
buff
,
len
,
in
,
remaining
,
handler
);
return
lob
;
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
private
FileStoreOutputStream
initLarge
(
DataHandler
handler
)
throws
IOException
,
SQLException
{
this
.
handler
=
handler
;
this
.
tableId
=
0
;
this
.
linked
=
false
;
this
.
precision
=
0
;
this
.
small
=
null
;
this
.
hash
=
0
;
String
compressionAlgorithm
=
handler
.
getLobCompressionAlgorithm
(
type
);
this
.
compression
=
compressionAlgorithm
!=
null
;
synchronized
(
handler
)
{
if
(
Constants
.
LOB_FILES_IN_DIRECTORIES
)
{
objectId
=
getNewObjectId
(
handler
.
getDatabasePath
());
fileName
=
getFileNamePrefix
(
handler
.
getDatabasePath
(),
objectId
)
+
".temp.db"
;
}
else
{
objectId
=
handler
.
allocateObjectId
(
false
,
true
);
fileName
=
handler
.
createTempFile
();
}
tempFile
=
handler
.
openFile
(
fileName
,
false
);
tempFile
.
autoDelete
();
}
FileStoreOutputStream
out
=
new
FileStoreOutputStream
(
tempFile
,
handler
,
compressionAlgorithm
);
return
out
;
}
private
void
createFromStream
(
byte
[]
buff
,
int
len
,
InputStream
in
,
long
remaining
,
DataHandler
handler
)
throws
SQLException
{
try
{
FileStoreOutputStream
out
=
initLarge
(
handler
);
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
Value
.
BLOB
)
!=
null
;
try
{
while
(
true
)
{
precision
+=
len
;
out
.
write
(
buff
,
0
,
len
);
remaining
-=
len
;
if
(
remaining
<=
0
)
{
break
;
}
len
=
getBufferSize
(
handler
,
compress
,
remaining
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
if
(
len
<=
0
)
{
break
;
}
}
}
finally
{
out
.
close
();
}
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
Value
convertTo
(
int
t
)
throws
SQLException
{
if
(
t
==
type
)
{
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
ValueLob
copy
=
ValueLob
.
createClob
(
getReader
(),
-
1
,
handler
);
return
copy
;
}
else
if
(
t
==
Value
.
BLOB
)
{
ValueLob
copy
=
ValueLob
.
createBlob
(
getInputStream
(),
-
1
,
handler
);
return
copy
;
}
return
super
.
convertTo
(
t
);
}
public
void
unlink
(
DataHandler
handler
)
throws
SQLException
{
if
(
linked
&&
fileName
!=
null
)
{
String
temp
;
if
(
Constants
.
LOB_FILES_IN_DIRECTORIES
)
{
temp
=
getFileName
(
handler
,
-
1
,
objectId
);
}
else
{
// just to get a filename - an empty file will be created
temp
=
handler
.
createTempFile
();
}
// delete the temp file
// TODO could there be a race condition? maybe another thread creates the file again?
FileUtils
.
delete
(
temp
);
// rename the current file to the temp file
FileUtils
.
rename
(
fileName
,
temp
);
// FileUtils.deleteOnExit(temp);
tempFile
=
FileStore
.
open
(
handler
,
temp
,
null
);
tempFile
.
autoDelete
();
tempFile
.
closeSilently
();
fileName
=
temp
;
linked
=
false
;
}
}
public
Value
link
(
DataHandler
handler
,
int
tabId
)
throws
SQLException
{
if
(
fileName
==
null
)
{
this
.
tableId
=
tabId
;
return
this
;
}
if
(
linked
)
{
ValueLob
copy
=
ValueLob
.
copy
(
this
);
if
(
Constants
.
LOB_FILES_IN_DIRECTORIES
)
{
copy
.
objectId
=
getNewObjectId
(
handler
.
getDatabasePath
());
}
else
{
copy
.
objectId
=
handler
.
allocateObjectId
(
false
,
true
);
}
copy
.
tableId
=
tabId
;
String
live
=
getFileName
(
handler
,
copy
.
tableId
,
copy
.
objectId
);
FileUtils
.
copy
(
fileName
,
live
);
copy
.
fileName
=
live
;
copy
.
linked
=
true
;
return
copy
;
}
if
(!
linked
)
{
this
.
tableId
=
tabId
;
String
live
=
getFileName
(
handler
,
tableId
,
objectId
);
tempFile
.
stopAutoDelete
();
tempFile
=
null
;
FileUtils
.
rename
(
fileName
,
live
);
fileName
=
live
;
linked
=
true
;
}
return
this
;
}
public
int
getTableId
()
{
return
tableId
;
}
public
int
getObjectId
()
{
return
objectId
;
}
public
int
getType
()
{
return
type
;
}
public
long
getPrecision
()
{
return
precision
;
}
public
String
getString
()
throws
SQLException
{
int
len
=
precision
>
Integer
.
MAX_VALUE
||
precision
==
0
?
Integer
.
MAX_VALUE
:
(
int
)
precision
;
try
{
if
(
type
==
Value
.
CLOB
)
{
if
(
small
!=
null
)
{
return
StringUtils
.
utf8Decode
(
small
);
}
return
IOUtils
.
readStringAndClose
(
getReader
(),
len
);
}
else
{
byte
[]
buff
;
if
(
small
!=
null
)
{
buff
=
small
;
}
else
{
buff
=
IOUtils
.
readBytesAndClose
(
getInputStream
(),
len
);
}
return
ByteUtils
.
convertBytesToString
(
buff
);
}
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
byte
[]
getBytes
()
throws
SQLException
{
if
(
small
!=
null
)
{
return
small
;
}
try
{
return
IOUtils
.
readBytesAndClose
(
getInputStream
(),
Integer
.
MAX_VALUE
);
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
}
}
public
int
hashCode
()
{
if
(
hash
==
0
)
{
try
{
hash
=
ByteUtils
.
getByteArrayHash
(
getBytes
());
}
catch
(
SQLException
e
)
{
// TODO hash code for lob: should not ignore exception
}
}
return
hash
;
}
protected
int
compareSecure
(
Value
v
,
CompareMode
mode
)
throws
SQLException
{
if
(
type
==
Value
.
CLOB
)
{
int
c
=
getString
().
compareTo
(
v
.
getString
());
return
c
==
0
?
0
:
(
c
<
0
?
-
1
:
1
);
}
else
{
byte
[]
v2
=
v
.
getBytes
();
return
ByteUtils
.
compareNotNull
(
getBytes
(),
v2
);
}
}
public
Object
getObject
()
throws
SQLException
{
if
(
type
==
Value
.
CLOB
)
{
return
getReader
();
}
else
{
return
getInputStream
();
}
}
public
Reader
getReader
()
throws
SQLException
{
return
TypeConverter
.
getReader
(
getInputStream
());
}
public
InputStream
getInputStream
()
throws
SQLException
{
if
(
fileName
==
null
)
{
return
new
ByteArrayInputStream
(
small
);
}
FileStore
store
=
handler
.
openFile
(
fileName
,
true
);
return
new
BufferedInputStream
(
new
FileStoreInputStream
(
store
,
handler
,
compression
),
Constants
.
IO_BUFFER_SIZE
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
long
p
=
getPrecision
();
// TODO test if setBinaryStream with -1 works for other databases a well
if
(
p
>
Integer
.
MAX_VALUE
||
p
<=
0
)
{
p
=
-
1
;
}
if
(
type
==
Value
.
BLOB
)
{
prep
.
setBinaryStream
(
parameterIndex
,
getInputStream
(),
(
int
)
p
);
}
else
{
prep
.
setCharacterStream
(
parameterIndex
,
getReader
(),
(
int
)
p
);
}
}
public
String
getSQL
()
{
try
{
String
s
;
if
(
type
==
Value
.
CLOB
)
{
s
=
getString
();
return
StringUtils
.
quoteStringSQL
(
s
);
}
else
{
byte
[]
buff
=
getBytes
();
s
=
ByteUtils
.
convertBytesToString
(
buff
);
return
"X'"
+
s
+
"'"
;
}
}
catch
(
SQLException
e
)
{
throw
Message
.
convertToInternal
(
e
);
}
}
public
byte
[]
getSmall
()
{
return
small
;
}
// public String getJavaString() {
// // TODO value: maybe use another trick (at least the size should be ok?)
// return StringUtils.quoteJavaString(getSQL());
// }
public
int
getDisplaySize
()
{
// TODO displaysize of lob?
return
40
;
}
protected
boolean
isEqual
(
Value
v
)
{
try
{
return
compareSecure
(
v
,
null
)
==
0
;
}
catch
(
SQLException
e
)
{
// TODO exceptions: improve concept, maybe remove throws SQLException almost everywhere
throw
Message
.
getInternalError
(
"compare"
,
e
);
}
}
public
void
convertToFileIfRequired
(
DataHandler
handler
)
throws
SQLException
{
if
(
Constants
.
AUTO_CONVERT_LOB_TO_FILES
&&
small
!=
null
&&
small
.
length
>
handler
.
getMaxLengthInplaceLob
())
{
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
type
)
!=
null
;
int
len
=
getBufferSize
(
handler
,
compress
,
Long
.
MAX_VALUE
);
int
tabId
=
tableId
;
if
(
type
==
Value
.
BLOB
)
{
createFromStream
(
new
byte
[
len
],
0
,
getInputStream
(),
Long
.
MAX_VALUE
,
handler
);
}
else
{
createFromReader
(
new
char
[
len
],
0
,
getReader
(),
Long
.
MAX_VALUE
,
handler
);
}
Value
v2
=
link
(
handler
,
tabId
);
if
(
Constants
.
CHECK
&&
v2
!=
this
)
{
throw
Message
.
getInternalError
();
}
}
}
public
static
void
removeAllForTable
(
DataHandler
handler
,
int
tableId
)
throws
SQLException
{
if
(
Constants
.
LOB_FILES_IN_DIRECTORIES
)
{
String
dir
=
getFileNamePrefix
(
handler
.
getDatabasePath
(),
0
);
removeAllForTable
(
handler
,
dir
,
tableId
);
}
else
{
String
prefix
=
handler
.
getDatabasePath
();
String
dir
=
FileUtils
.
getParent
(
prefix
);
String
[]
list
=
FileUtils
.
listFiles
(
dir
);
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
String
name
=
list
[
i
];
if
(
name
.
startsWith
(
prefix
+
"."
+
tableId
)
&&
name
.
endsWith
(
".lob.db"
))
{
FileUtils
.
delete
(
name
);
}
}
}
}
private
static
void
removeAllForTable
(
DataHandler
handler
,
String
dir
,
int
tableId
)
throws
SQLException
{
String
[]
list
=
FileUtils
.
listFiles
(
dir
);
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
if
(
FileUtils
.
isDirectory
(
list
[
i
]))
{
removeAllForTable
(
handler
,
list
[
i
],
tableId
);
}
else
{
String
name
=
list
[
i
];
if
(
name
.
endsWith
(
".t"
+
tableId
+
".lob.db"
))
{
FileUtils
.
delete
(
name
);
}
}
}
}
public
boolean
useCompression
()
{
return
compression
;
}
}
h2/src/main/org/h2/value/ValueLong.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.math.BigInteger
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
public
class
ValueLong
extends
Value
{
private
long
value
;
public
static
final
int
PRECISION
=
19
;
private
static
final
int
STATIC_SIZE
=
10
;
private
static
ValueLong
[]
cache
;
private
static
final
BigInteger
MIN
=
new
BigInteger
(
""
+
Long
.
MIN_VALUE
);
private
static
final
BigInteger
MAX
=
new
BigInteger
(
""
+
Long
.
MAX_VALUE
);
static
{
cache
=
new
ValueLong
[
STATIC_SIZE
];
for
(
int
i
=
0
;
i
<
STATIC_SIZE
;
i
++)
{
cache
[
i
]
=
new
ValueLong
(
i
);
}
}
private
ValueLong
(
long
value
)
{
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
throws
SQLException
{
ValueLong
other
=
(
ValueLong
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
long
result
=
value
+
other
.
value
;
int
sv
=
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
int
so
=
other
.
value
==
0
?
0
:
(
other
.
value
<
0
?
-
1
:
1
);
int
sr
=
result
==
0
?
0
:
(
result
<
0
?
-
1
:
1
);
// if the operands have different signs overflow can not occur
// if the operands have the same sign, and the result has a different sign, then it is an overflow
// it can not be an overflow when one of the operands is 0
if
(
sv
!=
so
||
sr
==
so
||
sv
==
0
||
so
==
0
)
{
return
ValueLong
.
get
(
result
);
}
throw
getOverflow
();
}
return
ValueLong
.
get
(
value
+
other
.
value
);
}
public
int
getSignum
()
{
return
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
}
public
Value
negate
()
throws
SQLException
{
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
if
(
value
==
Long
.
MIN_VALUE
)
{
throw
getOverflow
();
}
}
return
ValueLong
.
get
(-
value
);
}
private
SQLException
getOverflow
()
{
return
Message
.
getSQLException
(
Message
.
OVERFLOW_FOR_TYPE_1
,
DataType
.
getDataType
(
Value
.
LONG
).
name
);
}
public
Value
subtract
(
Value
v
)
throws
SQLException
{
ValueLong
other
=
(
ValueLong
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
int
sv
=
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
int
so
=
other
.
value
==
0
?
0
:
(
other
.
value
<
0
?
-
1
:
1
);
// if the operands have the same sign, then overflow can not occur
// if the second operand is 0, then overflow can not occur
if
(
sv
==
so
||
so
==
0
)
{
return
ValueLong
.
get
(
value
-
other
.
value
);
}
// now, if the other value is Long.MIN_VALUE, it must be an overflow
// x - Long.MIN_VALUE overflows for x>=0
return
add
(
other
.
negate
());
}
return
ValueLong
.
get
(
value
-
other
.
value
);
}
private
boolean
isInteger
(
long
a
)
{
return
a
>=
Integer
.
MIN_VALUE
&&
a
<=
Integer
.
MAX_VALUE
;
}
public
Value
multiply
(
Value
v
)
throws
SQLException
{
ValueLong
other
=
(
ValueLong
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
long
result
=
value
*
other
.
value
;
if
(
value
==
0
||
value
==
1
||
other
.
value
==
0
||
other
.
value
==
1
)
{
return
ValueLong
.
get
(
result
);
}
if
(
isInteger
(
value
)
&&
isInteger
(
other
.
value
))
{
return
ValueLong
.
get
(
result
);
}
// just checking one case is not enough: Long.MIN_VALUE * -1
// probably this is correct but I'm not sure
// if(result / value == other.value && result / other.value == value) {
// return ValueLong.get(result);
//}
BigInteger
bv
=
new
BigInteger
(
""
+
value
);
BigInteger
bo
=
new
BigInteger
(
""
+
other
.
value
);
BigInteger
br
=
bv
.
multiply
(
bo
);
if
(
br
.
compareTo
(
MIN
)
<
0
||
br
.
compareTo
(
MAX
)
>
0
)
{
throw
getOverflow
();
}
return
ValueLong
.
get
(
br
.
longValue
());
}
return
ValueLong
.
get
(
value
*
other
.
value
);
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueLong
other
=
(
ValueLong
)
v
;
if
(
other
.
value
==
0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueLong
.
get
(
value
/
other
.
value
);
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
LONG
;
}
public
long
getLong
()
{
return
value
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueLong
v
=
(
ValueLong
)
o
;
if
(
value
==
v
.
value
)
{
return
0
;
}
return
value
>
v
.
value
?
1
:
-
1
;
}
public
String
getString
()
{
return
String
.
valueOf
(
value
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
(
int
)
(
value
^
(
value
>>
32
));
}
public
Object
getObject
()
{
return
new
Long
(
value
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setLong
(
parameterIndex
,
value
);
}
public
static
ValueLong
get
(
long
i
)
{
if
(
i
>=
0
&&
i
<
STATIC_SIZE
)
{
return
cache
[(
int
)
i
];
}
return
(
ValueLong
)
Value
.
cache
(
new
ValueLong
(
i
));
}
// public String getJavaString() {
// return getString();
// }
public
int
getDisplaySize
()
{
return
PRECISION
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueLong
&&
value
==
((
ValueLong
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueNull.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.math.BigDecimal
;
import
java.sql.Date
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
org.h2.message.Message
;
/**
* @author Thomas
*/
public
class
ValueNull
extends
Value
{
public
static
final
ValueNull
INSTANCE
=
new
ValueNull
();
public
static
final
ValueNull
DELETED
=
new
ValueNull
();
public
static
final
int
PRECISION
=
1
;
private
ValueNull
()
{
}
public
String
getSQL
()
{
return
"NULL"
;
}
public
int
getType
()
{
return
Value
.
NULL
;
}
public
String
getString
()
{
return
null
;
}
public
Boolean
getBoolean
()
throws
SQLException
{
return
null
;
}
public
Date
getDate
()
throws
SQLException
{
return
null
;
}
public
Time
getTime
()
throws
SQLException
{
return
null
;
}
public
Timestamp
getTimestamp
()
throws
SQLException
{
return
null
;
}
public
byte
[]
getBytes
()
throws
SQLException
{
return
null
;
}
public
byte
getByte
()
throws
SQLException
{
return
0
;
}
public
short
getShort
()
throws
SQLException
{
return
0
;
}
public
BigDecimal
getBigDecimal
()
throws
SQLException
{
return
null
;
}
public
double
getDouble
()
throws
SQLException
{
return
0.0
;
}
public
float
getFloat
()
throws
SQLException
{
return
0.0
F
;
}
public
int
getInt
()
throws
SQLException
{
return
0
;
}
public
long
getLong
()
throws
SQLException
{
return
0
;
}
public
InputStream
getInputStream
()
throws
SQLException
{
return
null
;
}
public
Reader
getReader
()
throws
SQLException
{
return
null
;
}
public
Value
convertTo
(
int
type
)
throws
SQLException
{
return
this
;
}
protected
int
compareSecure
(
Value
v
,
CompareMode
mode
)
{
throw
Message
.
getInternalError
(
"compare null"
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
0
;
}
public
Object
getObject
()
{
return
null
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setNull
(
parameterIndex
,
DataType
.
convertTypeToSQLType
(
Value
.
NULL
));
}
// public String getJavaString() {
// return "null";
// }
public
int
getDisplaySize
()
{
return
"null"
.
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
==
ValueNull
.
INSTANCE
;
}
}
h2/src/main/org/h2/value/ValueResultSet.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.ResultSetMetaData
;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
import
org.h2.tools.SimpleResultSet
;
public
class
ValueResultSet
extends
Value
{
private
ResultSet
result
;
public
static
ValueResultSet
get
(
ResultSet
rs
)
throws
SQLException
{
ValueResultSet
val
=
new
ValueResultSet
();
val
.
result
=
rs
;
return
val
;
}
public
static
ValueResultSet
getCopy
(
ResultSet
rs
,
int
maxrows
)
throws
SQLException
{
ValueResultSet
val
=
new
ValueResultSet
();
ResultSetMetaData
meta
=
rs
.
getMetaData
();
int
columnCount
=
meta
.
getColumnCount
();
SimpleResultSet
simple
=
new
SimpleResultSet
();
val
.
result
=
simple
;
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
String
name
=
meta
.
getColumnLabel
(
i
+
1
);
int
sqlType
=
meta
.
getColumnType
(
i
+
1
);
int
precision
=
meta
.
getPrecision
(
i
+
1
);
int
scale
=
meta
.
getScale
(
i
+
1
);
simple
.
addColumn
(
name
,
sqlType
,
precision
,
scale
);
}
for
(
int
i
=
0
;
i
<
maxrows
&&
rs
.
next
();
i
++)
{
Object
[]
list
=
new
Object
[
columnCount
];
for
(
int
j
=
0
;
j
<
columnCount
;
j
++)
{
list
[
j
]
=
rs
.
getObject
(
j
+
1
);
}
simple
.
addRow
(
list
);
}
return
val
;
}
public
int
getType
()
{
return
Value
.
RESULT_SET
;
}
public
long
getPrecision
()
{
return
0
;
}
public
int
getDisplaySize
()
{
// it doesn't make sense to calculate this
return
100
;
}
public
String
getString
()
throws
SQLException
{
StringBuffer
buff
=
new
StringBuffer
();
buff
.
append
(
"("
);
result
.
beforeFirst
();
ResultSetMetaData
meta
=
result
.
getMetaData
();
int
columnCount
=
meta
.
getColumnCount
();
for
(
int
i
=
0
;
result
.
next
();
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
", "
);
}
buff
.
append
(
'('
);
for
(
int
j
=
0
;
j
<
columnCount
;
j
++)
{
if
(
j
>
0
)
{
buff
.
append
(
", "
);
}
int
t
=
DataType
.
convertSQLTypeToValueType
(
meta
.
getColumnType
(
j
+
1
));
Value
v
=
DataType
.
readValue
(
null
,
result
,
j
+
1
,
t
);
buff
.
append
(
v
.
getString
());
}
buff
.
append
(
')'
);
}
buff
.
append
(
")"
);
result
.
beforeFirst
();
return
buff
.
toString
();
}
protected
int
compareSecure
(
Value
v
,
CompareMode
mode
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
false
;
}
public
Object
getObject
()
throws
SQLException
{
return
result
;
}
public
ResultSet
getResultSet
()
{
return
result
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
throw
Message
.
getUnsupportedException
();
}
public
String
getSQL
()
{
return
""
;
}
}
h2/src/main/org/h2/value/ValueShort.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.message.Message
;
public
class
ValueShort
extends
Value
{
public
static
final
int
PRECISION
=
5
;
private
short
value
;
private
ValueShort
(
short
value
)
{
this
.
value
=
value
;
}
public
Value
add
(
Value
v
)
throws
SQLException
{
ValueShort
other
=
(
ValueShort
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(
value
+
other
.
value
);
}
return
ValueShort
.
get
((
short
)
(
value
+
other
.
value
));
}
private
ValueShort
checkRange
(
int
value
)
throws
SQLException
{
if
(
value
<
Short
.
MIN_VALUE
||
value
>
Short
.
MAX_VALUE
)
{
throw
Message
.
getSQLException
(
Message
.
OVERFLOW_FOR_TYPE_1
,
DataType
.
getDataType
(
Value
.
SHORT
).
name
);
}
else
{
return
ValueShort
.
get
((
short
)
value
);
}
}
public
int
getSignum
()
{
return
value
==
0
?
0
:
(
value
<
0
?
-
1
:
1
);
}
public
Value
negate
()
throws
SQLException
{
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(-(
int
)
value
);
}
return
ValueShort
.
get
((
short
)
(-
value
));
}
public
Value
subtract
(
Value
v
)
throws
SQLException
{
ValueShort
other
=
(
ValueShort
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(
value
-
other
.
value
);
}
return
ValueShort
.
get
((
short
)
(
value
-
other
.
value
));
}
public
Value
multiply
(
Value
v
)
throws
SQLException
{
ValueShort
other
=
(
ValueShort
)
v
;
if
(
Constants
.
OVERFLOW_EXCEPTIONS
)
{
return
checkRange
(
value
*
other
.
value
);
}
return
ValueShort
.
get
((
short
)
(
value
*
other
.
value
));
}
public
Value
divide
(
Value
v
)
throws
SQLException
{
ValueShort
other
=
(
ValueShort
)
v
;
if
(
other
.
value
==
0
)
{
throw
Message
.
getSQLException
(
Message
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueShort
.
get
((
short
)
(
value
/
other
.
value
));
}
public
String
getSQL
()
{
return
getString
();
}
public
int
getType
()
{
return
Value
.
SHORT
;
}
public
short
getShort
()
{
return
value
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueShort
v
=
(
ValueShort
)
o
;
if
(
value
==
v
.
value
)
{
return
0
;
}
return
value
>
v
.
value
?
1
:
-
1
;
}
public
String
getString
()
{
return
String
.
valueOf
(
value
);
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
value
;
}
public
Object
getObject
()
{
return
new
Short
(
value
);
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setShort
(
parameterIndex
,
value
);
}
public
static
ValueShort
get
(
short
i
)
{
return
(
ValueShort
)
Value
.
cache
(
new
ValueShort
(
i
));
}
// public String getJavaString() {
// return getString();
// }
public
int
getDisplaySize
()
{
return
PRECISION
;
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueShort
&&
value
==
((
ValueShort
)
v
).
value
;
}
}
h2/src/main/org/h2/value/ValueString.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
org.h2.engine.Constants
;
import
org.h2.util.StringCache
;
/**
* @author Thomas
*/
public
class
ValueString
extends
ValueStringBase
{
private
static
final
ValueString
EMPTY
=
new
ValueString
(
""
);
protected
ValueString
(
String
value
)
{
super
(
value
);
}
public
int
getType
()
{
return
Value
.
STRING
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueString
v
=
(
ValueString
)
o
;
return
mode
.
compareString
(
value
,
v
.
value
,
false
);
}
public
int
hashCode
()
{
// TODO hash performance: could build a quicker hash by hashing the size and a few characters
return
value
.
hashCode
();
// proposed code:
// private int hash = 0;
//
// public int hashCode() {
// int h = hash;
// if (h == 0) {
// String s = value;
// int l = s.length();
// if (l > 0) {
// if (l < 16)
// h = s.hashCode();
// else {
// h = l;
// for (int i = 1; i <= l; i <<= 1)
// h = 31 * (31 * h + s.charAt(i - 1)) + s.charAt(l - i);
// }
// hash = h;
// }
// }
// return h;
// }
}
public
static
ValueString
get
(
String
s
)
{
if
(
s
.
length
()
==
0
)
{
return
EMPTY
;
}
ValueString
obj
=
new
ValueString
(
StringCache
.
get
(
s
));
if
(
s
.
length
()
>
Constants
.
OBJECT_CACHE_MAX_PER_ELEMENT_SIZE
)
{
return
obj
;
}
return
(
ValueString
)
Value
.
cache
(
obj
);
// this saves memory, but is really slow
// return new ValueString(s.intern());
}
}
h2/src/main/org/h2/value/ValueStringBase.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
abstract
class
ValueStringBase
extends
Value
{
protected
String
value
;
protected
ValueStringBase
(
String
value
)
{
this
.
value
=
value
;
}
public
String
getSQL
()
{
return
StringUtils
.
quoteStringSQL
(
value
);
}
public
String
getString
()
{
return
value
;
}
public
long
getPrecision
()
{
return
value
.
length
();
}
public
Object
getObject
()
{
return
value
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setString
(
parameterIndex
,
value
);
}
public
Value
convertPrecision
(
long
precision
)
{
if
(
precision
==
0
||
value
.
length
()
<=
precision
)
{
return
this
;
}
int
p
=
MathUtils
.
convertLongToInt
(
precision
);
return
ValueString
.
get
(
value
.
substring
(
0
,
p
));
}
// public String getJavaString() {
// return StringUtils.quoteJavaString(value);
// }
public
int
getDisplaySize
()
{
return
value
.
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueString
&&
value
.
equals
(((
ValueString
)
v
).
value
);
}
}
h2/src/main/org/h2/value/ValueStringIgnoreCase.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
org.h2.engine.Constants
;
import
org.h2.util.StringCache
;
public
class
ValueStringIgnoreCase
extends
ValueStringBase
{
private
static
final
ValueStringIgnoreCase
EMPTY
=
new
ValueStringIgnoreCase
(
""
);
private
int
hash
;
protected
ValueStringIgnoreCase
(
String
value
)
{
super
(
value
);
}
public
int
getType
()
{
return
Value
.
STRING_IGNORECASE
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueStringIgnoreCase
v
=
(
ValueStringIgnoreCase
)
o
;
return
mode
.
compareString
(
value
,
v
.
value
,
true
);
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueStringBase
&&
value
.
equalsIgnoreCase
(((
ValueStringBase
)
v
).
value
);
}
public
int
hashCode
()
{
if
(
hash
==
0
)
{
// this is locale sensitive
hash
=
value
.
toUpperCase
().
hashCode
();
}
return
hash
;
}
public
static
ValueStringIgnoreCase
get
(
String
s
)
{
if
(
s
.
length
()
==
0
)
{
return
EMPTY
;
}
ValueStringIgnoreCase
obj
=
new
ValueStringIgnoreCase
(
StringCache
.
get
(
s
));
if
(
s
.
length
()
>
Constants
.
OBJECT_CACHE_MAX_PER_ELEMENT_SIZE
)
{
return
obj
;
}
ValueStringIgnoreCase
cache
=
(
ValueStringIgnoreCase
)
Value
.
cache
(
obj
);
// the cached object could have the wrong case (it would still be 'equal', but we don't like to store it)
if
(
cache
.
value
.
equals
(
s
))
{
return
cache
;
}
else
{
return
obj
;
}
}
}
h2/src/main/org/h2/value/ValueTime.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.util.Calendar
;
import
org.h2.message.Message
;
public
class
ValueTime
extends
Value
{
public
static
final
int
PRECISION
=
6
;
private
Time
value
;
private
ValueTime
(
Time
value
)
{
// this class is mutable - must copy the object
Calendar
cal
=
Calendar
.
getInstance
();
cal
.
setTime
(
value
);
// TODO gcj: required so that the millis are calculated?
cal
.
get
(
Calendar
.
HOUR_OF_DAY
);
cal
.
set
(
1970
,
0
,
1
);
this
.
value
=
new
Time
(
cal
.
getTime
().
getTime
());
}
public
static
Time
parseTime
(
String
s
)
throws
SQLException
{
return
(
Time
)
DataType
.
parseDateTime
(
s
,
Value
.
TIME
,
Message
.
TIME_CONSTANT_1
);
}
public
Time
getTime
()
{
// this class is mutable - must copy the object
return
(
Time
)
value
.
clone
();
}
public
String
getSQL
()
{
return
"TIME '"
+
getString
()
+
"'"
;
}
public
int
getType
()
{
return
Value
.
TIME
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueTime
v
=
(
ValueTime
)
o
;
int
c
=
value
.
compareTo
(
v
.
value
);
return
c
==
0
?
0
:
(
c
<
0
?
-
1
:
1
);
}
public
String
getString
()
{
return
value
.
toString
();
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
hashCode
()
{
return
value
.
hashCode
();
}
public
Object
getObject
()
{
return
getTime
();
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setTime
(
parameterIndex
,
value
);
}
public
static
ValueTime
get
(
Time
date
)
{
return
(
ValueTime
)
Value
.
cache
(
new
ValueTime
(
date
));
}
// public String getJavaString() {
// return "Time.valueOf(\"" + toString() + "\")";
// }
public
int
getDisplaySize
()
{
return
"23:59:59"
.
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueTime
&&
value
.
equals
(((
ValueTime
)
v
).
value
);
}
}
h2/src/main/org/h2/value/ValueTimestamp.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.math.BigDecimal
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.Timestamp
;
import
org.h2.message.Message
;
import
org.h2.util.MathUtils
;
public
class
ValueTimestamp
extends
Value
{
public
static
final
int
PRECISION
=
23
;
public
static
final
int
DEFAULT_SCALE
=
10
;
private
Timestamp
value
;
private
ValueTimestamp
(
Timestamp
value
)
{
// this class is mutable - must copy the object
this
.
value
=
(
Timestamp
)
value
.
clone
();
}
public
Timestamp
getTimestamp
()
{
// TODO performance: clone not always required
// this class is mutable - must copy the object
return
(
Timestamp
)
value
.
clone
();
}
public
String
getSQL
()
{
return
"TIMESTAMP '"
+
getString
()
+
"'"
;
}
public
static
Timestamp
parseTimestamp
(
String
s
)
throws
SQLException
{
return
(
Timestamp
)
DataType
.
parseDateTime
(
s
,
Value
.
TIMESTAMP
,
Message
.
TIMESTAMP_CONSTANT_1
);
}
public
int
getType
()
{
return
Value
.
TIMESTAMP
;
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueTimestamp
v
=
(
ValueTimestamp
)
o
;
int
c
=
value
.
compareTo
(
v
.
value
);
return
c
==
0
?
0
:
(
c
<
0
?
-
1
:
1
);
}
public
String
getString
()
{
return
value
.
toString
();
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
getScale
()
{
return
DEFAULT_SCALE
;
}
public
int
hashCode
()
{
return
value
.
hashCode
();
}
public
Object
getObject
()
{
// this class is mutable - must copy the object
return
getTimestamp
();
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setTimestamp
(
parameterIndex
,
value
);
}
public
static
ValueTimestamp
get
(
Timestamp
date
)
{
return
(
ValueTimestamp
)
Value
.
cache
(
new
ValueTimestamp
(
date
));
}
public
Value
convertScale
(
boolean
onlyToSmallerScale
,
int
targetScale
)
throws
SQLException
{
if
(
targetScale
<
0
||
targetScale
>
DEFAULT_SCALE
)
{
// TODO convertScale for Timestamps: may throw an exception?
throw
Message
.
getInvalidValueException
(
""
+
targetScale
,
"scale"
);
}
int
nanos
=
value
.
getNanos
();
BigDecimal
bd
=
new
BigDecimal
(
""
+
nanos
);
bd
=
bd
.
movePointLeft
(
9
);
bd
=
MathUtils
.
setScale
(
bd
,
targetScale
);
bd
=
bd
.
movePointRight
(
9
);
int
n2
=
bd
.
intValue
();
if
(
n2
==
nanos
)
{
return
this
;
}
long
t
=
value
.
getTime
();
while
(
n2
>=
1000000000
)
{
t
+=
1000
;
n2
-=
1000000000
;
}
Timestamp
t2
=
new
Timestamp
(
t
);
t2
.
setNanos
(
n2
);
return
ValueTimestamp
.
get
(
t2
);
}
// public String getJavaString() {
// return "Timestamp.valueOf(\"" + toString() + "\")";
// }
public
int
getDisplaySize
()
{
return
"2001-01-01 23:59:59"
.
length
();
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueTimestamp
&&
value
.
equals
(((
ValueTimestamp
)
v
).
value
);
}
}
h2/src/main/org/h2/value/ValueUuid.java
0 → 100644
浏览文件 @
3d2cd051
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.util.ByteUtils
;
import
org.h2.util.RandomUtils
;
import
org.h2.util.StringUtils
;
public
class
ValueUuid
extends
Value
{
public
static
final
int
PRECISION
=
36
;
private
long
high
,
low
;
private
ValueUuid
(
long
high
,
long
low
)
{
this
.
high
=
high
;
this
.
low
=
low
;
}
public
int
hashCode
()
{
return
(
int
)((
high
>>>
32
)
^
high
^
(
low
>>>
32
)
^
low
);
}
public
static
ValueUuid
getNewRandom
()
{
long
high
=
RandomUtils
.
getSecureLong
();
long
low
=
RandomUtils
.
getSecureLong
();
high
=
(
high
&
(~
0xf000
L
))
|
0x4000
L
;
// version 4 (random)
low
=
(
low
&
0x3fffffffffffffff
L
)
|
0x8000000000000000
L
;
// variant (Leach-Salz)
return
new
ValueUuid
(
high
,
low
);
}
public
static
ValueUuid
get
(
byte
[]
binary
)
{
if
(
binary
.
length
<
32
)
{
return
get
(
ByteUtils
.
convertBytesToString
(
binary
));
}
long
high
=
ByteUtils
.
readLong
(
binary
,
0
);
long
low
=
ByteUtils
.
readLong
(
binary
,
16
);
return
(
ValueUuid
)
Value
.
cache
(
new
ValueUuid
(
high
,
low
));
}
public
static
ValueUuid
get
(
long
high
,
long
low
)
{
return
(
ValueUuid
)
Value
.
cache
(
new
ValueUuid
(
high
,
low
));
}
public
static
ValueUuid
get
(
String
s
)
{
long
high
=
0
,
low
=
0
;
int
i
=
0
;
for
(
int
j
=
0
;
i
<
s
.
length
()
&&
j
<
16
;
i
++)
{
char
ch
=
s
.
charAt
(
i
);
if
(
ch
!=
'-'
)
{
high
=
(
high
<<
4
)
|
Character
.
digit
(
ch
,
16
);
j
++;
}
}
for
(
int
j
=
0
;
i
<
s
.
length
()
&&
j
<
16
;
i
++)
{
char
ch
=
s
.
charAt
(
i
);
if
(
ch
!=
'-'
)
{
low
=
(
low
<<
4
)
|
Character
.
digit
(
ch
,
16
);
j
++;
}
}
return
(
ValueUuid
)
Value
.
cache
(
new
ValueUuid
(
high
,
low
));
}
public
String
getSQL
()
{
return
StringUtils
.
quoteStringSQL
(
getString
());
}
public
int
getType
()
{
return
Value
.
UUID
;
}
public
long
getPrecision
()
{
return
PRECISION
;
}
public
int
getDisplaySize
()
{
return
0
;
}
private
void
appendHex
(
StringBuffer
buff
,
long
x
,
int
bytes
)
{
for
(
int
i
=
bytes
*
8
-
4
;
i
>=
0
;
i
-=
8
)
{
buff
.
append
(
Integer
.
toHexString
((
int
)(
x
>>
i
)
&
0xf
));
buff
.
append
(
Integer
.
toHexString
((
int
)(
x
>>
(
i
-
4
))
&
0xf
));
}
}
public
String
getString
()
{
StringBuffer
buff
=
new
StringBuffer
(
36
);
appendHex
(
buff
,
high
>>
32
,
4
);
buff
.
append
(
'-'
);
appendHex
(
buff
,
high
>>
16
,
2
);
buff
.
append
(
'-'
);
appendHex
(
buff
,
high
,
2
);
buff
.
append
(
'-'
);
appendHex
(
buff
,
low
>>
48
,
2
);
buff
.
append
(
'-'
);
appendHex
(
buff
,
low
,
6
);
return
buff
.
toString
();
}
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueUuid
v
=
(
ValueUuid
)
o
;
if
(
high
==
v
.
high
)
{
return
(
low
==
v
.
low
)
?
0
:
(
low
>
v
.
low
?
1
:
-
1
);
}
else
{
return
high
>
v
.
high
?
1
:
-
1
;
}
}
protected
boolean
isEqual
(
Value
v
)
{
return
v
instanceof
ValueUuid
&&
compareSecure
(
v
,
null
)
==
0
;
}
public
Object
getObject
()
{
// TODO needs to be documented
return
new
long
[]{
high
,
low
};
}
public
byte
[]
getBytes
()
{
byte
[]
buff
=
new
byte
[
16
];
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
buff
[
i
]
=
(
byte
)((
high
>>
(
8
*(
8
-
i
)))
&
255
);
buff
[
8
+
i
]
=
(
byte
)((
low
>>
(
8
*(
8
-
i
)))
&
255
);
}
return
buff
;
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setBytes
(
parameterIndex
,
getBytes
());
}
public
long
getHigh
()
{
return
high
;
}
public
long
getLow
()
{
return
low
;
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论