Skip to main content

ri/java/classes/
database.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18//! # Database Module JNI Bindings
19//!
20//! JNI bindings for Ri database classes.
21
22use jni::JNIEnv;
23use jni::objects::{JClass, JString};
24use jni::sys::{jlong, jboolean, jint, jdouble, jstring};
25use crate::database::{RiDatabaseConfig, RiDatabasePool, RiDatabaseMetrics, RiDynamicPoolConfig, RiDBRow, RiDBResult, RiDatabaseMigration};
26use crate::java::exception::check_not_null;
27
28// =============================================================================
29// RiDatabaseConfig JNI Bindings
30// =============================================================================
31
32#[no_mangle]
33pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseConfig_new0(
34    _env: JNIEnv,
35    _class: JClass,
36) -> jlong {
37    let config = Box::new(RiDatabaseConfig::default());
38    Box::into_raw(config) as jlong
39}
40
41#[no_mangle]
42pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseConfig_free0(
43    _env: JNIEnv,
44    _class: JClass,
45    ptr: jlong,
46) {
47    if ptr != 0 {
48        unsafe {
49            let _ = Box::from_raw(ptr as *mut RiDatabaseConfig);
50        }
51    }
52}
53
54// =============================================================================
55// RiDatabasePool JNI Bindings
56// =============================================================================
57
58#[no_mangle]
59pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_new0(
60    mut env: JNIEnv,
61    _class: JClass,
62    config_ptr: jlong,
63) -> jlong {
64    if !check_not_null(&mut env, config_ptr, "RiDatabaseConfig") {
65        return 0;
66    }
67
68    let config = unsafe { &*(config_ptr as *const crate::database::RiDatabaseConfig) };
69
70    match crate::database::RiDatabasePool::new(config.clone()) {
71        Ok(pool) => {
72            let boxed = Box::new(pool);
73            Box::into_raw(boxed) as jlong
74        }
75        Err(e) => {
76            throw_ri_error(&mut env, &e.to_string());
77            0
78        }
79    }
80}
81
82#[no_mangle]
83pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_execute0(
84    mut env: JNIEnv,
85    _class: JClass,
86    ptr: jlong,
87    sql: JString,
88) -> jlong {
89    if !check_not_null(&mut env, ptr, "RiDatabasePool") {
90        return 0;
91    }
92    
93    let _sql_str: String = env.get_string(&sql)
94        .expect("Failed to get SQL")
95        .into();
96    
97    0
98}
99
100#[no_mangle]
101pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_query0(
102    mut env: JNIEnv,
103    _class: JClass,
104    ptr: jlong,
105    sql: JString,
106) -> jlong {
107    if !check_not_null(&mut env, ptr, "RiDatabasePool") {
108        return 0;
109    }
110    
111    let _sql_str: String = env.get_string(&sql)
112        .expect("Failed to get SQL")
113        .into();
114    
115    let result = Box::new(RiDBResult::new());
116    Box::into_raw(result) as jlong
117}
118
119#[no_mangle]
120pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_getMetrics0(
121    mut env: JNIEnv,
122    _class: JClass,
123    ptr: jlong,
124) -> jlong {
125    if !check_not_null(&mut env, ptr, "RiDatabasePool") {
126        return 0;
127    }
128    
129    let metrics = Box::new(RiDatabaseMetrics::default());
130    Box::into_raw(metrics) as jlong
131}
132
133#[no_mangle]
134pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_getUtilizationRate0(
135    mut env: JNIEnv,
136    _class: JClass,
137    ptr: jlong,
138) -> jdouble {
139    if !check_not_null(&mut env, ptr, "RiDatabasePool") {
140        return 0.0;
141    }
142    
143    0.0
144}
145
146#[no_mangle]
147pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_getDynamicConfig0(
148    mut env: JNIEnv,
149    _class: JClass,
150    ptr: jlong,
151) -> jlong {
152    if !check_not_null(&mut env, ptr, "RiDatabasePool") {
153        return 0;
154    }
155    
156    let config = Box::new(RiDynamicPoolConfig::default());
157    Box::into_raw(config) as jlong
158}
159
160#[no_mangle]
161pub extern "system" fn Java_com_dunimd_ri_database_RiDatabasePool_free0(
162    _env: JNIEnv,
163    _class: JClass,
164    ptr: jlong,
165) {
166    if ptr != 0 {
167        unsafe {
168            let _ = Box::from_raw(ptr as *mut RiDatabasePool);
169        }
170    }
171}
172
173// =============================================================================
174// RiDBRow JNI Bindings
175// =============================================================================
176
177#[no_mangle]
178pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_getString0(
179    mut env: JNIEnv,
180    _class: JClass,
181    ptr: jlong,
182    name: JString,
183) -> jstring {
184    if !check_not_null(&mut env, ptr, "RiDBRow") {
185        return std::ptr::null_mut();
186    }
187    
188    let _name_str: String = env.get_string(&name)
189        .expect("Failed to get column name")
190        .into();
191    
192    std::ptr::null_mut()
193}
194
195#[no_mangle]
196pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_getInt0(
197    mut env: JNIEnv,
198    _class: JClass,
199    ptr: jlong,
200    name: JString,
201) -> jint {
202    if !check_not_null(&mut env, ptr, "RiDBRow") {
203        return 0;
204    }
205    
206    let _name_str: String = env.get_string(&name)
207        .expect("Failed to get column name")
208        .into();
209    
210    0
211}
212
213#[no_mangle]
214pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_getLong0(
215    mut env: JNIEnv,
216    _class: JClass,
217    ptr: jlong,
218    name: JString,
219) -> jlong {
220    if !check_not_null(&mut env, ptr, "RiDBRow") {
221        return 0;
222    }
223    
224    let _name_str: String = env.get_string(&name)
225        .expect("Failed to get column name")
226        .into();
227    
228    0
229}
230
231#[no_mangle]
232pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_getDouble0(
233    mut env: JNIEnv,
234    _class: JClass,
235    ptr: jlong,
236    name: JString,
237) -> jdouble {
238    if !check_not_null(&mut env, ptr, "RiDBRow") {
239        return 0.0;
240    }
241    
242    let _name_str: String = env.get_string(&name)
243        .expect("Failed to get column name")
244        .into();
245    
246    0.0
247}
248
249#[no_mangle]
250pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_getBoolean0(
251    mut env: JNIEnv,
252    _class: JClass,
253    ptr: jlong,
254    name: JString,
255) -> jboolean {
256    if !check_not_null(&mut env, ptr, "RiDBRow") {
257        return 0;
258    }
259    
260    let _name_str: String = env.get_string(&name)
261        .expect("Failed to get column name")
262        .into();
263    
264    0
265}
266
267#[no_mangle]
268pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_isNull0(
269    mut env: JNIEnv,
270    _class: JClass,
271    ptr: jlong,
272    name: JString,
273) -> jboolean {
274    if !check_not_null(&mut env, ptr, "RiDBRow") {
275        return 1;
276    }
277    
278    let _name_str: String = env.get_string(&name)
279        .expect("Failed to get column name")
280        .into();
281    
282    1
283}
284
285#[no_mangle]
286pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_hasColumn0(
287    mut env: JNIEnv,
288    _class: JClass,
289    ptr: jlong,
290    name: JString,
291) -> jboolean {
292    if !check_not_null(&mut env, ptr, "RiDBRow") {
293        return 0;
294    }
295    
296    let _name_str: String = env.get_string(&name)
297        .expect("Failed to get column name")
298        .into();
299    
300    0
301}
302
303#[no_mangle]
304pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_getColumnCount0(
305    mut env: JNIEnv,
306    _class: JClass,
307    ptr: jlong,
308) -> jint {
309    if !check_not_null(&mut env, ptr, "RiDBRow") {
310        return 0;
311    }
312    
313    0
314}
315
316#[no_mangle]
317pub extern "system" fn Java_com_dunimd_ri_database_RiDBRow_free0(
318    _env: JNIEnv,
319    _class: JClass,
320    ptr: jlong,
321) {
322    if ptr != 0 {
323        unsafe {
324            let _ = Box::from_raw(ptr as *mut RiDBRow);
325        }
326    }
327}
328
329// =============================================================================
330// RiDBResult JNI Bindings
331// =============================================================================
332
333#[no_mangle]
334pub extern "system" fn Java_com_dunimd_ri_database_RiDBResult_getRowCount0(
335    mut env: JNIEnv,
336    _class: JClass,
337    ptr: jlong,
338) -> jint {
339    if !check_not_null(&mut env, ptr, "RiDBResult") {
340        return 0;
341    }
342    
343    let result = unsafe { &*(ptr as *const RiDBResult) };
344    result.row_count() as jint
345}
346
347#[no_mangle]
348pub extern "system" fn Java_com_dunimd_ri_database_RiDBResult_getAffectedRows0(
349    mut env: JNIEnv,
350    _class: JClass,
351    ptr: jlong,
352) -> jlong {
353    if !check_not_null(&mut env, ptr, "RiDBResult") {
354        return 0;
355    }
356    
357    let result = unsafe { &*(ptr as *const RiDBResult) };
358    result.affected_rows()
359}
360
361#[no_mangle]
362pub extern "system" fn Java_com_dunimd_ri_database_RiDBResult_getLastInsertId0(
363    mut env: JNIEnv,
364    _class: JClass,
365    ptr: jlong,
366) -> jlong {
367    if !check_not_null(&mut env, ptr, "RiDBResult") {
368        return -1;
369    }
370    
371    let result = unsafe { &*(ptr as *const RiDBResult) };
372    result.last_insert_id().unwrap_or(-1)
373}
374
375#[no_mangle]
376pub extern "system" fn Java_com_dunimd_ri_database_RiDBResult_isEmpty0(
377    mut env: JNIEnv,
378    _class: JClass,
379    ptr: jlong,
380) -> jboolean {
381    if !check_not_null(&mut env, ptr, "RiDBResult") {
382        return 1;
383    }
384    
385    let result = unsafe { &*(ptr as *const RiDBResult) };
386    result.is_empty() as jboolean
387}
388
389#[no_mangle]
390pub extern "system" fn Java_com_dunimd_ri_database_RiDBResult_getRow0(
391    mut env: JNIEnv,
392    _class: JClass,
393    ptr: jlong,
394    index: jint,
395) -> jlong {
396    if !check_not_null(&mut env, ptr, "RiDBResult") {
397        return 0;
398    }
399    
400    let result = unsafe { &*(ptr as *const RiDBResult) };
401    if let Some(_row) = result.get(index as usize) {
402        let row = Box::new(RiDBRow::new());
403        return Box::into_raw(row) as jlong;
404    }
405    
406    0
407}
408
409#[no_mangle]
410pub extern "system" fn Java_com_dunimd_ri_database_RiDBResult_free0(
411    _env: JNIEnv,
412    _class: JClass,
413    ptr: jlong,
414) {
415    if ptr != 0 {
416        unsafe {
417            let _ = Box::from_raw(ptr as *mut RiDBResult);
418        }
419    }
420}
421
422// =============================================================================
423// RiDatabaseMetrics JNI Bindings
424// =============================================================================
425
426#[no_mangle]
427pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getActiveConnections0(
428    mut env: JNIEnv,
429    _class: JClass,
430    ptr: jlong,
431) -> jlong {
432    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
433        return 0;
434    }
435    
436    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
437    metrics.active_connections
438}
439
440#[no_mangle]
441pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getIdleConnections0(
442    mut env: JNIEnv,
443    _class: JClass,
444    ptr: jlong,
445) -> jlong {
446    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
447        return 0;
448    }
449    
450    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
451    metrics.idle_connections
452}
453
454#[no_mangle]
455pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getTotalConnections0(
456    mut env: JNIEnv,
457    _class: JClass,
458    ptr: jlong,
459) -> jlong {
460    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
461        return 0;
462    }
463    
464    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
465    metrics.total_connections
466}
467
468#[no_mangle]
469pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getQueriesExecuted0(
470    mut env: JNIEnv,
471    _class: JClass,
472    ptr: jlong,
473) -> jlong {
474    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
475        return 0;
476    }
477    
478    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
479    metrics.queries_executed
480}
481
482#[no_mangle]
483pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getQueryDurationMs0(
484    mut env: JNIEnv,
485    _class: JClass,
486    ptr: jlong,
487) -> jdouble {
488    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
489        return 0.0;
490    }
491    
492    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
493    metrics.query_duration_ms
494}
495
496#[no_mangle]
497pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getErrors0(
498    mut env: JNIEnv,
499    _class: JClass,
500    ptr: jlong,
501) -> jlong {
502    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
503        return 0;
504    }
505    
506    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
507    metrics.errors
508}
509
510#[no_mangle]
511pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_getUtilizationRate0(
512    mut env: JNIEnv,
513    _class: JClass,
514    ptr: jlong,
515) -> jdouble {
516    if !check_not_null(&mut env, ptr, "RiDatabaseMetrics") {
517        return 0.0;
518    }
519    
520    let metrics = unsafe { &*(ptr as *const RiDatabaseMetrics) };
521    metrics.utilization_rate
522}
523
524#[no_mangle]
525pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMetrics_free0(
526    _env: JNIEnv,
527    _class: JClass,
528    ptr: jlong,
529) {
530    if ptr != 0 {
531        unsafe {
532            let _ = Box::from_raw(ptr as *mut RiDatabaseMetrics);
533        }
534    }
535}
536
537// =============================================================================
538// RiDynamicPoolConfig JNI Bindings
539// =============================================================================
540
541#[no_mangle]
542pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_new0(
543    _env: JNIEnv,
544    _class: JClass,
545) -> jlong {
546    let config = Box::new(RiDynamicPoolConfig::default());
547    Box::into_raw(config) as jlong
548}
549
550#[no_mangle]
551pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_isDynamicScalingEnabled0(
552    mut env: JNIEnv,
553    _class: JClass,
554    ptr: jlong,
555) -> jboolean {
556    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
557        return 0;
558    }
559    
560    let config = unsafe { &*(ptr as *const RiDynamicPoolConfig) };
561    config.enable_dynamic_scaling as jboolean
562}
563
564#[no_mangle]
565pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_setDynamicScalingEnabled0(
566    mut env: JNIEnv,
567    _class: JClass,
568    ptr: jlong,
569    enabled: jboolean,
570) {
571    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
572        return;
573    }
574    
575    let config = unsafe { &mut *(ptr as *mut RiDynamicPoolConfig) };
576    config.enable_dynamic_scaling = enabled != 0;
577}
578
579#[no_mangle]
580pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_getScaleUpThreshold0(
581    mut env: JNIEnv,
582    _class: JClass,
583    ptr: jlong,
584) -> jdouble {
585    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
586        return 0.0;
587    }
588    
589    let config = unsafe { &*(ptr as *const RiDynamicPoolConfig) };
590    config.scale_up_threshold
591}
592
593#[no_mangle]
594pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_setScaleUpThreshold0(
595    mut env: JNIEnv,
596    _class: JClass,
597    ptr: jlong,
598    threshold: jdouble,
599) {
600    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
601        return;
602    }
603    
604    let config = unsafe { &mut *(ptr as *mut RiDynamicPoolConfig) };
605    config.scale_up_threshold = threshold;
606}
607
608#[no_mangle]
609pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_getScaleDownThreshold0(
610    mut env: JNIEnv,
611    _class: JClass,
612    ptr: jlong,
613) -> jdouble {
614    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
615        return 0.0;
616    }
617    
618    let config = unsafe { &*(ptr as *const RiDynamicPoolConfig) };
619    config.scale_down_threshold
620}
621
622#[no_mangle]
623pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_setScaleDownThreshold0(
624    mut env: JNIEnv,
625    _class: JClass,
626    ptr: jlong,
627    threshold: jdouble,
628) {
629    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
630        return;
631    }
632    
633    let config = unsafe { &mut *(ptr as *mut RiDynamicPoolConfig) };
634    config.scale_down_threshold = threshold;
635}
636
637#[no_mangle]
638pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_getMinConnections0(
639    mut env: JNIEnv,
640    _class: JClass,
641    ptr: jlong,
642) -> jint {
643    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
644        return 0;
645    }
646    
647    let config = unsafe { &*(ptr as *const RiDynamicPoolConfig) };
648    config.min_connections as jint
649}
650
651#[no_mangle]
652pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_setMinConnections0(
653    mut env: JNIEnv,
654    _class: JClass,
655    ptr: jlong,
656    min: jint,
657) {
658    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
659        return;
660    }
661    
662    let config = unsafe { &mut *(ptr as *mut RiDynamicPoolConfig) };
663    config.min_connections = min as u32;
664}
665
666#[no_mangle]
667pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_getMaxConnections0(
668    mut env: JNIEnv,
669    _class: JClass,
670    ptr: jlong,
671) -> jint {
672    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
673        return 0;
674    }
675    
676    let config = unsafe { &*(ptr as *const RiDynamicPoolConfig) };
677    config.max_connections as jint
678}
679
680#[no_mangle]
681pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_setMaxConnections0(
682    mut env: JNIEnv,
683    _class: JClass,
684    ptr: jlong,
685    max: jint,
686) {
687    if !check_not_null(&mut env, ptr, "RiDynamicPoolConfig") {
688        return;
689    }
690    
691    let config = unsafe { &mut *(ptr as *mut RiDynamicPoolConfig) };
692    config.max_connections = max as u32;
693}
694
695#[no_mangle]
696pub extern "system" fn Java_com_dunimd_ri_database_RiDynamicPoolConfig_free0(
697    _env: JNIEnv,
698    _class: JClass,
699    ptr: jlong,
700) {
701    if ptr != 0 {
702        unsafe {
703            let _ = Box::from_raw(ptr as *mut RiDynamicPoolConfig);
704        }
705    }
706}
707
708// =============================================================================
709// RiDatabaseMigration JNI Bindings
710// =============================================================================
711
712#[no_mangle]
713pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMigration_new0(
714    mut env: JNIEnv,
715    _class: JClass,
716    version: jint,
717    name: JString,
718    sql_up: JString,
719    sql_down: JString,
720) -> jlong {
721    let name_str: String = env.get_string(&name)
722        .expect("Failed to get name")
723        .into();
724    let sql_up_str: String = env.get_string(&sql_up)
725        .expect("Failed to get SQL up")
726        .into();
727    let sql_down_str: Option<String> = if sql_down.is_null() {
728        None
729    } else {
730        Some(env.get_string(&sql_down).expect("Failed to get SQL down").into())
731    };
732    
733    let migration = Box::new(RiDatabaseMigration::new(
734        version as u32,
735        &name_str,
736        &sql_up_str,
737        sql_down_str.as_deref(),
738    ));
739    Box::into_raw(migration) as jlong
740}
741
742#[no_mangle]
743pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMigration_getVersion0(
744    mut env: JNIEnv,
745    _class: JClass,
746    ptr: jlong,
747) -> jint {
748    if !check_not_null(&mut env, ptr, "RiDatabaseMigration") {
749        return 0;
750    }
751    
752    let migration = unsafe { &*(ptr as *const RiDatabaseMigration) };
753    migration.version as jint
754}
755
756#[no_mangle]
757pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMigration_getName0<'local>(
758    mut env: JNIEnv<'local>,
759    _class: JClass<'local>,
760    ptr: jlong,
761) -> jstring {
762    if !check_not_null(&mut env, ptr, "RiDatabaseMigration") {
763        return std::ptr::null_mut();
764    }
765    
766    let migration = unsafe { &*(ptr as *const RiDatabaseMigration) };
767    env.new_string(&migration.name).unwrap().into_raw()
768}
769
770#[no_mangle]
771pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMigration_getSqlUp0<'local>(
772    mut env: JNIEnv<'local>,
773    _class: JClass<'local>,
774    ptr: jlong,
775) -> jstring {
776    if !check_not_null(&mut env, ptr, "RiDatabaseMigration") {
777        return std::ptr::null_mut();
778    }
779    
780    let migration = unsafe { &*(ptr as *const RiDatabaseMigration) };
781    env.new_string(&migration.sql_up).unwrap().into_raw()
782}
783
784#[no_mangle]
785pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMigration_getSqlDown0<'local>(
786    mut env: JNIEnv<'local>,
787    _class: JClass<'local>,
788    ptr: jlong,
789) -> jstring {
790    if !check_not_null(&mut env, ptr, "RiDatabaseMigration") {
791        return std::ptr::null_mut();
792    }
793    
794    let migration = unsafe { &*(ptr as *const RiDatabaseMigration) };
795    match &migration.sql_down {
796        Some(sql) => env.new_string(sql).unwrap().into_raw(),
797        None => std::ptr::null_mut(),
798    }
799}
800
801#[no_mangle]
802pub extern "system" fn Java_com_dunimd_ri_database_RiDatabaseMigration_free0(
803    _env: JNIEnv,
804    _class: JClass,
805    ptr: jlong,
806) {
807    if ptr != 0 {
808        unsafe {
809            let _ = Box::from_raw(ptr as *mut RiDatabaseMigration);
810        }
811    }
812}