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

--no commit message

--no commit message
上级 aaba8d61
......@@ -29,7 +29,7 @@ public class SysProperties {
public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true);
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_SUBQUERY_CACHE = getBooleanSetting("h2.optimizeSubqueryCache", true);
......
......@@ -19,7 +19,7 @@ import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
public class DateTimeUtils {
public static Timestamp convertTimestampToCalendar(Timestamp x, Calendar calendar) throws SQLException {
if (x != null) {
Timestamp y = new Timestamp(getLocalTime(x, calendar));
......@@ -29,14 +29,14 @@ public class DateTimeUtils {
}
return x;
}
public static Time cloneAndNormalizeTime(Time value) {
Calendar cal = Calendar.getInstance();
cal.setTime(value);
cal.set(1970, 0, 1);
return new Time(cal.getTime().getTime());
return new Time(cal.getTime().getTime());
}
public static Date cloneAndNormalizeDate(Date value) {
Calendar cal = Calendar.getInstance();
cal.setTime(value);
......@@ -45,7 +45,7 @@ public class DateTimeUtils {
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
return new Date(cal.getTime().getTime());
}
}
public static Value convertDateToUniversal(Date x, Calendar source) throws SQLException {
return ValueDate.get(new Date(getUniversalTime(source, x)));
......@@ -174,29 +174,20 @@ public class DateTimeUtils {
nano = Integer.parseInt(n);
}
}
Calendar c;
if (tz == null) {
c = Calendar.getInstance();
} else {
c = Calendar.getInstance(tz);
if (hour < 0 || hour > 23) {
throw new IllegalArgumentException("hour: " + hour);
}
c.setLenient(false);
long time;
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 (type != Value.TIMESTAMP) {
c.set(Calendar.MILLISECOND, nano / 1000000);
try {
time = getTime(false, tz, year, month, day, hour, minute, second, type != Value.TIMESTAMP, nano);
} 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 {
throw e;
}
}
time = c.getTime().getTime();
switch (type) {
case Value.DATE:
return new java.sql.Date(time);
......@@ -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,43 +6,60 @@ package org.h2.samples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
/**
* @author Thomas
* This example shows how to secure passwords
* (both database passwords, and account passwords).
*/
public class SecurePassword {
public static void main(String[] argv) throws Exception {
Class.forName("org.h2.Driver");
String url = "jdbc:h2:data/simple";
String user = "sam";
char[] password = {'t', 'i', 'a', 'E', 'T', 'r', 'p'};
// 'unsafe' way to connect
// the password may reside in the main memory for an undefined time
// or even written to disk (swap file)
// This is the normal, but 'unsafe' way to connect:
// the password may reside in the main memory for an undefined time,
// or even written to disk (swap file):
// Connection conn = DriverManager.getConnection(url, user, new String(password));
// 'safe' way to connect
// the password is overwritten after use
// This is the most safe way to connect: the password is overwritten after use
Properties prop = new Properties();
prop.setProperty("user", user);
prop.put("password", password);
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();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.executeUpdate("INSERT INTO TEST VALUES(1, 'Hello')");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST");
stat.execute(
"drop table account if exists");
stat.execute(
"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()) {
System.out.println(rs.getString("NAME"));
System.out.println(rs.getString("name"));
}
conn.close();
}
}
......@@ -79,6 +79,7 @@ import org.h2.test.unit.TestBitField;
import org.h2.test.unit.TestCache;
import org.h2.test.unit.TestCompress;
import org.h2.test.unit.TestDataPage;
import org.h2.test.unit.TestDate;
import org.h2.test.unit.TestExit;
import org.h2.test.unit.TestFile;
import org.h2.test.unit.TestFileLock;
......@@ -516,6 +517,7 @@ Features of H2
new TestBitField().runTest(this);
new TestCompress().runTest(this);
new TestDataPage().runTest(this);
new TestDate().runTest(this);
new TestExit().runTest(this);
new TestFile().runTest(this);
new TestFileLock().runTest(this);
......
......@@ -220,8 +220,8 @@ insert into test values(1), (2), (3);
explain select * from test where id in(1, 2, null);
> 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
drop table test;
......@@ -1941,8 +1941,8 @@ select * from test t1 where id in(id);
explain select * from test t1 where id in(select id from test);
> 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
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);
> 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
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
EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID IN(1, 2);
> 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
EXPLAIN PLAN FOR SELECT * FROM TEST T1 WHERE ID IN(SELECT ID FROM TEST);
> 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
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 {
+ "PHONE: +41976543210\n");
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");
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 ShutdownServer (server needs to be started in a separate
// process)
......
......@@ -61,7 +61,7 @@ public class PrepareTranslation {
// create the translated documentation
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");
// convert the properties files back to utf8 text files, including the
......@@ -97,7 +97,9 @@ public class PrepareTranslation {
String key = (String) it.next();
String t = transProp.getProperty(key);
// 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);
}
}
......@@ -436,7 +438,7 @@ public class PrepareTranslation {
} else {
String t = p.getProperty(key);
String last = base.getProperty(key);
if (t.startsWith("#")) {
if (t.startsWith("#") && !t.startsWith("##")) {
// not translated before
t = oldTranslations.getProperty(now);
if (t == null) {
......@@ -474,7 +476,7 @@ public class PrepareTranslation {
String now = main.getProperty(key);
String t;
if (AUTO_TRANSLATE) {
t = "#" + autoTranslated.get(now);
t = "##" + autoTranslated.get(now);
} else {
System.out.println(trans.getName() + ": key " + key + " not found in translation file; added dummy # 'translation'");
t = "#" + now;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论