]> uap-core.de Git - note.git/commitdiff
implement dav query exec main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 18 Jul 2026 06:54:36 +0000 (08:54 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 18 Jul 2026 06:54:36 +0000 (08:54 +0200)
dav-rs/src/dav/ffi.rs
dav-rs/src/dav/query.rs
dav-rs/src/dav/resource.rs
dav-rs/src/dav/session.rs

index 982296c99130b2cebd158ea18489bde5824363a2..2e140aa31acd125e94b93ce3b7157bb4c8c6885b 100644 (file)
 use std::ffi::{c_char, c_int, c_long, c_void};
 use libc::time_t;
 
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct CxString {
+    pub ptr: *const c_char,
+    pub len: usize,
+}
+
+impl CxString {
+    pub fn new(s: &str) -> Self {
+        Self {
+            ptr: s.as_ptr() as *const c_char,
+            len: s.len(),
+        }
+    }
+}
+
 #[repr(C)]
 pub struct DavContext {
     _private: [u8; 0],
@@ -135,3 +152,17 @@ pub struct DavXmlAttr {
     pub value: *mut c_char,
     pub next: *mut DavXmlAttr,
 }
+
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct DavQLStatement {
+    _private: [u8; 0],
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct DavResult {
+    pub result: *mut DavResource,
+    pub status: c_int,
+}
index 62494408582ff243a8d1833f4c56fa7473c346f7..4a3d648e32aa999403f35deb78b9dc5970440e86 100644 (file)
  */
 #![allow(dead_code)]
 
-use crate::dav::session::Session;
+use std::ffi::{c_char, c_int, CString};
+use crate::dav::ffi::{CxString, DavQLStatement, DavResult, DavSession};
+use crate::dav::resource::Resource;
+use crate::dav::session::{DavError, Session};
+use crate::dav::utils::cstr2str;
 
 pub struct DavQuery {
     pub from: String,
     pub properties: Vec<String>,
-    pub filter: Vec<String>,
+    pub filter: Option<String>,
     pub depth: u16
 }
 
@@ -40,7 +44,7 @@ pub fn query(from: &str) -> DavQuery {
     DavQuery {
         from: from.to_string(),
         properties: Vec::new(),
-        filter: Vec::new(),
+        filter: None,
         depth: 1
     }
 }
@@ -56,22 +60,61 @@ impl DavQuery {
         self
     }
 
-    pub fn filter(&mut self, filter: Cmp) -> &mut Self {
-        self.filter.push(filter.cmp);
+    pub fn filter(&mut self, filter: &str) -> &mut Self {
+        self.filter = Some(filter.to_string());
         self
     }
-}
 
+    pub fn execute<'a>(&self, session: &Session) -> Result<Resource<'a>, DavError> {
+        let query = self.compile();
+        let cxstr = CxString::new(query.as_str());
 
-pub struct Cmp {
-    cmp: String,
-}
+        unsafe {
+            let stmt = dav_parse_statement(cxstr);
+            let errrorcode = dav_sql_statement_get_errorcode(stmt);
+            let result = if errrorcode != 0 {
+                let errrorcode = dav_sql_statement_get_errorcode(stmt);
+                let errormsg = cstr2str(dav_sql_statement_get_errormessage(stmt));
+                Err(DavError::QlError(format!("{} {}", errrorcode, errormsg)))
+            } else {
+                let stmt_result = dav_statement_exec(session.ptr, stmt);
+                if stmt_result.status == 0 && !stmt_result.result.is_null() {
+                    Ok(Resource::from_ptr(stmt_result.result))
+                } else {
+                    Err(session.get_error())
+                }
+            };
+            dav_free_statement(stmt);
+            result
+        }
+    }
+
+    fn compile(&self) -> String {
+        let properties = self
+            .properties
+            .iter()
+            .map(|p| format!("`{}`", p))
+            .collect::<Vec<_>>()
+            .join(", ");
 
+        let mut query = format!(
+            "select {} from {} with depth {}",
+            properties, self.from, self.depth
+        );
 
-impl Cmp {
-    pub fn eq_str(prop: &str, str: &str) -> Cmp {
-        Cmp {
-            cmp: format!("{} = '{}'", prop, str),
+        if let Some(filter) = &self.filter {
+            query.push_str(" where ");
+            query.push_str(filter);
         }
+
+        query
     }
-}
\ No newline at end of file
+}
+
+unsafe extern "C" {
+    fn dav_parse_statement(stmt: CxString) -> *mut DavQLStatement;
+    fn dav_free_statement(stmt: *mut DavQLStatement);
+    fn dav_sql_statement_get_errorcode(stmt: *const DavQLStatement) -> c_int;
+    fn dav_sql_statement_get_errormessage(stmt: *const DavQLStatement) -> *mut c_char;
+    fn dav_statement_exec(sn: *mut DavSession, st: *mut DavQLStatement, ...) -> DavResult;
+}
index 4a667c59b426a63aae9131a5e10d127eda1a5873..c0e01f7a8c2a3b52ba8c481e54a08bb649ffb47e 100644 (file)
@@ -42,6 +42,25 @@ pub struct Resource<'a> {
     pub base: ResourceRef<'a>
 }
 
+impl Resource<'_> {
+    pub fn from_ptr<'a>(ptr: *mut ffi::DavResource) -> Resource<'a> {
+        Resource {
+            base: ResourceRef {
+                ptr: ptr,
+                _marker: PhantomData,
+            }
+        }
+    }
+    
+    pub fn new<'a>(sn: &Session, path: &str) -> Resource<'a> {
+        let path = CString::new(path).unwrap();
+        unsafe {
+            let res = dav_resource_new(sn.ptr, path.as_ptr());
+            Resource::from_ptr(res)
+        }
+    }
+}
+
 pub struct ResourceRef<'a> {
     pub ptr: *mut ffi::DavResource,
     _marker: PhantomData<&'a Resource<'a>>,
index e744746e958be7a3e8b44efae4542fef209c169e..9e460fa617aeda3446d4aa1c1b3f63c93e4a1a25 100644 (file)
@@ -147,7 +147,7 @@ pub fn get_session_error(sn: *const ffi::DavSession) -> DavError {
         ffi::DavError::DavCouldntConnect => DavError::CouldntConnect,
         ffi::DavError::DavTimeout => DavError::Timeout,
         ffi::DavError::DavSslError => DavError::SslError,
-        ffi::DavError::DavQlError => DavError::QlError,
+        ffi::DavError::DavQlError => DavError::QlError("".to_string()),
         ffi::DavError::DavContentVerificationError => DavError::ContentVerificationError,
         ffi::DavError::DavPreconditionFailed => DavError::PreconditionFailed,
         ffi::DavError::DavRequestEntityTooLarge => DavError::RequestEntityTooLarge,
@@ -173,7 +173,7 @@ pub enum DavError {
     CouldntConnect,
     Timeout,
     SslError,
-    QlError,
+    QlError(String),
     ContentVerificationError,
     PreconditionFailed,
     RequestEntityTooLarge,