提交 96d8c078 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 9a25c1c1
package org.h2.samples;
import java.io.*;
import java.sql.*;
public class SQLInjection {
Connection conn;
Statement stat;
public static void main(String[] args) throws Exception {
new SQLInjection().run("org.h2.Driver",
"jdbc:h2:test", "sa", "sa");
// new SQLInjection().run("org.postgresql.Driver",
// "jdbc:postgresql:jpox2", "sa", "sa");
// new SQLInjection().run("com.mysql.jdbc.Driver",
// "jdbc:mysql://localhost/test", "sa", "sa");
// new SQLInjection().run("org.hsqldb.jdbcDriver",
// "jdbc:hsqldb:test", "sa", "");
// new SQLInjection().run(
// "org.apache.derby.jdbc.EmbeddedDriver",
// "jdbc:derby:test3;create=true", "sa", "sa");
}
void run(String driver, String url, String user, String password) throws Exception {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
stat = conn.createStatement();
try {
stat.execute("DROP TABLE USERS");
} catch (SQLException e) {
// ignore
}
stat.execute("CREATE TABLE USERS(ID INT PRIMARY KEY, " +
"NAME VARCHAR(255), PASSWORD VARCHAR(255))");
stat.execute("INSERT INTO USERS VALUES(1, 'admin', 'super')");
stat.execute("INSERT INTO USERS VALUES(2, 'guest', '123456')");
stat.execute("INSERT INTO USERS VALUES(3, 'test', 'abc')");
// loginByNameInsecure();
if(url.startsWith("jdbc:h2:")) {
// loginStoredProcedureInsecure();
limitRowAccess();
}
// loginByNameSecure();
if(url.startsWith("jdbc:h2:")) {
stat.execute("SET ALLOW_LITERALS NONE");
stat.execute("SET ALLOW_LITERALS NUMBERS");
stat.execute("SET ALLOW_LITERALS ALL");
}
// loginByIdInsecure();
// loginByIdSecure();
try {
stat.execute("DROP TABLE ITEMS");
} catch (SQLException e) {
// ignore
}
stat.execute("CREATE TABLE ITEMS(ID INT PRIMARY KEY, " +
"NAME VARCHAR(255), ACTIVE INT)");
stat.execute("INSERT INTO ITEMS VALUES(0, 'XBox', 0)");
stat.execute("INSERT INTO ITEMS VALUES(1, 'XBox 360', 1)");
stat.execute("INSERT INTO ITEMS VALUES(2, 'PlayStation 1', 0)");
stat.execute("INSERT INTO ITEMS VALUES(3, 'PlayStation 2', 1)");
stat.execute("INSERT INTO ITEMS VALUES(4, 'PlayStation 3', 1)");
listActiveItems();
if(url.startsWith("jdbc:h2:")) {
stat.execute("DROP CONSTANT IF EXISTS TYPE_INACTIVE");
stat.execute("DROP CONSTANT IF EXISTS TYPE_ACTIVE");
stat.execute("CREATE CONSTANT TYPE_INACTIVE VALUE 0");
stat.execute("CREATE CONSTANT TYPE_ACTIVE VALUE 1");
listActiveItemsUsingConstants();
}
// listItemsSortedInsecure();
// listItemsSortedSecure();
if(url.startsWith("jdbc:h2:")) {
listItemsSortedSecureParam();
// storePasswordHashWithSalt();
}
conn.close();
}
void loginByNameInsecure() throws Exception {
System.out.println("Insecure Systems Inc. - login");
String name = input("Name?");
String password = input("Password?");
ResultSet rs = stat.executeQuery("SELECT * FROM USERS WHERE " +
"NAME='" + name + "' AND PASSWORD='" + password + "'");
if (rs.next()) {
System.out.println("Welcome!");
} else {
System.out.println("Access denied!");
}
}
public static ResultSet getUser(Connection conn, String userName, String password) throws Exception {
PreparedStatement prep = conn.prepareStatement(
"SELECT * FROM USERS WHERE NAME=? AND PASSWORD=?");
prep.setString(1, userName);
prep.setString(2, password);
return prep.executeQuery();
}
public static String changePassword(Connection conn, String userName, String password) throws Exception {
PreparedStatement prep = conn.prepareStatement(
"UPDATE USERS SET PASSWORD=? WHERE NAME=?");
prep.setString(1, password);
prep.setString(2, userName);
prep.executeUpdate();
return password;
}
void loginStoredProcedureInsecure() throws Exception {
System.out.println("Insecure Systems Inc. - login using a stored procedure");
stat.execute("CREATE ALIAS IF NOT EXISTS " +
"GET_USER FOR \"org.h2.samples.SQLInjection.getUser\"");
stat.execute("CREATE ALIAS IF NOT EXISTS " +
"CHANGE_PASSWORD FOR \"org.h2.samples.SQLInjection.changePassword\"");
String name = input("Name?");
String password = input("Password?");
ResultSet rs = stat.executeQuery(
"CALL GET_USER('" + name + "', '" + password + "')");
if (rs.next()) {
System.out.println("Welcome!");
} else {
System.out.println("Access denied!");
}
}
void loginByNameSecure() throws Exception {
System.out.println("Secure Systems Inc. - login using placeholders");
String name = input("Name?");
String password = input("Password?");
PreparedStatement prep = conn.prepareStatement(
"SELECT * FROM USERS WHERE " +
"NAME=? AND PASSWORD=?");
prep.setString(1, name);
prep.setString(2, password);
ResultSet rs = prep.executeQuery();
if (rs.next()) {
System.out.println("Welcome!");
} else {
System.out.println("Access denied!");
}
}
void limitRowAccess() throws Exception {
System.out.println("Secure Systems Inc. - limit row access");
stat.execute("DROP TABLE IF EXISTS SESSION_USER");
stat.execute("CREATE TABLE SESSION_USER(ID INT, USER INT)");
stat.execute("DROP VIEW IF EXISTS MY_USER");
stat.execute("CREATE VIEW MY_USER AS " +
"SELECT U.* FROM SESSION_USER S, USERS U " +
"WHERE S.ID=SESSION_ID() AND S.USER=U.ID");
stat.execute("INSERT INTO SESSION_USER VALUES(SESSION_ID(), 1)");
ResultSet rs = stat.executeQuery("SELECT ID, NAME FROM MY_USER");
while (rs.next()) {
System.out.println(rs.getString(1) + ": " + rs.getString(2));
}
}
void loginByIdInsecure() throws Exception {
System.out.println("Half Secure Systems Inc. - login by id");
String id = input("User ID?");
String password = input("Password?");
try {
PreparedStatement prep = conn.prepareStatement(
"SELECT * FROM USERS WHERE " +
"ID=" + id + " AND PASSWORD=?");
prep.setString(1, password);
ResultSet rs = prep.executeQuery();
if (rs.next()) {
System.out.println("Welcome!");
} else {
System.out.println("Access denied!");
}
} catch(SQLException e) {
System.out.println(e);
}
}
void loginByIdSecure() throws Exception {
System.out.println("Secure Systems Inc. - login by id");
String id = input("User ID?");
String password = input("Password?");
try {
PreparedStatement prep = conn.prepareStatement(
"SELECT * FROM USERS WHERE " +
"ID=? AND PASSWORD=?");
prep.setInt(1, Integer.parseInt(id));
prep.setString(2, password);
ResultSet rs = prep.executeQuery();
if (rs.next()) {
System.out.println("Welcome!");
} else {
System.out.println("Access denied!");
}
} catch(Exception e) {
System.out.println(e);
}
}
void listActiveItems() throws Exception {
System.out.println("Half Secure Systems Inc. - list active items");
ResultSet rs = stat.executeQuery(
"SELECT NAME FROM ITEMS WHERE ACTIVE=1");
while (rs.next()) {
System.out.println("Name: " + rs.getString(1));
}
}
void listActiveItemsUsingConstants() throws Exception {
System.out.println("Secure Systems Inc. - list active items");
ResultSet rs = stat.executeQuery(
"SELECT NAME FROM ITEMS WHERE ACTIVE=TYPE_ACTIVE");
while (rs.next()) {
System.out.println("Name: " + rs.getString(1));
}
}
void listItemsSortedInsecure() throws Exception {
System.out.println("Insecure Systems Inc. - list items");
String order = input("order (id, name)?");
try {
ResultSet rs = stat.executeQuery(
"SELECT ID, NAME FROM ITEMS ORDER BY " + order);
while (rs.next()) {
System.out.println(rs.getString(1) + ": " + rs.getString(2));
}
} catch(SQLException e) {
System.out.println(e);
}
}
void listItemsSortedSecure() throws Exception {
System.out.println("Secure Systems Inc. - list items");
String order = input("order (id, name)?");
if (!order.matches("[a-zA-Z0-9_]*")) {
order = "id";
}
try {
ResultSet rs = stat.executeQuery(
"SELECT ID, NAME FROM ITEMS ORDER BY " + order);
while (rs.next()) {
System.out.println(rs.getString(1) + ": " + rs.getString(2));
}
} catch(SQLException e) {
System.out.println(e);
}
}
void listItemsSortedSecureParam() throws Exception {
System.out.println("Secure Systems Inc. - list items");
String order = input("order (1, 2, -1, -2)?");
PreparedStatement prep = conn.prepareStatement(
"SELECT ID, NAME FROM ITEMS ORDER BY ?");
try {
prep.setInt(1, Integer.parseInt(order));
ResultSet rs = prep.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(1) + ": " + rs.getString(2));
}
} catch(Exception e) {
System.out.println(e);
}
}
void storePasswordHashWithSalt() throws Exception {
System.out.println("Very Secure Systems Inc. - login");
stat.execute("DROP TABLE IF EXISTS USERS2");
stat.execute("CREATE TABLE USERS2(ID INT PRIMARY KEY, " +
"NAME VARCHAR, SALT BINARY, HASH BINARY)");
stat.execute("INSERT INTO USERS2 VALUES" +
"(1, 'admin', SECURE_RAND(16), NULL)");
stat.execute("DROP CONSTANT IF EXISTS HASH_ITERATIONS");
stat.execute("DROP CONSTANT IF EXISTS HASH_ALGORITHM");
stat.execute("CREATE CONSTANT HASH_ITERATIONS VALUE 100");
stat.execute("CREATE CONSTANT HASH_ALGORITHM VALUE 'SHA256'");
stat.execute("UPDATE USERS2 SET " +
"HASH=HASH(HASH_ALGORITHM, STRINGTOUTF8('abc' || SALT), HASH_ITERATIONS) " +
"WHERE ID=1");
String user = input("user?");
String password = input("password?");
stat.execute("SET ALLOW_LITERALS NONE");
PreparedStatement prep = conn.prepareStatement(
"SELECT * FROM USERS2 WHERE NAME=? AND " +
"HASH=HASH(HASH_ALGORITHM, STRINGTOUTF8(? || SALT), HASH_ITERATIONS)");
prep.setString(1, user);
prep.setString(2, password);
ResultSet rs = prep.executeQuery();
while (rs.next()) {
System.out.println("name: " + rs.getString("NAME"));
System.out.println("salt: " + rs.getString("SALT"));
System.out.println("hash: " + rs.getString("HASH"));
}
stat.execute("SET ALLOW_LITERALS ALL");
}
String input(String prompt) throws Exception {
System.out.print(prompt);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
return reader.readLine();
}
}
...@@ -89,19 +89,200 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -89,19 +89,200 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
test.printSystem(); test.printSystem();
/* /*
how to make -baseDir work for H2 Console?
*/
/* H2 CSV update
Pavel Ganelin
Integrate patches www.dullesopen.com/software/h2-database-03-04-07-mod.src.zip TestWriteFile
*/
D:\pictures\2007-email
ftp://192.168.0.100:8021/
/* christmas lights tests
Fix Quickstart
h2.linkedTableUpdates to send update statements instead of delete-insert pairs ftp: problem with multithreading?
News: add H2 Database News
Email Subscription: If you like to get informed by email about new releases,
subscribe here. The email addresses of members are only used in this context.
Usually, only one mail every few weeks will be sent.
Email:
send http://thecodist.com/fiche/thecodist/article/sql-injections-how-not-to-get-stuck to JavaWorld, TheServerSide,
MySQL, PostgreSQL
http://semmle.com/
try out, find bugs
DROP TABLE TEST;
CREATE TABLE TEST(ID INT);
@LOOP 10000 INSERT INTO TEST VALUES(?);
-- derby: 5828, 5735
-- jdbc:h2:test;write_mode_log=rws;write_delay=0
-- h2: 15172
DatDb:
insert a varchar ('xxxx...m...') into a binary column is not legal, so I changed:
CREATE TABLE "+tableName+" (fname varchar(80) primary key, gendate bigint, dat binary)
to:
CREATE TABLE "+tableName+" (fname varchar(80) primary key, gendate bigint, dat varchar)
Session sess1 = DBConnection.openSession();
//Wenn Die Transaction erst nach sess2.close() gestartet wird, dann funktioniert es
Transaction t = sess1.beginTransaction();
Session sess2 = DBConnection.openSession();
//Wenn um den query eine Transaction gelegt wird, funktioniert es auch
// Transaction t2 = sess2.beginTransaction();
System.out.println("Number of animals " + sess2.createCriteria(Animal.class).list().size());
// t2.commit();
sess2.close();
Animal a = new Animal();
sess1.save(a);
sess1.flush();
t.commit();
sess1.close();
download/trace*.log
DatDb test
Short answer:
This database does not guarantee that all committed transactions survive a power failure.
While other databases (such as Derby) claim they can guarantee it, in reality they can't.
Testing shows that all databases lose transactions on power failure sometimes.
Where this is not acceptable, a laptop or UPS (uninterruptible power supply) should be used.
If durability is required for all possible cases of hardware failure, clustering should be used,
such as the H2 clustering mode.
Long answer:
Making sure that committed transaction are not lost is more complicated than it seems first.
To guarantee complete durability, a database must ensure that the log record is on the hard drive
before the commit call returns. To do that, different approaches are possible. The first option
is to use the 'synchronous write' option when opening a file. In Java, RandomAccessFile
supports the opening modes "rws" and "rwd":
Around 1000 write operations per second are possible when using one of those modes.
You can get the exact number for your system by running the test org.h2.test.poweroff.TestWrite.
This feature is used by Derby and PostgreSQL.
However, this alone does not force changes to disk, because it does not flush the operating system and hard drive buffers.
Even 7800 RPM hard drives can spin at 130 rounds per second only.
There are other ways force data to disk:
FileDescriptor.sync().
The documentation says that this will force all system buffers to synchronize with the underlying device.
Sync is supposed to return after all in-memory modified copies of buffers associated with this FileDescriptor have been written to the physical medium.
FileChannel.force() (since JDK 1.4).
This method is supposed to force any updates to this channel's file to be written to the storage device that contains it.
The test was made with this database, as well as with PostgreSQL, Derby, and HSQLDB.
None of those databases was able to guarantee complete transaction durability.
To test the durability / non-durability of this and other databases, you can use the test application in the package
org.h2.test.poweroff. Two computers with network connection are required to run this test.
One computer acts as the listener, the test application is run on the other computer.
The computer with the listener application opens a TCP/IP port and listens for an incoming connection.
The second computer first connects to the listener, and then created the databases and starts inserting records.
The connection is set to 'autocommit', which means after each inserted record a commit is performed automatically.
Afterwards, the test computer notifies the listener that this record was inserted successfully.
The listener computer displays the last inserted record number every 10 seconds.
Now, the power needs to be switched off manually while the test is still running.
Now you can restart the computer, and run the application again.
You will find out that in most cases, none of the databases contains all the records that the listener computer knows about.
For details, please consult the source code of the listener and test application.
The test was made using two computers, with computer A
writing to disk and then sending the transaction id over the network to computer B. After some time,
the power is switched off on computer A. After switching on computer A again, some committed
transactions where lost.
It is not enough to just send the write request to
the operating system, because the write cache may be enabled (which is the default for Windows XP).
Unfortunetly, it is also not enough to flush the buffers (fsync), because regular hard drives do not obey
this command. The only way to guarantee durability, according to a test, is to wait about one second
before returning from a commit call. This would mean the maximum number of transactions is 1 per second.
All databases tested achive a much higher transaction rate, which means all databases take some shortcuts.
H2 does not guarantee durability, and while other databases (such as Derby) claim they guarantee it,
in reality none of the tested databases achieve complete durability
There are multiple ways to
With regular hard drives, trying to
Durability means that
Mail P2P
DROP TABLE TEST;
DROP VIEW TEST_VIEW;
CREATE TABLE TEST(ID INT PRIMARY KEY);
@LOOP 1000 INSERT INTO TEST VALUES(?);
CREATE VIEW TEST_VIEW AS SELECT * FROM TEST;
EXPLAIN SELECT * FROM TEST_VIEW WHERE ID=10;
@LOOP 1000 SELECT * FROM TEST_VIEW WHERE ID=?;
@LOOP 1000 SELECT * FROM TEST WHERE ID=?;
DROP TABLE TEST;
DROP VIEW TEST_VIEW;
CREATE TABLE TEST(
PERSON_ID INT PRIMARY KEY,
NAME VARCHAR,
LOWER_NAME VARCHAR AS LOWER(NAME)
);
CREATE INDEX IDX_NAME ON TEST(LOWER_NAME);
EXPLAIN SELECT * FROM TEST WHERE LOWER_NAME LIKE '%';
EXPLAIN SELECT * FROM TEST WHERE LOWER_NAME LIKE '%' ORDER BY LOWER_NAME;
CREATE VIEW TEST_VIEW AS SELECT * FROM TEST;
EXPLAIN SELECT * FROM TEST_VIEW WHERE LOWER_NAME LIKE '%';
EXPLAIN SELECT * FROM TEST_VIEW WHERE LOWER_NAME LIKE '%' ORDER BY LOWER_NAME;
DROP TABLE TEST;
DROP VIEW TEST_VIEW;
CREATE TABLE TEST(ID INT PRIMARY KEY);
@LOOP 1000 INSERT INTO TEST VALUES(?);
CREATE VIEW TEST_VIEW AS SELECT * FROM TEST;
EXPLAIN SELECT * FROM TEST_VIEW WHERE ID=10;
@LOOP 1000 SELECT * FROM TEST_VIEW WHERE ID=?;
@LOOP 1000 SELECT * FROM TEST WHERE ID=?;
Currently there is no such feature, however it is quite simple to add a user defined function
READ_TEXT(fileName String) returning a CLOB. The performance would probably not be optimal,
but it should work. I am not sure if this will read the CLOB in memory however.
I will add this to the todo list.
Docs: Fix Quickstart
Dave Brewster (dbrewster at guidewire dot com): currency: Add a setting to allow BigDecimal extensions
Send SQL Injection solution proposal to PostgreSQL, MySQL, Derby, HSQLDB,...
Improve ACID documentation (durability problem)
Improve LOB in directories performance
Improve documentation for MAX_LENGTH_INPLACE_LOB
Convert SQL-injection-2.txt to html document, include SQLInjection.java sample
Integrate patches from Pavel Ganelin: www.dullesopen.com/software/h2-database-03-04-07-mod.src.zip
Test Eclipse DTP 1.5 (HSQLDB / H2 connection bug fixed) Test Eclipse DTP 1.5 (HSQLDB / H2 connection bug fixed)
Automate power off tests Automate real power off tests
how to make -baseDir work for H2 Console?
Maybe add a little bit AdSense
Custom Captcha for the forum, to protect against spam bots (required for Google Code?)
CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ]
[ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
[ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
http://db.apache.org/ddlutils/ (write a H2 driver)
*/ */
/* /*
...@@ -138,6 +319,39 @@ insert into abc select * from dual where 1=0; ...@@ -138,6 +319,39 @@ insert into abc select * from dual where 1=0;
create local temporary table abc(id varchar) on commit drop; create local temporary table abc(id varchar) on commit drop;
insert into abc select * from dual; insert into abc select * from dual;
drop table abc; drop table abc;
DROP TABLE TEST;
CREATE TABLE TEST(ID INT);
INSERT INTO TEST VALUES(1);
INSERT INTO TEST VALUES(2);
SELECT ID AS A FROM TEST WHERE A>0;
-- Yes: HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, MySQL, H2, Derby
SELECT ID AS A FROM TEST ORDER BY A;
-- Yes: Oracle, MS SQL Server, PostgreSQL, MySQL, H2, Derby, HSQLDB
SELECT ID AS A FROM TEST ORDER BY -A;
-- Yes: Oracle, MySQL, HSQLDB
-- Fail: MS SQL Server, PostgreSQL, H2, Derby
SELECT ID AS A FROM TEST GROUP BY A;
-- Yes: PostgreSQL, MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, H2, Derby
SELECT ID AS A FROM TEST GROUP BY -A;
-- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
SELECT ID AS A FROM TEST GROUP BY ID HAVING A>0;
-- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
SELECT COUNT(*) AS A FROM TEST GROUP BY ID HAVING A>0;
-- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
*/ */
// TODO: fix Hibernate dialect bug / Bordea Felix (lost email) // TODO: fix Hibernate dialect bug / Bordea Felix (lost email)
...@@ -162,12 +376,6 @@ drop table abc; ...@@ -162,12 +376,6 @@ drop table abc;
// EXPLAIN SELECT * FROM test WHERE id between 2 and 3 AND flag=true; // EXPLAIN SELECT * FROM test WHERE id between 2 and 3 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag; // EXPLAIN SELECT * FROM test WHERE id=2 AND flag;
/*
Automate real power off test
*/
// h2 // h2
// update FOO set a = dateadd('second', 4320000, a); // update FOO set a = dateadd('second', 4320000, a);
// ms sql server // ms sql server
......
package org.h2.test.cases;
/*
* DatDb.java
*
* Created on 21 maggio 2007, 12.30
*
*/
//package com.impl.util;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.*;
import java.util.HashMap;
import java.util.Random;
/**
*
* @author fbi
*/
public class DatDb {
private static DatDb datdb;
static HashMap cP = new HashMap();
static Connection sharedCon ;
//private String url = "jdbc:h2:file:" + Constants.DAT_DB;
// private String url = "jdbc:h2:file:/temp/datdb;TRACE_LEVEL_FILE=3";
private String url = "jdbc:h2:file:/temp/datdb;DATABASE_EVENT_LISTENER='org.h2.samples.ShowProgress'";
/** Creates a new instance of DatDb */
protected DatDb() {
try {
long t1 = System.currentTimeMillis();
Class.forName("org.h2.Driver");
System.out.println (" getConnection --> ");
//This is a 'special' connection used only to execute select statements (no transactions)
sharedCon = DriverManager.getConnection(url, "sa", "");
System.out.println (" getConnection <-- " + (System.currentTimeMillis()- t1));
sharedCon.setReadOnly(true);
} catch (Exception e) {
//Util.logThrowable(e);
System.out.println(" error: " + e.getMessage());
}
}
public static synchronized DatDb getInstance() {
if (datdb == null) {
datdb = new DatDb();
}
return datdb;
}
public void init (String tableName) {
//String sc = ma.substring(ma.lastIndexOf("/")+1);
try {
Connection con = DriverManager.getConnection(url, "sa", "");
cP.put(tableName, con);
createTable(con, tableName);
} catch (Exception e) {
//Util.logThrowable(e);
}
}
public void save(String tableName, String key, String xml) {
Connection con = null;
//String tableName = ma.substring(ma.lastIndexOf("/")+1);
try {
con = (Connection) cP.get(tableName);
if (con == null) throw new RuntimeException ("Unable to find the connection");
con.setAutoCommit(false);
PreparedStatement stm = null;
stm = con.prepareStatement("delete from "+tableName+" where fname = ?");
stm.setString(1, key);
stm.executeUpdate();
stm.close();
stm = con.prepareStatement("insert into "+tableName+" (fname, gendate, dat) values(?,?,?)");
stm.setString(1, key);
stm.setLong(2, System.currentTimeMillis());
//--- original code ---->>>> stm.setObject(3, com.fw.util.Util.compressString(xml));
stm.setObject(3, xml);
stm.executeUpdate();
con.commit();
} catch (Exception e) {
try {
con.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
// Util.logThrowable(e);
}
}
public long getGenDate (String tableName, String key) {
Connection con = null;
long gendate = 0;
PreparedStatement stm = null;
try {
stm = sharedCon.prepareStatement("select gendate from "+tableName+" where fname = ?");
stm.setString(1, key);
ResultSet rs = stm.executeQuery();
while (rs.next()) {
gendate = rs.getLong(1);
}
} catch (Exception e) {
//Util.logThrowable(e);
} finally {
try {
stm.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
//System.out.println ("getGenDate table "+tableName+" key "+key+" returns "+gendate);
return gendate;
}
public boolean containsKey(String tableName, String key) {
Connection con = null;
boolean b = false;
PreparedStatement stm = null;
try {
stm = sharedCon.prepareStatement("select fname from "+tableName+" where fname = ?");
stm.setString(1, key);
ResultSet rs = stm.executeQuery();
while (rs.next()) {
b = true;
}
} catch (Exception e) {
//Util.logThrowable(e);
} finally {
try {
stm.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
//System.out.println ("containsKey table "+tableName+" key "+key+" returns "+b);
return b;
}
public String getDat(String tableName, String key) {
String ret = null;
byte buf[] = null;
PreparedStatement stm = null;
try {
stm = sharedCon.prepareStatement("select dat from "+tableName+" where fname = ?");
stm.setString(1, key);
ResultSet rs = stm.executeQuery();
while (rs.next()) {
buf = rs.getBytes(1);
}
if (buf == null) {
//System.out.println (" NULL BUF for table "+tableName+" KEY "+ key);
return ret;
}
// ------->>>> Original code ------<<<< ret = Util.uncompressString(buf);
ret = new String(buf);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
stm.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
return ret;
}
private void createTable(Connection con, String tableName) {
ResultSet rs = null;
try {
DatabaseMetaData dmd = con.getMetaData();
rs = dmd.getTables(null, null, null, null);
String temp = null;
while (rs.next()) {
temp = rs.getString(3);
if (temp.equalsIgnoreCase(tableName)) {
return;
}
}
} catch (Exception e) {
//Util.logThrowable(e);
}
try {
java.sql.Statement stm = con.createStatement();
stm.execute("CREATE TABLE "+tableName+" (fname varchar(80) primary key, gendate bigint, dat varchar) ");
System.out.println (" Table "+tableName+" created");
} catch (Exception e) {
// Util.logThrowable(e);
}
}
public void close(String tableName) {
Connection c = (Connection) cP.remove(tableName);
try {
c.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
//-------------------------------------- TEST START ------------------------
public static void main(String ar[]) {
System.out.println (" Starting ");
DatDb db = new DatDb();
db.go();
}
private void go () {
/*
* Please change the values as needed.
* The test I've made uses MAX_REC = 400000
* and MAX_TAB = 50,
* 20.000.000 records!
*/
int MAX_REC = 400000;
int MAX_TAB = 10;
String tableName = null;
long start = System.currentTimeMillis();
System.out.println(" Start test ");
long trec = 0;
for (int j = 0; j < MAX_TAB; j++) {
tableName = "n"+j;
try {
Connection con = DriverManager.getConnection(url, "sa","");
cP.put(tableName, con);
createTable(con, tableName);
} catch (Exception e ){ e.printStackTrace(); }
long t1 = System.currentTimeMillis();
trec = t1;
for (int k = 0; k < MAX_REC; k++ ){
this.save(tableName,"this_is_a_possible_key_value"+k, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");
if (k > 0 && (k % 10000) == 0) {
System.out.println(" added more 10000 records to "+tableName+" spent "+ (System.currentTimeMillis()-trec)+ " K "+k);
trec = System.currentTimeMillis();
}
}
close(tableName);
System.out.println(" TABLE "+tableName+" completed with "+MAX_REC +" millis "+ (System.currentTimeMillis() - t1));
}
// Now, try to get back some raws
int tkey = 0;
int rkey = 0;
Random rnd = new Random();
for (int l = 0; l < 100; l++) {
start = System.currentTimeMillis();
tkey = rnd.nextInt(MAX_TAB);
rkey = rnd.nextInt(MAX_REC);
this.getDat("n"+tkey, "questa_essere_la_chivae_numero_"+rkey);
// System.out.println ("estract dat key "+rkey+" from table n"+ tkey+" in millis "+ (System.currentTimeMillis() - start));
}
System.out.println (" exercise end" );
try {
sharedCon.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
package org.h2.test.cases;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class TestMemoryDb {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
String url = "jdbc:h2:mem:EventDB";
String user = "sa";
String password = "sa";
Connection conn1 = DriverManager.getConnection(url, user, password);
Statement stat1 = conn1.createStatement();
stat1.execute("create table test(id int)");
Connection conn2 = DriverManager.getConnection(url, user, password);
Statement stat2 = conn2.createStatement();
stat2.executeQuery("select * from test");
conn1.close();
conn2.close();
}
}
package org.h2.test.poweroff;
import java.io.File;
import java.io.FileDescriptor;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class TestWrite {
public static void main(String[] args) throws Exception {
testFile("rw", false);
testFile("rwd", false);
testFile("rws", false);
testFile("rw", true);
testFile("rwd", true);
testFile("rws", true);
testDatabase("org.h2.Driver", "jdbc:h2:test", "sa", "");
testDatabase("org.hsqldb.jdbcDriver", "jdbc:hsqldb:test4", "sa", "");
testDatabase("org.apache.derby.jdbc.EmbeddedDriver", "jdbc:derby:test;create=true", "sa", "");
testDatabase("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "sa", "sa");
testDatabase("org.postgresql.Driver", "jdbc:postgresql:test", "sa", "sa");
}
static void testFile(String mode, boolean flush) throws Exception {
System.out.println("Testing RandomAccessFile(.., \"" + mode + "\")...");
if(flush) {
System.out.println(" with FileDescriptor.sync()");
}
RandomAccessFile file = new RandomAccessFile("test.txt", mode);
file.setLength(0);
FileDescriptor fd = file.getFD();
long start = System.currentTimeMillis();
byte[] data = new byte[] {0};
file.write(data);
int i=0;
if(flush) {
for(; ; i++) {
file.seek(0);
file.write(data);
fd.sync();
if((i & 15) == 0) {
long time = System.currentTimeMillis() - start;
if(time > 5000) {
break;
}
}
}
} else {
for(; ; i++) {
file.seek(0);
file.write(data);
if((i & 1023) == 0) {
long time = System.currentTimeMillis() - start;
if(time > 5000) {
break;
}
}
}
}
long time = System.currentTimeMillis() - start;
System.out.println("Time: " + time);
System.out.println("Operations: " + i);
System.out.println("Operations/second: " + (i * 1000 / time));
System.out.println();
file.close();
new File("test.txt").delete();
}
static void testDatabase(String driver, String url, String user, String password) throws Exception {
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println("Testing Database, URL=" + url);
Statement stat = conn.createStatement();
try {
stat.execute("DROP TABLE TEST");
} catch(SQLException e) {
// ignore
}
stat.execute("CREATE TABLE TEST(ID INT)");
PreparedStatement prep = conn.prepareStatement("INSERT INTO TEST VALUES(?)");
long start = System.currentTimeMillis();
int i=0;
for(; ; i++) {
prep.setInt(1, i);
// autocommit is on by default, so this commits as well
prep.execute();
if((i & 15) == 0) {
long time = System.currentTimeMillis() - start;
if(time > 5000) {
break;
}
}
}
long time = System.currentTimeMillis() - start;
System.out.println("Time: " + time);
System.out.println("Operations: " + i);
System.out.println("Operations/second: " + (i * 1000 / time));
System.out.println();
stat.execute("DROP TABLE TEST");
conn.close();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论