提交 19556a3e authored 作者: Erwan Bocher's avatar Erwan Bocher

Merge branch 'master' of https://github.com/h2database/h2database into updateJTS

......@@ -44,7 +44,17 @@ import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.tools.CompressTool;
import org.h2.tools.Csv;
import org.h2.util.*;
import org.h2.util.AutoCloseInputStream;
import org.h2.util.DateTimeUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
import org.h2.util.ToChar;
import org.h2.util.ToDateParser;
import org.h2.util.Utils;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueArray;
......@@ -1424,11 +1434,11 @@ public class Function extends Expression implements FunctionCall {
}
break;
case TO_DATE:
result = ValueTimestamp.get(ToDate.TO_DATE(v0.getString(),
result = ValueTimestamp.get(ToDateParser.toDate(v0.getString(),
v1 == null ? null : v1.getString()));
break;
case TO_TIMESTAMP:
result = ValueTimestamp.get(ToDate.TO_TIMESTAMP(v0.getString(),
result = ValueTimestamp.get(ToDateParser.toTimestamp(v0.getString(),
v1 == null ? null : v1.getString()));
break;
case TRANSLATE: {
......
......@@ -410,9 +410,9 @@ public final class JoinBatch {
@Override
public String toString() {
return "JoinBatch->\nprev->" + (current == null ? null : current.prev) +
"\ncurr->" + current +
"\nnext->" + (current == null ? null : current.next);
return "JoinBatch->\n" + "prev->" + (current == null ? null : current.prev) +
"\n" + "curr->" + current +
"\n" + "next->" + (current == null ? null : current.next);
}
/**
......
......@@ -11,7 +11,10 @@ import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.h2.api.ErrorCode;
import org.h2.message.DbException;
......
package org.h2.util;
import java.sql.Timestamp;
import java.util.Date;
/**
* Emulates Oracle's TO_DATE function.<br>
* Main class
*/
public class ToDate {
public static Timestamp TO_DATE(final String input, final String format) {
ToDateParser parser = ToDateParser.toDate(input, format);
return parser.getResultingTimestamp();
}
public static Timestamp TO_TIMESTAMP(final String input, final String format) {
ToDateParser parser = ToDateParser.toTimestamp(input, format);
return parser.getResultingTimestamp();
}
}
\ No newline at end of file
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Daniel Gredler
*/
package org.h2.util;
import static java.lang.String.format;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* Emulates Oracle's TO_DATE function.<br>
* This class holds and handles the input data form the TO_DATE-method
*/
class ToDateParser {
public class ToDateParser {
private final String unmodifiedInputStr;
private final String unmodifiedFormatStr;
private final ConfigParam functionName;
private String inputStr;
private String formatStr;
private final Calendar resultCalendar = (Calendar) Calendar.getInstance().clone();
private Integer nanos = null;
private enum ConfigParam {
TO_DATE("DD MON YYYY"), TO_TIMESTAMP("DD MON YYYY HH:MI:SS");
private final String defaultFormatStr;
ConfigParam (final String defaultFormatStr) {
this.defaultFormatStr = defaultFormatStr;
}
String getDefaultFormatStr() {
return defaultFormatStr;
}
}
static ToDateParser toDate(final String input, final String format) {
ToDateParser result = new ToDateParser(ConfigParam.TO_DATE, input, format);
parse(result);
return result;
}
static ToDateParser toTimestamp(final String input, final String format) {
ToDateParser result = new ToDateParser(ConfigParam.TO_TIMESTAMP, input, format);
parse(result);
return result;
}
private Integer nanos;
/**
* @param input the input date with the date-time info
* @param format the format of date-time info
* @param functionName one of [TO_DATE, TO_TIMESTAMP] (both share the same code)
* @param format the format of date-time info
* @param functionName one of [TO_DATE, TO_TIMESTAMP] (both share the same
* code)
*/
ToDateParser(final ConfigParam functionName, final String input, final String format) {
private ToDateParser(ConfigParam functionName, String input, String format) {
// reset calendar - default oracle behaviour
resultCalendar.set(Calendar.YEAR, 1970);
resultCalendar.set(Calendar.MONTH, Calendar.getInstance().get(Calendar.MONTH));
......@@ -65,18 +47,34 @@ class ToDateParser {
this.functionName = functionName;
inputStr = input.trim();
unmodifiedInputStr = inputStr; // Keep a copy
// Keep a copy
unmodifiedInputStr = inputStr;
if (format == null || format.isEmpty()) {
formatStr = functionName.getDefaultFormatStr(); // default Oracle format.
// default Oracle format.
formatStr = functionName.getDefaultFormatStr();
} else {
formatStr = format.trim();
}
unmodifiedFormatStr = formatStr; // Keep a copy
// Keep a copy
unmodifiedFormatStr = formatStr;
}
private static ToDateParser getDateParser(String input, String format) {
ToDateParser result = new ToDateParser(ConfigParam.TO_DATE, input, format);
parse(result);
return result;
}
private static ToDateParser getTimestampParser(String input, String format) {
ToDateParser result = new ToDateParser(ConfigParam.TO_TIMESTAMP, input, format);
parse(result);
return result;
}
Timestamp getResultingTimestamp() {
private Timestamp getResultingTimestamp() {
Calendar cal = (Calendar) getResultCalendar().clone();
int nanosToSet = nanos == null ? cal.get(Calendar.MILLISECOND) * 1000000 : nanos.intValue();
int nanosToSet = nanos == null ?
cal.get(Calendar.MILLISECOND) * 1000000 : nanos.intValue();
cal.set(Calendar.MILLISECOND, 0);
Timestamp ts = new Timestamp(cal.getTimeInMillis());
ts.setNanos(nanosToSet);
......@@ -99,15 +97,15 @@ class ToDateParser {
return functionName.name();
}
void setNanos(final int nanos) {
void setNanos(int nanos) {
this.nanos = nanos;
}
boolean hasToParseData() {
private boolean hasToParseData() {
return formatStr.length() > 0;
}
void removeFirstChar() {
private void removeFirstChar() {
if (!formatStr.isEmpty()) {
formatStr = formatStr.substring(1);
}
......@@ -116,9 +114,10 @@ class ToDateParser {
}
}
private static ToDateParser parse(final ToDateParser p) {
private static ToDateParser parse(ToDateParser p) {
while (p.hasToParseData()) {
List<ToDateTokenizer.FormatTokenEnum> tokenList = ToDateTokenizer.FormatTokenEnum.getTokensInQuestion(p.getFormatStr());
List<ToDateTokenizer.FormatTokenEnum> tokenList =
ToDateTokenizer.FormatTokenEnum.getTokensInQuestion(p.getFormatStr());
if (tokenList.isEmpty()) {
p.removeFirstChar();
continue;
......@@ -138,19 +137,9 @@ class ToDateParser {
return p;
}
void remove(final String toIgnore) {
if (toIgnore != null) {
int trimLeng = toIgnore.length();
formatStr = formatStr.substring(trimLeng);
if (inputStr.length() >= trimLeng) {
inputStr = inputStr.substring(trimLeng);
}
}
}
void remove(final String intputFragmentStr, final String formatFragment) {
if (intputFragmentStr != null && inputStr.length() >= intputFragmentStr.length()) {
inputStr = inputStr.substring(intputFragmentStr.length());
void remove(String inputFragmentStr, String formatFragment) {
if (inputFragmentStr != null && inputStr.length() >= inputFragmentStr.length()) {
inputStr = inputStr.substring(inputFragmentStr.length());
}
if (formatFragment != null && formatStr.length() >= formatFragment.length()) {
formatStr = formatStr.substring(formatFragment.length());
......@@ -159,21 +148,50 @@ class ToDateParser {
@Override
public String toString() {
int inputStrLeng = inputStr.length();
int orgInputLeng = unmodifiedInputStr.length();
int currentInputPos = orgInputLeng - inputStrLeng;
int restInputLeng = inputStrLeng <= 0 ? inputStrLeng : inputStrLeng - 1;
int inputStrLen = inputStr.length();
int orgInputLen = unmodifiedInputStr.length();
int currentInputPos = orgInputLen - inputStrLen;
int restInputLen = inputStrLen <= 0 ? inputStrLen : inputStrLen - 1;
int orgFormatLeng = unmodifiedFormatStr.length();
int currentFormatPos = orgFormatLeng - formatStr.length();
int orgFormatLen = unmodifiedFormatStr.length();
int currentFormatPos = orgFormatLen - formatStr.length();
StringBuilder sb = new StringBuilder();
sb.append(format("\n %s('%s', '%s')", functionName, unmodifiedInputStr, unmodifiedFormatStr));
sb.append(format("\n %s^%s , %s^ <-- Parsing failed at this point", //
sb.append(format("\n %s('%s', '%s')", functionName,
unmodifiedInputStr, unmodifiedFormatStr));
sb.append(format("\n %s^%s , %s^ <-- Parsing failed at this point",
format("%" + (functionName.name().length() + currentInputPos) + "s", ""),
restInputLeng <= 0 ? "" : format("%" + restInputLeng + "s", ""),
restInputLen <= 0 ? "" : format("%" + restInputLen + "s", ""),
currentFormatPos <= 0 ? "" : format("%" + currentFormatPos + "s", "")));
return sb.toString();
}
public static Timestamp toTimestamp(String input, String format) {
ToDateParser parser = getTimestampParser(input, format);
return parser.getResultingTimestamp();
}
public static Timestamp toDate(String input, String format) {
ToDateParser parser = getDateParser(input, format);
return parser.getResultingTimestamp();
}
/**
* The configuration of the date parser.
*/
private enum ConfigParam {
TO_DATE("DD MON YYYY"),
TO_TIMESTAMP("DD MON YYYY HH:MI:SS");
private final String defaultFormatStr;
ConfigParam(String defaultFormatStr) {
this.defaultFormatStr = defaultFormatStr;
}
String getDefaultFormatStr() {
return defaultFormatStr;
}
}
}
\ No newline at end of file
......@@ -767,7 +767,7 @@ public abstract class Value {
case TIMESTAMP_UTC:
return ValueTimestamp.fromMillisNanos(
((ValueTimestampUtc) this).getUtcDateTimeMillis(),
((ValueTimestampUtc) this).getNanosSinceLastMilli());
((ValueTimestampUtc) this).getNanosSinceLastMillis());
}
break;
}
......
......@@ -110,14 +110,14 @@ public final class ValueTimestampUtc extends Value {
return utcDateTimeNanos / 1000 / 1000;
}
public int getNanosSinceLastMilli() {
int getNanosSinceLastMillis() {
return (int) (utcDateTimeNanos % (1000 * 1000));
}
@Override
public java.sql.Timestamp getTimestamp() {
java.sql.Timestamp ts = new java.sql.Timestamp(getUtcDateTimeMillis());
ts.setNanos(getNanosSinceLastMilli());
ts.setNanos(getNanosSinceLastMillis());
return ts;
}
......@@ -157,7 +157,7 @@ public final class ValueTimestampUtc extends Value {
timeNanos *= 60;
timeNanos += cal.get(Calendar.MILLISECOND);
timeNanos *= 1000 * 1000;
timeNanos += getNanosSinceLastMilli();
timeNanos += getNanosSinceLastMillis();
ValueTime.appendTime(buff, timeNanos, true);
buff.append(" UTC");
return buff.toString();
......
......@@ -5,17 +5,14 @@
*/
package org.h2.samples;
import org.h2.tools.DeleteDbFiles;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.h2.tools.DeleteDbFiles;
/**
* A very simple class that shows how to load the driver, create a database,
......@@ -37,11 +34,20 @@ public class ToDate {
Connection conn = DriverManager.getConnection("jdbc:h2:~/test");
Statement stat = conn.createStatement();
stat.execute("create table ToDateTest(id int primary key, start_date datetime, end_date datetime)");
stat.execute("insert into ToDateTest values(1, TO_DATE('2015-11-13', 'yyyy-MM-DD'), TO_DATE('2015-12-15', 'YYYY-MM-DD'))");
stat.execute("insert into ToDateTest values(2, TO_DATE('2015-12-12 00:00:00', 'yyyy-MM-DD HH24:MI:ss'), TO_DATE('2015-12-16 15:00:00', 'YYYY-MM-DD HH24:MI:ss'))");
stat.execute("insert into ToDateTest values(3, TO_DATE('2015-12-12 08:00 A.M.', 'yyyy-MM-DD HH:MI AM'), TO_DATE('2015-12-17 08:00 P.M.', 'YYYY-MM-DD HH:MI AM'))");
stat.execute("insert into ToDateTest values(4, TO_DATE(substr('2015-12-12 08:00 A.M.', 1, 10), 'yyyy-MM-DD'), TO_DATE('2015-12-17 08:00 P.M.', 'YYYY-MM-DD HH:MI AM'))");
stat.execute("create table ToDateTest(id int primary key, " +
"start_date datetime, end_date datetime)");
stat.execute("insert into ToDateTest values(1, " +
"TO_DATE('2015-11-13', 'yyyy-MM-DD'), " +
"TO_DATE('2015-12-15', 'YYYY-MM-DD'))");
stat.execute("insert into ToDateTest values(2, " +
"TO_DATE('2015-12-12 00:00:00', 'yyyy-MM-DD HH24:MI:ss'), " +
"TO_DATE('2015-12-16 15:00:00', 'YYYY-MM-DD HH24:MI:ss'))");
stat.execute("insert into ToDateTest values(3, " +
"TO_DATE('2015-12-12 08:00 A.M.', 'yyyy-MM-DD HH:MI AM'), " +
"TO_DATE('2015-12-17 08:00 P.M.', 'YYYY-MM-DD HH:MI AM'))");
stat.execute("insert into ToDateTest values(4, " +
"TO_DATE(substr('2015-12-12 08:00 A.M.', 1, 10), 'yyyy-MM-DD'), " +
"TO_DATE('2015-12-17 08:00 P.M.', 'YYYY-MM-DD HH:MI AM'))");
ResultSet rs = stat.executeQuery("select * from ToDateTest");
while (rs.next()) {
......
......@@ -1033,32 +1033,32 @@ public class TestOptimizations extends TestBase {
deleteDb("optimizations");
Connection conn = getConnection("optimizations");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TBL_A(id IDENTITY PRIMARY KEY NOT NULL, " +
stat.execute("CREATE TABLE TABLE_A(id IDENTITY PRIMARY KEY NOT NULL, " +
"name VARCHAR NOT NULL, active BOOLEAN DEFAULT TRUE, " +
"UNIQUE KEY TBL_A_UK (name) )");
stat.execute("CREATE TABLE TBL_B(id IDENTITY PRIMARY KEY NOT NULL, " +
"tbl_a_id BIGINT NOT NULL, createDate TIMESTAMP DEFAULT NOW(), " +
"UNIQUE KEY TBL_B_UK (tbl_a_id, createDate), " +
"FOREIGN KEY (tbl_a_id) REFERENCES TBL_A(id) )");
stat.execute("INSERT INTO TBL_A (name) SELECT 'package_' || CAST(X as VARCHAR) " +
"UNIQUE KEY TABLE_A_UK (name) )");
stat.execute("CREATE TABLE TABLE_B(id IDENTITY PRIMARY KEY NOT NULL, " +
"TABLE_a_id BIGINT NOT NULL, createDate TIMESTAMP DEFAULT NOW(), " +
"UNIQUE KEY TABLE_B_UK (table_a_id, createDate), " +
"FOREIGN KEY (table_a_id) REFERENCES TABLE_A(id) )");
stat.execute("INSERT INTO TABLE_A (name) SELECT 'package_' || CAST(X as VARCHAR) " +
"FROM SYSTEM_RANGE(1, 100) WHERE X <= 100");
stat.execute("INSERT INTO TBL_B (tbl_a_id, createDate) SELECT " +
"CASE WHEN tbl_a_id = 0 THEN 1 ELSE tbl_a_id END, createDate " +
"FROM ( SELECT ROUND((RAND() * 100)) AS tbl_a_id, " +
stat.execute("INSERT INTO TABLE_B (table_a_id, createDate) SELECT " +
"CASE WHEN table_a_id = 0 THEN 1 ELSE table_a_id END, createDate " +
"FROM ( SELECT ROUND((RAND() * 100)) AS table_a_id, " +
"DATEADD('SECOND', X, NOW()) as createDate FROM SYSTEM_RANGE(1, 50000) " +
"WHERE X < 50000 )");
stat.execute("CREATE INDEX tbl_b_idx ON tbl_b(tbl_a_id, id)");
stat.execute("CREATE INDEX table_b_idx ON table_b(table_a_id, id)");
stat.execute("ANALYZE");
ResultSet rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(b.id) as id " +
"FROM tbl_b b JOIN tbl_a a ON b.tbl_a_id = a.id GROUP BY b.tbl_a_id " +
"FROM table_b b JOIN table_a a ON b.table_a_id = a.id GROUP BY b.table_a_id " +
"HAVING A.ACTIVE = TRUE");
rs.next();
assertContains(rs.getString(1), "/* PUBLIC.TBL_B_IDX: TBL_A_ID = A.ID */");
assertContains(rs.getString(1), "/* PUBLIC.TABLE_B_IDX: TABLE_A_ID = A.ID */");
rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(id) FROM tbl_b GROUP BY tbl_a_id");
rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(id) FROM table_b GROUP BY table_a_id");
rs.next();
assertContains(rs.getString(1), "/* PUBLIC.TBL_B_IDX");
assertContains(rs.getString(1), "/* PUBLIC.TABLE_B_IDX");
conn.close();
}
}
......@@ -351,15 +351,15 @@ public class TestTableEngines extends TestBase {
deleteDb("testQueryExpressionFlag");
Connection conn = getConnection("testQueryExpressionFlag");
Statement stat = conn.createStatement();
stat.execute("create table QRY_EXPR_TEST(id int) ENGINE \"" +
stat.execute("create table QUERY_EXPR_TEST(id int) ENGINE \"" +
TreeSetIndexTableEngine.class.getName() + "\"");
stat.execute("create table QRY_EXPR_TEST_NO(id int) ENGINE \"" +
stat.execute("create table QUERY_EXPR_TEST_NO(id int) ENGINE \"" +
TreeSetIndexTableEngine.class.getName() + "\"");
stat.executeQuery("select 1 + (select 1 from QRY_EXPR_TEST)").next();
stat.executeQuery("select 1 from QRY_EXPR_TEST_NO where id in "
+ "(select id from QRY_EXPR_TEST)");
stat.executeQuery("select 1 from QRY_EXPR_TEST_NO n "
+ "where exists(select 1 from QRY_EXPR_TEST y where y.id = n.id)");
stat.executeQuery("select 1 + (select 1 from QUERY_EXPR_TEST)").next();
stat.executeQuery("select 1 from QUERY_EXPR_TEST_NO where id in "
+ "(select id from QUERY_EXPR_TEST)");
stat.executeQuery("select 1 from QUERY_EXPR_TEST_NO n "
+ "where exists(select 1 from QUERY_EXPR_TEST y where y.id = n.id)");
deleteDb("testQueryExpressionFlag");
}
......@@ -621,7 +621,7 @@ public class TestTableEngines extends TestBase {
setBatchingEnabled(stat, true);
List<List<Object>> actual = query(stat, sql);
if (!expected.equals(actual)) {
fail("\nexpected: " + expected + "\nactual: " + actual);
fail("\n" + "expected: " + expected + "\n" + "actual: " + actual);
}
}
......@@ -699,10 +699,10 @@ public class TestTableEngines extends TestBase {
private static void setBatchSize(TreeSetTable t, int batchSize) {
if (t.getIndexes() == null) {
t.scan.preferedBatchSize = batchSize;
t.scan.preferredBatchSize = batchSize;
} else {
for (Index idx : t.getIndexes()) {
((TreeSetIndex) idx).preferedBatchSize = batchSize;
((TreeSetIndex) idx).preferredBatchSize = batchSize;
}
}
}
......@@ -746,7 +746,7 @@ public class TestTableEngines extends TestBase {
t >>>= 4;
}
if (where.length() != 0) {
b.append("\nwhere ").append(where);
b.append("\n" + "where ").append(where);
}
return b.toString();
......@@ -1313,7 +1313,7 @@ public class TestTableEngines extends TestBase {
static AtomicInteger lookupBatches = new AtomicInteger();
int preferedBatchSize;
int preferredBatchSize;
final TreeSet<SearchRow> set = new TreeSet<SearchRow>(this);
......@@ -1337,8 +1337,8 @@ public class TestTableEngines extends TestBase {
@Override
public IndexLookupBatch createLookupBatch(final TableFilter filter) {
assert0(filter.getMasks() != null || "scan".equals(getName()), "masks");
final int preferedSize = preferedBatchSize;
if (preferedSize == 0) {
final int preferredSize = preferredBatchSize;
if (preferredSize == 0) {
return null;
}
lookupBatches.incrementAndGet();
......@@ -1351,7 +1351,7 @@ public class TestTableEngines extends TestBase {
}
@Override public boolean isBatchFull() {
return searchRows.size() >= preferedSize * 2;
return searchRows.size() >= preferredSize * 2;
}
@Override
......@@ -1490,9 +1490,9 @@ public class TestTableEngines extends TestBase {
String alias = alias(session.getSubQueryInfo());
assert0(alias.equals("ZZ"), "select expression sub-query: " + alias);
assert0(session.getSubQueryInfo().getUpper() == null, "upper");
} else if (getTable().getName().equals("QRY_EXPR_TEST")) {
} else if (getTable().getName().equals("QUERY_EXPR_TEST")) {
assert0(session.isPreparingQueryExpression(), "preparing query expression");
} else if (getTable().getName().equals("QRY_EXPR_TEST_NO")) {
} else if (getTable().getName().equals("QUERY_EXPR_TEST_NO")) {
assert0(!session.isPreparingQueryExpression(), "not preparing query expression");
}
}
......@@ -1588,7 +1588,7 @@ public class TestTableEngines extends TestBase {
@Override
public String toString() {
return "IterCursor->" + current;
return "IteratorCursor->" + current;
}
}
......
......@@ -474,7 +474,8 @@ public class TestDate extends TestBase {
assertEquals("-999-08-07 13:14:15.16", ts1a.getString());
assertEquals("19999-08-07 13:14:15.16", ts2a.getString());
// test for bug on Java 1.8.0_60 in "Europe/Moscow" timezone. Doesn't affect most other timezones
// test for bug on Java 1.8.0_60 in "Europe/Moscow" timezone.
// Doesn't affect most other timezones
long millis = 1407437460000L;
long result1 = DateTimeUtils.nanosFromDate(DateTimeUtils.getTimeUTCWithoutDst(millis));
long result2 = DateTimeUtils.nanosFromDate(DateTimeUtils.getTimeUTCWithoutDst(millis));
......
......@@ -26,13 +26,13 @@ public class TestTimeStampUtc extends TestBase {
@Override
public void test() throws SQLException {
deleteDb("timestamputc");
deleteDb("timestamp_utc");
test1();
deleteDb("timestamputc");
deleteDb("timestamp_utc");
}
private void test1() throws SQLException {
Connection conn = getConnection("timestamputc");
Connection conn = getConnection("timestamp_utc");
Statement stat = conn.createStatement();
stat.execute("create table test(id identity, t1 timestamp_utc)");
stat.execute("insert into test(t1) values(0)");
......
......@@ -308,9 +308,9 @@ public class BuildBase {
protected int execScript(String script, StringList args) {
if (isWindows()) {
// Under windows, we use the "cmd" command interpreter since it will
// search the path for us without us having to hardcode an extension
// for the script we want. (Sometimes we don't know if the extension
// will be .bat or .cmd)
// search the path for us without us having to hard-code an
// extension for the script we want. (Sometimes we don't know if the
// extension will be .bat or .cmd)
StringList newArgs = new StringList();
newArgs.add("/C");
newArgs.add(script);
......
......@@ -778,10 +778,8 @@ dance schedule hitting reverted youngest footers inliner deadlocked reorder nger
nullid syspublic sysibmts sysibminternal syscat sysfun sysstat systools sysibmadm
sysproc jcc expecting gpg showed unreferenced activating cvf stephane lacoin
centrale umr ecole nantes sticc lab reordering preferable simultaneously
--- todo
timestamputc lazily satisfy nexpected messager participating eviction milli globally
futures atp lookups batches slot nnext forced tbl diagnostic filer stamp turn going
nwhere hardcode cancellation qry nprev fetched produced nactual incurring interpreter
batching ncurr prefered fewer runners iter
lazily satisfy participating eviction globally futures batches slot forced
diagnostic filer stamp turn going cancellation fetched produced incurring
interpreter batching fewer runners imperial correspond nine purge meridian
calendars moscow messager lookups unhandled buddha parslet
tzh roc xii tzm viii myydd mar vii
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论