提交 5d7daa14 authored 作者: nicolas-f's avatar nicolas-f

Add function FILE_WRITE with unit test

上级 507d02d0
...@@ -3821,6 +3821,16 @@ SELECT LENGTH(FILE_READ('~/.h2.server.properties')) LEN; ...@@ -3821,6 +3821,16 @@ SELECT LENGTH(FILE_READ('~/.h2.server.properties')) LEN;
SELECT FILE_READ('http://localhost:8182/stylesheet.css', NULL) CSS; SELECT FILE_READ('http://localhost:8182/stylesheet.css', NULL) CSS;
" "
"Functions (System)","FILE_WRITE","
FILE_WRITE(Blob , fileNameString)
","
Write the supplied parameter into a file. Return the number of bytes written.
Write access to folder, and admin rights are required to execute this command.
","
SELECT FILE_WRITE('Hello world', '/tmp/hello.txt')) LEN;
"
"Functions (System)","GREATEST"," "Functions (System)","GREATEST","
GREATEST(aValue, bValue [,...]) GREATEST(aValue, bValue [,...])
"," ","
......
...@@ -7,6 +7,7 @@ package org.h2.expression; ...@@ -7,6 +7,7 @@ package org.h2.expression;
import static org.h2.util.ToChar.toChar; import static org.h2.util.ToChar.toChar;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
...@@ -47,6 +48,7 @@ import org.h2.tools.CompressTool; ...@@ -47,6 +48,7 @@ import org.h2.tools.CompressTool;
import org.h2.tools.Csv; import org.h2.tools.Csv;
import org.h2.util.AutoCloseInputStream; import org.h2.util.AutoCloseInputStream;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
...@@ -116,7 +118,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -116,7 +118,7 @@ public class Function extends Expression implements FunctionCall {
ARRAY_LENGTH = 217, LINK_SCHEMA = 218, GREATEST = 219, LEAST = 220, ARRAY_LENGTH = 217, LINK_SCHEMA = 218, GREATEST = 219, LEAST = 220,
CANCEL_SESSION = 221, SET = 222, TABLE = 223, TABLE_DISTINCT = 224, CANCEL_SESSION = 221, SET = 222, TABLE = 223, TABLE_DISTINCT = 224,
FILE_READ = 225, TRANSACTION_ID = 226, TRUNCATE_VALUE = 227, FILE_READ = 225, TRANSACTION_ID = 226, TRUNCATE_VALUE = 227,
NVL2 = 228, DECODE = 229, ARRAY_CONTAINS = 230; NVL2 = 228, DECODE = 229, ARRAY_CONTAINS = 230, FILE_WRITE = 232;
/** /**
* Used in MySQL-style INSERT ... ON DUPLICATE KEY UPDATE ... VALUES * Used in MySQL-style INSERT ... ON DUPLICATE KEY UPDATE ... VALUES
...@@ -453,6 +455,8 @@ public class Function extends Expression implements FunctionCall { ...@@ -453,6 +455,8 @@ public class Function extends Expression implements FunctionCall {
2, Value.NULL, false, false, true); 2, Value.NULL, false, false, true);
addFunction("FILE_READ", FILE_READ, addFunction("FILE_READ", FILE_READ,
VAR_ARGS, Value.NULL, false, false, true); VAR_ARGS, Value.NULL, false, false, true);
addFunction("FILE_WRITE", FILE_WRITE,
2, Value.LONG, false, false, true);
addFunctionNotDeterministic("TRANSACTION_ID", TRANSACTION_ID, addFunctionNotDeterministic("TRANSACTION_ID", TRANSACTION_ID,
0, Value.STRING); 0, Value.STRING);
addFunctionWithNull("DECODE", DECODE, addFunctionWithNull("DECODE", DECODE,
...@@ -1597,6 +1601,24 @@ public class Function extends Expression implements FunctionCall { ...@@ -1597,6 +1601,24 @@ public class Function extends Expression implements FunctionCall {
} }
break; break;
} }
case FILE_WRITE: {
session.getUser().checkAdmin();
result = ValueNull.INSTANCE;
String fileName = v1.getString();
try {
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
InputStream in = v0.getInputStream();
try {
result = ValueLong.get(IOUtils.copyAndClose(in,
fileOutputStream));
} finally {
in.close();
}
} catch (IOException e) {
throw DbException.convertIOException(e, fileName);
}
break;
}
case TRUNCATE_VALUE: { case TRUNCATE_VALUE: {
result = v0.convertPrecision(v1.getLong(), v2.getBoolean()); result = v0.convertPrecision(v1.getLong(), v2.getBoolean());
break; break;
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
package org.h2.test.db; package org.h2.test.db;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
...@@ -43,6 +46,7 @@ import org.h2.test.TestBase; ...@@ -43,6 +46,7 @@ import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.StringUtils;
import org.h2.value.Value; import org.h2.value.Value;
/** /**
...@@ -96,6 +100,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -96,6 +100,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
testToCharFromText(); testToCharFromText();
testTranslate(); testTranslate();
testGenerateSeries(); testGenerateSeries();
testFileWrite();
deleteDb("functions"); deleteDb("functions");
} }
...@@ -622,6 +627,36 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -622,6 +627,36 @@ public class TestFunctions extends TestBase implements AggregateFunction {
FileUtils.delete(fileName); FileUtils.delete(fileName);
} }
private void testFileWrite() throws Exception {
Connection conn = getConnection("functions");
Statement stat = conn.createStatement();
// Copy data into clob table
stat.execute("DROP TABLE TEST IF EXISTS");
PreparedStatement pst = conn.prepareStatement(
"CREATE TABLE TEST(data clob) AS SELECT ? " + "data");
Properties prop = System.getProperties();
ByteArrayOutputStream os = new ByteArrayOutputStream(prop.size());
prop.store(os, "");
pst.setBinaryStream(1, new ByteArrayInputStream(os.toByteArray()));
pst.execute();
os.close();
String fileName = new File(getBaseDir(), "test.txt").getPath();
FileUtils.delete(fileName);
ResultSet rs = stat.executeQuery("SELECT FILE_WRITE(data, " +
StringUtils.quoteStringSQL(fileName) + ") len from test");
assertTrue(rs.next());
assertEquals(os.size(), rs.getInt(1));
InputStreamReader r = new InputStreamReader(FileUtils.newInputStream(fileName));
// Compare expected content with written file content
String ps2 = IOUtils.readStringAndClose(r, -1);
assertEquals(os.toString(), ps2);
conn.close();
FileUtils.delete(fileName);
}
/** /**
* This median implementation keeps all objects in memory. * This median implementation keeps all objects in memory.
*/ */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论