diff --git a/prql-java/DEVELOPMENT.md b/prql-java/DEVELOPMENT.md index a8dc766aa1eb..5d2933a86a32 100644 --- a/prql-java/DEVELOPMENT.md +++ b/prql-java/DEVELOPMENT.md @@ -8,8 +8,8 @@ We implement Rust bindings to Java with [JNI](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/). First, define a native method -- -`public static native String toSql(String query)` for PrqlCompiler, `toJson` is -same. +`public static native String toSql(String query, String target, boolean format, boolean signature)` +for PrqlCompiler, `toJson` is same. And then implement it in Rust with this [crate](https://docs.rs/jni/latest/jni/). diff --git a/prql-java/java/pom.xml b/prql-java/java/pom.xml index 84d8bddd2339..d7276e6edff1 100644 --- a/prql-java/java/pom.xml +++ b/prql-java/java/pom.xml @@ -6,7 +6,7 @@ org.prqllang prql-java - 0.2.1 + 0.5.2 ${project.groupId}:${project.artifactId} prql-compiler api for java diff --git a/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java b/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java index 49f47d19728d..bf0efbf46f23 100644 --- a/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java +++ b/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java @@ -3,8 +3,19 @@ import java.io.IOException; public class PrqlCompiler { - public static native String toSql(String query); - public static native String toJson(String query); + + /** + * compile PRQL to SQL + * @param query PRQL query + * @param target target dialect, such as sql.mysql etc. Please refer PRQL Target and Version + * @param format format SQL or not + * @param signature comment signature or not + * @return SQL + * @throws Exception PRQL compile exception + */ + public static native String toSql(String query, String target, boolean format, boolean signature) throws Exception; + public static native String toJson(String query) throws Exception; + public static native String format(String query) throws Exception; static { try { diff --git a/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java b/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java index 4ca948b87959..5a8627d62c57 100644 --- a/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java +++ b/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java @@ -4,8 +4,8 @@ public class PrqlCompilerTest { @Test - public void compile() { - String found = PrqlCompiler.toSql("from table"); + public void compile() throws Exception { + String found = PrqlCompiler.toSql("from table", "sql.mysql", true, true); // remove signature found = found.substring(0, found.indexOf("\n\n--")); @@ -16,4 +16,9 @@ public void compile() { " table"; assert expected.equalsIgnoreCase(found); } + + @Test(expected = Exception.class) + public void compileWithError() throws Exception { + PrqlCompiler.toSql("from table | filter id >> 1", "sql.mysql", true, true); + } } diff --git a/prql-java/src/lib.rs b/prql-java/src/lib.rs index 6c59dfa9fb24..93e7052dc160 100644 --- a/prql-java/src/lib.rs +++ b/prql-java/src/lib.rs @@ -1,7 +1,8 @@ use jni::objects::{JClass, JString}; -use jni::sys::jstring; +use jni::sys::{jboolean, jstring}; use jni::JNIEnv; -use prql_compiler::{json, prql_to_pl, Options}; +use prql_compiler::{json, pl_to_prql, prql_to_pl, ErrorMessages, Options, Target}; +use std::str::FromStr; #[no_mangle] #[allow(non_snake_case)] @@ -9,16 +10,41 @@ pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_toSql( env: JNIEnv, _class: JClass, query: JString, + target: JString, + format: jboolean, + signature: jboolean, ) -> jstring { let prql_query: String = env .get_string(query) .expect("Couldn't get java string!") .into(); - let rs_sql_str: String = prql_compiler::compile(&prql_query, &Options::default()) - .expect("Couldn't compile query to prql!"); - env.new_string(rs_sql_str) - .expect("Couldn't create java string!") - .into_raw() + let target_str: String = env + .get_string(target) + .expect("Couldn't get java string") + .into(); + let prql_dialect: Target = Target::from_str(&target_str).unwrap_or(Target::Sql(None)); + let opt = Options { + format: format != 0, + target: prql_dialect, + signature_comment: signature != 0, + }; + let result = prql_compiler::compile(&prql_query, &opt); + java_string_with_exception(result, &env) +} + +#[no_mangle] +#[allow(non_snake_case)] +pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_format( + env: JNIEnv, + _class: JClass, + query: JString, +) -> jstring { + let prql_query: String = env + .get_string(query) + .expect("Couldn't get java string!") + .into(); + let result = prql_to_pl(&prql_query).and_then(pl_to_prql); + java_string_with_exception(result, &env) } #[no_mangle] @@ -32,9 +58,20 @@ pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_toJson( .get_string(query) .expect("Couldn't get java string!") .into(); - let rs_json_str: String = { prql_to_pl(&prql_query).and_then(json::from_pl) } - .expect("Couldn't get json from prql query!"); - env.new_string(rs_json_str) - .expect("Couldn't create java string!") - .into_raw() + let result = prql_to_pl(&prql_query).and_then(json::from_pl); + java_string_with_exception(result, &env) +} + +fn java_string_with_exception(result: Result, env: &JNIEnv) -> jstring { + if let Ok(text) = result { + env.new_string(text) + .expect("Couldn't create java string!") + .into_raw() + } else { + let exception = env.find_class("java/lang/Exception").unwrap(); + if let Err(e) = env.throw_new(exception, result.err().unwrap().to_string()) { + println!("Error throwing exception: {:?}", e); + } + std::ptr::null_mut() as jstring + } }