Skip to content

Commit 0bfd4e0

Browse files
committed
feat(tesseract): Use proxy object to resolve dependencies
1 parent 0dbf3bb commit 0bfd4e0

File tree

34 files changed

+1358
-221
lines changed

34 files changed

+1358
-221
lines changed

packages/cubejs-backend-native/js/index.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,22 @@ export const execSql = async (instance: SqlInterfaceInstance, sqlQuery: string,
358358

359359
export const buildSqlAndParams = (cubeEvaluator: any): String => {
360360
const native = loadNative();
361+
const safeCallFn = (fn: Function, thisArg: any, ...args: any[]) => {
362+
try {
363+
console.log("!!!! this: ", thisArg);
364+
console.log("!!!! args: ", args.length);
365+
return {
366+
result: fn.apply(thisArg, args),
367+
};
368+
} catch (e: any) {
369+
console.log("!!! error: ", e);
370+
return {
371+
error: e.toString(),
372+
};
373+
}
374+
};
361375

362-
return native.buildSqlAndParams(cubeEvaluator);
376+
return native.buildSqlAndParams(cubeEvaluator, safeCallFn);
363377
};
364378

365379
export type ResultRow = Record<string, string>;
@@ -405,6 +419,12 @@ export const getFinalQueryResultMulti = (transformDataArr: Object[], rows: any[]
405419
return native.getFinalQueryResultMulti(transformDataArr, rows, responseData);
406420
};
407421

422+
export const nativeProxy = (nativeResolver: any, resolveFunc: any) => new Proxy({}, {
423+
get(_, prop) {
424+
return resolveFunc(nativeResolver, prop);
425+
}
426+
});
427+
408428
export interface PyConfiguration {
409429
repositoryFactory?: (ctx: unknown) => Promise<unknown>,
410430
logger?: (msg: string, params: Record<string, any>) => void,

packages/cubejs-backend-native/src/node_export.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,18 @@ fn build_sql_and_params(cx: FunctionContext) -> JsResult<JsValue> {
471471
.unwrap()?,
472472
));
473473

474+
let safe_call_fn = neon_context_holder
475+
.with_context(|cx| {
476+
if let Ok(func) = cx.argument::<JsFunction>(1) {
477+
Some(func)
478+
} else {
479+
None
480+
}
481+
})
482+
.unwrap();
483+
484+
neon_context_holder.set_safe_call_fn(safe_call_fn).unwrap();
485+
474486
let context_holder = NativeContextHolder::<NeonInnerTypes<FunctionContext<'static>>>::new(
475487
neon_context_holder,
476488
);

packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,14 @@ export class BaseQuery {
670670
return res;
671671
}
672672

673+
nativeProxy(nativeResolver, resolveFunc) {
674+
return new Proxy({}, {
675+
get(_, prop) {
676+
return resolveFunc(nativeResolver, prop.valueOf());
677+
}
678+
});
679+
}
680+
673681
allCubeMembers(path) {
674682
const fromPath = this.cubeEvaluator.cubeFromPath(path);
675683

packages/cubejs-schema-compiler/src/compiler/CubeSymbols.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,25 @@ export class CubeSymbols {
645645
});
646646
}
647647

648+
isNameOfCube(name) {
649+
if (this.symbols[name]) {
650+
return true;
651+
} else {
652+
return false;
653+
}
654+
}
655+
656+
isNameOfSymbolInCube(cubeName, name) {
657+
const cube = this.symbols[cubeName];
658+
if (!cube) {
659+
return false;
660+
}
661+
if (cube[name]) {
662+
return true;
663+
}
664+
return false;
665+
}
666+
648667
filterGroupFunctionDep() {
649668
return (...filterParamArgs) => '';
650669
}

