提交 5d1d7a1e authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 aaba8d61
...@@ -29,7 +29,7 @@ public class SysProperties { ...@@ -29,7 +29,7 @@ public class SysProperties {
public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true); public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true);
private int testing; private int testing;
public static final boolean OPTIMIZE_IN_JOIN = getBooleanSetting("h2.optimizeInJoin", true); public static final boolean OPTIMIZE_IN_JOIN = getBooleanSetting("h2.optimizeInJoin", false);
public static final boolean OPTIMIZE_MIN_MAX = getBooleanSetting("h2.optimizeMinMax", true); public static final boolean OPTIMIZE_MIN_MAX = getBooleanSetting("h2.optimizeMinMax", true);
public static final boolean OPTIMIZE_SUBQUERY_CACHE = getBooleanSetting("h2.optimizeSubqueryCache", true); public static final boolean OPTIMIZE_SUBQUERY_CACHE = getBooleanSetting("h2.optimizeSubqueryCache", true);
......
...@@ -174,29 +174,20 @@ public class DateTimeUtils { ...@@ -174,29 +174,20 @@ public class DateTimeUtils {
nano = Integer.parseInt(n); nano = Integer.parseInt(n);
} }
} }
Calendar c; if (hour < 0 || hour > 23) {
if (tz == null) { throw new IllegalArgumentException("hour: " + hour);
c = Calendar.getInstance();
} else {
c = Calendar.getInstance(tz);
} }
c.setLenient(false);
long time; long time;
if (year <= 0) { try {
c.set(Calendar.ERA, GregorianCalendar.BC); time = getTime(false, tz, year, month, day, hour, minute, second, type != Value.TIMESTAMP, nano);
c.set(Calendar.YEAR, 1 - year); } catch (IllegalArgumentException e) {
// special case: if the time simply doesn't exist, use the lenient version
if (e.toString().indexOf("HOUR_OF_DAY") > 0) {
time = getTime(true, tz, year, month, day, hour, minute, second, type != Value.TIMESTAMP, nano);
} else { } else {
c.set(Calendar.YEAR, year); throw e;
} }
c.set(Calendar.MONTH, month - 1); // january is 0
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, second);
if (type != Value.TIMESTAMP) {
c.set(Calendar.MILLISECOND, nano / 1000000);
} }
time = c.getTime().getTime();
switch (type) { switch (type) {
case Value.DATE: case Value.DATE:
return new java.sql.Date(time); return new java.sql.Date(time);
...@@ -215,4 +206,29 @@ public class DateTimeUtils { ...@@ -215,4 +206,29 @@ public class DateTimeUtils {
} }
} }
private static long getTime(boolean lenient, TimeZone tz, int year, int month, int day, int hour, int minute, int second, boolean setMillis, int nano) {
Calendar c;
if (tz == null) {
c = Calendar.getInstance();
} else {
c = Calendar.getInstance(tz);
}
c.setLenient(lenient);
if (year <= 0) {
c.set(Calendar.ERA, GregorianCalendar.BC);
c.set(Calendar.YEAR, 1 - year);
} else {
c.set(Calendar.YEAR, year);
}
c.set(Calendar.MONTH, month - 1); // january is 0
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, second);
if (setMillis) {
c.set(Calendar.MILLISECOND, nano / 1000000);
}
return c.getTime().getTime();
}
} }
...@@ -6,14 +6,15 @@ package org.h2.samples; ...@@ -6,14 +6,15 @@ package org.h2.samples;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.Statement; import java.sql.Statement;
import java.util.Properties; import java.util.Properties;
/** /**
* @author Thomas * This example shows how to secure passwords
* (both database passwords, and account passwords).
*/ */
public class SecurePassword { public class SecurePassword {
public static void main(String[] argv) throws Exception { public static void main(String[] argv) throws Exception {
...@@ -22,25 +23,41 @@ public class SecurePassword { ...@@ -22,25 +23,41 @@ public class SecurePassword {
String user = "sam"; String user = "sam";
char[] password = {'t', 'i', 'a', 'E', 'T', 'r', 'p'}; char[] password = {'t', 'i', 'a', 'E', 'T', 'r', 'p'};
// 'unsafe' way to connect // This is the normal, but 'unsafe' way to connect:
// the password may reside in the main memory for an undefined time // the password may reside in the main memory for an undefined time,
// or even written to disk (swap file) // or even written to disk (swap file):
// Connection conn = DriverManager.getConnection(url, user, new String(password)); // Connection conn = DriverManager.getConnection(url, user, new String(password));
// 'safe' way to connect // This is the most safe way to connect: the password is overwritten after use
// the password is overwritten after use
Properties prop = new Properties(); Properties prop = new Properties();
prop.setProperty("user", user); prop.setProperty("user", user);
prop.put("password", password); prop.put("password", password);
Connection conn = DriverManager.getConnection(url, prop); Connection conn = DriverManager.getConnection(url, prop);
// For security reasons, account passwords should not be stored directly in a database.
// Instead, only the hash should be stored. Also, PreparedStatements must be used
// to avoid SQL injection:
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST"); stat.execute(
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)"); "drop table account if exists");
stat.executeUpdate("INSERT INTO TEST VALUES(1, 'Hello')"); stat.execute(
ResultSet rs = stat.executeQuery("SELECT * FROM TEST"); "create table account(name varchar primary key, salt binary default secure_rand(16), hash binary)");
PreparedStatement prep;
prep = conn.prepareStatement("insert into account(name) values(?)");
prep.setString(1, "Joe");
prep.execute();
prep = conn.prepareStatement(
"update account set hash=hash('SHA256', stringtoutf8(salt||?), 10) where name=?");
prep.setString(1, "secret");
prep.setString(2, "Joe");
prep.execute();
prep = conn.prepareStatement(
"select * from account where name=? and hash=hash('SHA256', stringtoutf8(salt||?), 10)");
prep.setString(1, "Joe");
prep.setString(2, "secret");
ResultSet rs = prep.executeQuery();
while (rs.next()) { while (rs.next()) {
System.out.println(rs.getString("NAME")); System.out.println(rs.getString("name"));
} }
conn.close(); conn.close();
} }
......
...@@ -79,6 +79,7 @@ import org.h2.test.unit.TestBitField; ...@@ -79,6 +79,7 @@ import org.h2.test.unit.TestBitField;
import org.h2.test.unit.TestCache; import org.h2.test.unit.TestCache;
import org.h2.test.unit.TestCompress; import org.h2.test.unit.TestCompress;
import org.h2.test.unit.TestDataPage; import org.h2.test.unit.TestDataPage;
import org.h2.test.unit.TestDate;
import org.h2.test.unit.TestExit; import org.h2.test.unit.TestExit;
import org.h2.test.unit.TestFile; import org.h2.test.unit.TestFile;
import org.h2.test.unit.TestFileLock; import org.h2.test.unit.TestFileLock;
...@@ -516,6 +517,7 @@ Features of H2 ...@@ -516,6 +517,7 @@ Features of H2
new TestBitField().runTest(this); new TestBitField().runTest(this);
new TestCompress().runTest(this); new TestCompress().runTest(this);
new TestDataPage().runTest(this); new TestDataPage().runTest(this);
new TestDate().runTest(this);
new TestExit().runTest(this); new TestExit().runTest(this);
new TestFile().runTest(this); new TestFile().runTest(this);
new TestFileLock().runTest(this); new TestFileLock().runTest(this);
......
...@@ -220,8 +220,8 @@ insert into test values(1), (2), (3); ...@@ -220,8 +220,8 @@ insert into test values(1), (2), (3);
explain select * from test where id in(1, 2, null); explain select * from test where id in(1, 2, null);
> PLAN > PLAN
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > -------------------------------------------------------------------------------------------------------
> SELECT TEST.ID FROM PUBLIC.TEST /* PUBLIC.TEST_TABLE_SCAN */ /* WHERE TRUE */ INNER JOIN TABLE_DISTINCT(TEMP_VIEW_8_X INTEGER=(1, 2, NULL)) TEMP_VIEW_9 /* PUBLIC."" */ ON ID = TEMP_VIEW_9.TEMP_VIEW_8_X WHERE TRUE > SELECT TEST.ID FROM PUBLIC.TEST /* PUBLIC.PRIMARY_KEY_1: ID >= 1 AND ID <= 2 */ WHERE ID IN(1, 2, NULL)
> rows: 1 > rows: 1
drop table test; drop table test;
...@@ -1941,8 +1941,8 @@ select * from test t1 where id in(id); ...@@ -1941,8 +1941,8 @@ select * from test t1 where id in(id);
explain select * from test t1 where id in(select id from test); explain select * from test t1 where id in(select id from test);
> PLAN > PLAN
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > -------------------------------------------------------------------------------------------------------------------------------------------
> SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.TEST_TABLE_SCAN */ /* WHERE TRUE */ INNER JOIN (SELECT DISTINCT ID AS TEMP_VIEW_58_X FROM PUBLIC.TEST /* PUBLIC.TEST_TABLE_SCAN */) TEMP_VIEW_59 /* SELECT DISTINCT ID AS TEMP_VIEW_58_X FROM PUBLIC.TEST /++ PUBLIC.TEST_TABLE_SCAN ++/ */ ON ID = TEMP_VIEW_59.TEMP_VIEW_58_X WHERE TRUE > SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.TEST_TABLE_SCAN */ WHERE ID IN(SELECT ID FROM PUBLIC.TEST /* PUBLIC.TEST_TABLE_SCAN */)
> rows: 1 > rows: 1
select * from test t1 where id in(select id from test); select * from test t1 where id in(select id from test);
...@@ -1954,8 +1954,8 @@ select * from test t1 where id in(select id from test); ...@@ -1954,8 +1954,8 @@ select * from test t1 where id in(select id from test);
explain select * from test t1 where id in(1, select max(id) from test); explain select * from test t1 where id in(1, select max(id) from test);
> PLAN > PLAN
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > -----------------------------------------------------------------------------------------------------------
> SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.TEST_TABLE_SCAN */ /* WHERE TRUE */ INNER JOIN TABLE_DISTINCT(TEMP_VIEW_66_X INTEGER=(1, 2)) TEMP_VIEW_67 /* PUBLIC."" */ ON ID = TEMP_VIEW_67.TEMP_VIEW_66_X WHERE TRUE > SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.PRIMARY_KEY_1: ID >= 1 AND ID <= 2 */ WHERE ID IN(1, 2)
> rows: 1 > rows: 1
select * from test t1 where id in(1, select max(id) from test); select * from test t1 where id in(1, select max(id) from test);
...@@ -4858,14 +4858,14 @@ EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE EXISTS(SELECT * FROM TEST T2 WHERE ...@@ -4858,14 +4858,14 @@ EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE EXISTS(SELECT * FROM TEST T2 WHERE
EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID IN(1, 2); EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID IN(1, 2);
> PLAN > PLAN
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > -----------------------------------------------------------------------------------------------------------
> SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.TEST_TABLE_SCAN */ /* WHERE TRUE */ INNER JOIN TABLE_DISTINCT(TEMP_VIEW_103_X INTEGER=(1, 2)) TEMP_VIEW_104 /* PUBLIC."" */ ON ID = TEMP_VIEW_104.TEMP_VIEW_103_X WHERE TRUE > SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.PRIMARY_KEY_1: ID >= 1 AND ID <= 2 */ WHERE ID IN(1, 2)
> rows: 1 > rows: 1
EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID IN(SELECT ID FROM TEST); EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID IN(SELECT ID FROM TEST);
> PLAN > PLAN
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > -------------------------------------------------------------------------------------------------------------------------------------------
> SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.TEST_TABLE_SCAN */ /* WHERE TRUE */ INNER JOIN (SELECT DISTINCT ID AS TEMP_VIEW_107_X FROM PUBLIC.TEST /* PUBLIC.TEST_TABLE_SCAN */) TEMP_VIEW_108 /* SELECT DISTINCT ID AS TEMP_VIEW_107_X FROM PUBLIC.TEST /++ PUBLIC.TEST_TABLE_SCAN ++/ */ ON ID = TEMP_VIEW_108.TEMP_VIEW_107_X WHERE TRUE > SELECT T1.ID, T1.NAME FROM PUBLIC.TEST T1 /* PUBLIC.TEST_TABLE_SCAN */ WHERE ID IN(SELECT ID FROM PUBLIC.TEST /* PUBLIC.TEST_TABLE_SCAN */)
> rows: 1 > rows: 1
EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID NOT IN(SELECT ID FROM TEST); EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID NOT IN(SELECT ID FROM TEST);
......
package org.h2.test.unit;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
import org.h2.util.DateTimeUtils;
import org.h2.value.Value;
public class TestDate extends TestBase {
public void test() throws Exception {
for (int year = 1970; year < 2070; year++) {
for (int month = 1; month <= 12; month++) {
for (int day = 1; day < 29; day++) {
for (int hour = 0; hour < 24; hour++) {
test(year, month, day, hour);
}
}
}
}
}
private void test(int year, int month, int day, int hour) throws SQLException {
DateTimeUtils.parseDateTime(year + "-" + month + "-" + day + " " + hour + ":00:00", Value.TIMESTAMP, ErrorCode.TIMESTAMP_CONSTANT_2);
}
}
...@@ -21,7 +21,7 @@ public class TestSampleApps extends TestBase { ...@@ -21,7 +21,7 @@ public class TestSampleApps extends TestBase {
+ "PHONE: +41976543210\n"); + "PHONE: +41976543210\n");
testApp(org.h2.samples.Function.class, null, testApp(org.h2.samples.Function.class, null,
"2 is prime\n3 is prime\n5 is prime\n7 is prime\n11 is prime\n13 is prime\n17 is prime\n19 is prime"); "2 is prime\n3 is prime\n5 is prime\n7 is prime\n11 is prime\n13 is prime\n17 is prime\n19 is prime");
testApp(org.h2.samples.SecurePassword.class, null, "Hello"); testApp(org.h2.samples.SecurePassword.class, null, "Joe");
// TODO test ShowProgress (percent numbers are hardware specific) // TODO test ShowProgress (percent numbers are hardware specific)
// TODO test ShutdownServer (server needs to be started in a separate // TODO test ShutdownServer (server needs to be started in a separate
// process) // process)
......
...@@ -61,7 +61,7 @@ public class PrepareTranslation { ...@@ -61,7 +61,7 @@ public class PrepareTranslation {
// create the translated documentation // create the translated documentation
buildHtml("src/docsrc/text", "docs/html", "en"); buildHtml("src/docsrc/text", "docs/html", "en");
buildHtml("src/docsrc/text", "docs/html", "de"); // buildHtml("src/docsrc/text", "docs/html", "de");
buildHtml("src/docsrc/text", "docs/html", "ja"); buildHtml("src/docsrc/text", "docs/html", "ja");
// convert the properties files back to utf8 text files, including the // convert the properties files back to utf8 text files, including the
...@@ -97,7 +97,9 @@ public class PrepareTranslation { ...@@ -97,7 +97,9 @@ public class PrepareTranslation {
String key = (String) it.next(); String key = (String) it.next();
String t = transProp.getProperty(key); String t = transProp.getProperty(key);
// overload with translations, but not the ones starting with # // overload with translations, but not the ones starting with #
if (!t.startsWith("#")) { if (t.startsWith("##")) {
prop.put(key, t.substring(2));
} else if (!t.startsWith("#")) {
prop.put(key, t); prop.put(key, t);
} }
} }
...@@ -436,7 +438,7 @@ public class PrepareTranslation { ...@@ -436,7 +438,7 @@ public class PrepareTranslation {
} else { } else {
String t = p.getProperty(key); String t = p.getProperty(key);
String last = base.getProperty(key); String last = base.getProperty(key);
if (t.startsWith("#")) { if (t.startsWith("#") && !t.startsWith("##")) {
// not translated before // not translated before
t = oldTranslations.getProperty(now); t = oldTranslations.getProperty(now);
if (t == null) { if (t == null) {
...@@ -474,7 +476,7 @@ public class PrepareTranslation { ...@@ -474,7 +476,7 @@ public class PrepareTranslation {
String now = main.getProperty(key); String now = main.getProperty(key);
String t; String t;
if (AUTO_TRANSLATE) { if (AUTO_TRANSLATE) {
t = "#" + autoTranslated.get(now); t = "##" + autoTranslated.get(now);
} else { } else {
System.out.println(trans.getName() + ": key " + key + " not found in translation file; added dummy # 'translation'"); System.out.println(trans.getName() + ": key " + key + " not found in translation file; added dummy # 'translation'");
t = "#" + now; t = "#" + now;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论