提交 3d2cd051 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 77fe8768
org.h2.Driver
\ No newline at end of file
/*
* 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);
}
}
}
/*
* 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) & 0xffffffffL);
}
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;
}
}
/*
* 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();
}
差异被折叠。
/*
* 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 {
}
}
/*
* 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;
// }
//}
/*
* 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;
}
}
/*
* 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;
}
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;
}
}
差异被折叠。
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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();
// }
}
/*
* 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;
}
}
/*
* 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;
}
}
}
/*
* 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;
}
}
/*
* 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;
}
}
}
}
/*
* 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);
}
}
}
/*
* 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);
// }
// }
}
/*
* 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 &lt; 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;
}
}
/*
* 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);
}
}
/*
* 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;
}
}
/*
* 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
}
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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();
}
}
}
/*
* 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);
}
}
差异被折叠。
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();
}
}
/*
* 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();
}
}
}
/*
* 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();
}
}
/*
* 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;
}
}
/*
* 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;
}
}
差异被折叠。
差异被折叠。
差异被折叠。
/*
* 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;
}
}
差异被折叠。
差异被折叠。
/*
* 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;
}
}
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
/*
* 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;
}
}
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论