packages/cubejs-schema-compiler/test/integration/postgres/sql-generation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ describe('SQL Generation', () => {
549549
});
550550
`);
551551

552-
it('simple join', async () => {
552+
it('simple join 1', async () => {
553553
await compiler.compile();
554554

555555
console.log(joinGraph.buildJoin(['visitor_checkins', 'visitors']));

rust/cubenativeutils/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ convert_case = "0.6.0"
2222
[dependencies.neon]
2323
version = "=1"
2424
default-features = false
25-
features = ["napi-1", "napi-4", "napi-6", "futures"]
25+
features = ["napi-1", "napi-4", "napi-5", "napi-6", "futures"]

rust/cubenativeutils/src/wrappers/context.rs

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::{inner_types::InnerTypes, object_handle::NativeObjectHandle};
22
use cubesql::CubeError;
3+
use std::any::Any;
4+
use std::rc::Rc;
35

46
pub trait NativeContext<IT: InnerTypes>: Clone {
57
fn boolean(&self, v: bool) -> Result<IT::Boolean, CubeError>;
@@ -8,8 +10,30 @@ pub trait NativeContext<IT: InnerTypes>: Clone {
810
fn undefined(&self) -> Result<NativeObjectHandle<IT>, CubeError>;
911
fn empty_array(&self) -> Result<IT::Array, CubeError>;
1012
fn empty_struct(&self) -> Result<IT::Struct, CubeError>;
11-
//fn boxed<T: 'static>(&self, value: T) -> impl NativeBox<IT, T>;
1213
fn to_string_fn(&self, result: String) -> Result<IT::Function, CubeError>;
14+
15+
//IMPORTANT NOTE: Using of any native args in callback (as well as any native objects created
16+
//with NativeContextHolder passed to callback) outside of callback will cause error from
17+
//runtime lifetime check
18+
fn function<F>(&self, function: F) -> Result<IT::Function, CubeError>
19+
where
20+
F: Fn(
21+
Rc<NativeContextHolder<IT::FunctionIT>>,
22+
Vec<NativeObjectHandle<IT::FunctionIT>>,
23+
) -> Result<NativeObjectHandle<IT::FunctionIT>, CubeError>
24+
+ 'static;
25+
26+
fn boxed<T: NativeFinalize + 'static>(
27+
&self,
28+
object: T,
29+
) -> Result<impl NativeBox<IT, T>, CubeError>;
30+
fn global(&self, name: &str) -> Result<NativeObjectHandle<IT>, CubeError>;
31+
}
32+
33+
//Top level reference to ContextHolder for using in top level interfaces. Should be downcaster to
34+
//specific context for use
35+
pub trait NativeContextHolderRef {
36+
fn as_any(self: Rc<Self>) -> Rc<dyn Any>;
1337
}
1438

1539
#[derive(Clone)]
@@ -18,10 +42,10 @@ pub struct NativeContextHolder<IT: InnerTypes> {
1842
}
1943

2044
impl<IT: InnerTypes> NativeContextHolder<IT> {
21-
pub fn new(context: IT::Context) -> Self {
22-
Self { context }
45+
pub fn new(context: IT::Context) -> Rc<Self> {
46+
Rc::new(Self { context })
2347
}
24-
pub fn context(&self) -> &impl NativeContext<IT> {
48+
pub fn context(&self) -> &IT::Context {
2549
&self.context
2650
}
2751
pub fn boolean(&self, v: bool) -> Result<IT::Boolean, CubeError> {
@@ -42,8 +66,54 @@ impl<IT: InnerTypes> NativeContextHolder<IT> {
4266
pub fn empty_struct(&self) -> Result<IT::Struct, CubeError> {
4367
self.context.empty_struct()
4468
}
45-
#[allow(dead_code)]
4669
pub fn to_string_fn(&self, result: String) -> Result<IT::Function, CubeError> {
4770
self.context.to_string_fn(result)
4871
}
72+
pub fn function<F>(&self, function: F) -> Result<IT::Function, CubeError>
73+
where
74+
F: Fn(
75+
Rc<NativeContextHolder<IT::FunctionIT>>,
76+
Vec<NativeObjectHandle<IT::FunctionIT>>,
77+
) -> Result<NativeObjectHandle<IT::FunctionIT>, CubeError>
78+
+ 'static,
79+
{
80+
self.context.function(function)
81+
}
82+
pub fn boxed<T: NativeFinalize + 'static>(
83+
&self,
84+
object: T,
85+
) -> Result<impl NativeBox<IT, T> + '_, CubeError> {
86+
self.context.boxed(object)
87+
}
88+
pub fn global(&self, name: &str) -> Result<NativeObjectHandle<IT>, CubeError> {
89+
self.context.global(name)
90+
}
91+
pub fn as_context_ref(self: &Rc<Self>) -> Rc<dyn NativeContextHolderRef> {
92+
self.clone()
93+
}
94+
}
95+
96+
impl<IT: InnerTypes> NativeContextHolderRef for NativeContextHolder<IT> {
97+
fn as_any(self: Rc<Self>) -> Rc<dyn Any> {
98+
self.clone()
99+
}
100+
}
101+
102+
//FIXME For now we don't allow js calls on finalize, so it's only to clean rust resources
103+
pub trait NativeFinalize: Sized {
104+
fn finalize(self) {}
105+
}
106+
107+
impl<T: NativeFinalize> NativeFinalize for std::rc::Rc<T> {
108+
fn finalize(self) {
109+
if let Ok(v) = std::rc::Rc::try_unwrap(self) {
110+
v.finalize();
111+
}
112+
}
113+
}
114+
115+
impl<T: NativeFinalize> NativeFinalize for std::cell::RefCell<T> {
116+
fn finalize(self) {
117+
self.into_inner().finalize();
118+
}
49119
}

rust/cubenativeutils/src/wrappers/inner_types.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::{
22
context::NativeContext,
33
object::{
4-
NativeArray, NativeBoolean, NativeFunction, NativeNumber, NativeObject, NativeString,
5-
NativeStruct,
4+
NativeArray, NativeBoolean, NativeFunction, NativeNumber, NativeObject, NativeRoot,
5+
NativeString, NativeStruct,
66
},
77
};
88
pub trait InnerTypes: Clone + 'static {
@@ -14,4 +14,6 @@ pub trait InnerTypes: Clone + 'static {
1414
type Function: NativeFunction<Self>;
1515
type Number: NativeNumber<Self>;
1616
type Context: NativeContext<Self>;
17+
type FunctionIT: InnerTypes;
18+
type Root: NativeRoot<Self>;
1719
}

rust/cubenativeutils/src/wrappers/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ pub mod inner_types;
33
pub mod neon;
44
pub mod object;
55
pub mod object_handle;
6+
pub mod root_holder;
67
pub mod serializer;
78

8-
pub use context::NativeContextHolder;
9+
pub use context::{NativeContextHolder, NativeContextHolderRef};
910
pub use object::{
10-
NativeArray, NativeBoolean, NativeFunction, NativeNumber, NativeString, NativeStruct,
11-
NativeType,
11+
NativeArray, NativeBoolean, NativeFunction, NativeNumber, NativeRoot, NativeString,
12+
NativeStruct, NativeType,
1213
};
1314
pub use object_handle::NativeObjectHandle;
15+
pub use root_holder::{RootHolder, Rootable};

0 commit comments

Comments
 (0)