You've already forked OpenIntegrations
mirror of
https://github.com/Bayselonarrend/OpenIntegrations.git
synced 2025-08-10 22:41:43 +02:00
Переработка MSSQL и PG для #72
This commit is contained in:
22
src/addins/mssql/Cargo.lock
generated
22
src/addins/mssql/Cargo.lock
generated
@@ -281,6 +281,26 @@ version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "7.0.0-rc2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a1e35a65fe0538a60167f0ada6e195ad5d477f6ddae273943596d4a1a5730b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"equivalent",
|
||||
"hashbrown 0.15.2",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dateparser"
|
||||
version = "0.2.1"
|
||||
@@ -813,6 +833,7 @@ dependencies = [
|
||||
"addin1c",
|
||||
"base64",
|
||||
"chrono",
|
||||
"dashmap",
|
||||
"dateparser",
|
||||
"serde_json",
|
||||
"thread-id",
|
||||
@@ -1535,6 +1556,7 @@ version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@@ -21,6 +21,7 @@ tokio-util = { version = "0.7", features = ["compat"] }
|
||||
serde_json = "1.0"
|
||||
chrono = "0.4"
|
||||
base64 = "0.21"
|
||||
uuid = "1.17.0"
|
||||
uuid = { version = "1.17.0", features = ["v4"] }
|
||||
dateparser = "0.2.1"
|
||||
thread-id = "5.0.0"
|
||||
thread-id = "5.0.0"
|
||||
dashmap = "7.0.0-rc2"
|
@@ -1,13 +1,13 @@
|
||||
"MAIN ---"
|
||||
linux-vdso.so.1 (0x00007fffb1fbc000)
|
||||
libssl.so.3 => /lib64/libssl.so.3 (0x00007d48d3200000)
|
||||
libcrypto.so.3 => /lib64/libcrypto.so.3 (0x00007d48d2a00000)
|
||||
libm.so.6 => /lib64/libm.so.6 (0x00007d48d2600000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007d48d2200000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x00007d48d1e00000)
|
||||
libdl.so.2 => /lib64/libdl.so.2 (0x00007d48d1a00000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007d48d3800000)
|
||||
libz.so.1 => /lib64/libz.so.1 (0x00007d48d1600000)
|
||||
linux-vdso.so.1 (0x00007fff79bfd000)
|
||||
libssl.so.3 => /lib64/libssl.so.3 (0x0000793932800000)
|
||||
libcrypto.so.3 => /lib64/libcrypto.so.3 (0x0000793932000000)
|
||||
libm.so.6 => /lib64/libm.so.6 (0x0000793931c00000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000793931800000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x0000793931400000)
|
||||
libdl.so.2 => /lib64/libdl.so.2 (0x0000793931000000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x0000793932e00000)
|
||||
libz.so.1 => /lib64/libz.so.1 (0x0000793930c00000)
|
||||
GLIBC_2.2.5
|
||||
GLIBC_2.12
|
||||
GLIBC_2.3
|
||||
|
@@ -29,9 +29,9 @@ enum BackendCommand {
|
||||
},
|
||||
Execute {
|
||||
query: String,
|
||||
params_json: String,
|
||||
params_json: Vec<Value>,
|
||||
force_result: bool,
|
||||
response: Sender<String>,
|
||||
response: Sender<Result<Option<Vec<Value>>, String>>,
|
||||
},
|
||||
Shutdown,
|
||||
}
|
||||
@@ -95,10 +95,10 @@ impl MSSQLBackend {
|
||||
BackendCommand::Execute { query, params_json, force_result, response } => {
|
||||
let result = if let Some(client) = &mut client {
|
||||
rt.block_on(async {
|
||||
Self::execute_query_internal(client, &query, ¶ms_json, force_result).await
|
||||
Self::execute_query_internal(client, &query, params_json, force_result).await
|
||||
})
|
||||
} else {
|
||||
json!({"result": false, "error": "Not connected"}).to_string()
|
||||
Err("Not connected".to_string())
|
||||
};
|
||||
|
||||
let _ = response.send(result);
|
||||
@@ -116,6 +116,7 @@ impl MSSQLBackend {
|
||||
}
|
||||
|
||||
pub fn connect(&self, conn_str: String, use_tls: bool, accept_invalid_certs: bool, ca_cert_path: String) -> String {
|
||||
|
||||
let (response_tx, response_rx) = mpsc::channel();
|
||||
let sending = self.tx.send(BackendCommand::Connect {
|
||||
conn_str,
|
||||
@@ -133,9 +134,9 @@ impl MSSQLBackend {
|
||||
response_rx.recv().unwrap_or_else(|e| format!("Response receiver error: {}", e.to_string()))
|
||||
}
|
||||
|
||||
pub fn execute_query(&self, query: String, params_json: String, force_result: bool) -> String {
|
||||
pub fn execute_query(&self, query: String, params_json: Vec<Value>, force_result: bool) -> Result<Option<Vec<Value>>, String> {
|
||||
|
||||
let (response_tx, response_rx) = mpsc::channel();
|
||||
let (response_tx, response_rx) = mpsc::channel::<Result<Option<Vec<Value>>, String>>();
|
||||
|
||||
let sending = self.tx.send(BackendCommand::Execute {
|
||||
query,
|
||||
@@ -144,30 +145,30 @@ impl MSSQLBackend {
|
||||
response: response_tx,
|
||||
});
|
||||
|
||||
match sending{
|
||||
Err(e) => {return format!("Sending error: {}", e.to_string())}
|
||||
match sending {
|
||||
Err(e) => {
|
||||
let error = format!("Sending error: {}", e.to_string());
|
||||
return Err(error)
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
response_rx.recv().unwrap_or_else(|e| format!("Response receiver error: {}", e.to_string()))
|
||||
response_rx.recv().unwrap_or_else(|e| {
|
||||
let error = format!("Response receiver error: {}", e.to_string());
|
||||
Err(error)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
async fn execute_query_internal(
|
||||
client: &mut Client<Compat<TcpStream>>,
|
||||
query: &str,
|
||||
params_json: &str,
|
||||
params_json: Vec<Value>,
|
||||
force_result: bool,
|
||||
) -> String {
|
||||
let mut parsed_params: Value = match serde_json::from_str(params_json) {
|
||||
Ok(params) => params,
|
||||
Err(e) => return Self::format_json_error(&e.to_string()),
|
||||
};
|
||||
) -> Result<Option<Vec<Value>>, String> {
|
||||
|
||||
let params_array = match parsed_params.as_array_mut() {
|
||||
Some(array) => Self::process_mssql_params(array),
|
||||
None => return Self::format_json_error("Parameters must be a JSON array"),
|
||||
};
|
||||
let mut params = params_json;
|
||||
let params_array = Self::process_mssql_params(&mut params);
|
||||
|
||||
let normalized_query = query.trim_start().to_uppercase();
|
||||
let params_refs: Vec<&dyn ToSql> = params_array.iter().map(|b| b.as_ref()).collect();
|
||||
@@ -177,11 +178,11 @@ impl MSSQLBackend {
|
||||
Ok(stream) => {
|
||||
let rows = match stream.into_results().await {
|
||||
Ok(rows) => rows.into_iter().flatten().collect(),
|
||||
Err(e) => return Self::format_json_error(&e.to_string()),
|
||||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
Self::rows_to_json_array(rows)
|
||||
Ok(Some(Self::rows_to_json_array(rows)))
|
||||
},
|
||||
Err(e) => Self::format_json_error(&e.to_string()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
} else if normalized_query == "BEGIN TRAN"
|
||||
|| normalized_query == "COMMIT;"
|
||||
@@ -189,27 +190,20 @@ impl MSSQLBackend {
|
||||
|| normalized_query == "BEGIN TRANSACTION"{
|
||||
|
||||
match client.simple_query(query).await {
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => Self::format_json_error(&e.to_string()),
|
||||
Ok(_) => Ok(None),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
match client.execute(query, ¶ms_refs).await {
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => Self::format_json_error(&e.to_string()),
|
||||
Ok(_) => Ok(None),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn format_json_error(error: &str) -> String {
|
||||
json!({
|
||||
"result": false,
|
||||
"error": error
|
||||
}).to_string()
|
||||
}
|
||||
|
||||
fn rows_to_json_array(rows: Vec<Row>) -> String {
|
||||
fn rows_to_json_array(rows: Vec<Row>) -> Vec<Value> {
|
||||
let mut json_array = Vec::new();
|
||||
|
||||
for row in rows {
|
||||
@@ -222,7 +216,7 @@ impl MSSQLBackend {
|
||||
json_array.push(Value::Object(json_obj));
|
||||
}
|
||||
|
||||
json!({ "result": true, "data": json_array }).to_string()
|
||||
json_array
|
||||
}
|
||||
|
||||
fn from_sql_to_json(row: &Row, index: usize, column: &Column) -> Value {
|
||||
|
84
src/addins/mssql/src/component/dataset.rs
Normal file
84
src/addins/mssql/src/component/dataset.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use dashmap::DashMap;
|
||||
use serde_json::Value;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct Datasets {
|
||||
data: Arc<DashMap<String, QueryData>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QueryData {
|
||||
pub results: Vec<Value>,
|
||||
pub params: Vec<Value>,
|
||||
pub text: String,
|
||||
pub force_result: bool,
|
||||
}
|
||||
|
||||
impl Datasets {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: Arc::new(DashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_query(&self) -> String {
|
||||
let key = Uuid::new_v4().to_string();
|
||||
let query = QueryData::new();
|
||||
self.data.insert(key.clone(), query);
|
||||
key
|
||||
}
|
||||
|
||||
pub fn get_query(&self, key: &str) -> Option<QueryData> {
|
||||
self.data.get(key).map(|guard| guard.value().clone())
|
||||
}
|
||||
|
||||
pub fn set_results(&self, key: &str, values: Vec<Value>) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.results = values;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_param(&self, key: &str, value: Value) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.params.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_text(&self, key: &str, text: &str) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.text = text.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_force_result(&self, key: &str, enabled: bool) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.force_result = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self, key: &str) -> Option<usize> {
|
||||
self.data.get(key).map(|entry| entry.results.len())
|
||||
}
|
||||
|
||||
pub fn remove(&self, key: &str) {
|
||||
self.data.remove(key);
|
||||
}
|
||||
|
||||
pub fn get_row(&self, key: &str, index: usize) -> Option<String> {
|
||||
let entry = self.data.get(key)?;
|
||||
let value = entry.results.get(index)?;
|
||||
serde_json::to_string(value).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryData {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
results: Vec::new(),
|
||||
params: Vec::new(),
|
||||
text: String::new(),
|
||||
force_result: false,
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,24 +1,36 @@
|
||||
mod backend;
|
||||
mod dataset;
|
||||
|
||||
use addin1c::{name, Variant};
|
||||
use crate::core::getset;
|
||||
use serde_json::json;
|
||||
use serde_json::{json, Value};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::component::dataset::Datasets;
|
||||
|
||||
// МЕТОДЫ КОМПОНЕНТЫ
|
||||
pub const METHODS: &[&[u16]] = &[
|
||||
name!("Connect"),
|
||||
name!("Close"),
|
||||
name!("Execute"),
|
||||
name!("SetTLS")
|
||||
name!("SetTLS"),
|
||||
name!("GetQueryResultRow"),
|
||||
name!("GetQueryResultLength"),
|
||||
name!("RemoveQuery"),
|
||||
name!("InitQuery"),
|
||||
name!("AddQueryParam"),
|
||||
];
|
||||
|
||||
pub fn get_params_amount(num: usize) -> usize {
|
||||
match num {
|
||||
0 => 0,
|
||||
1 => 0,
|
||||
2 => 3,
|
||||
2 => 1,
|
||||
3 => 3,
|
||||
4 => 2,
|
||||
5 => 1,
|
||||
6 => 1,
|
||||
7 => 2,
|
||||
8 => 2,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
@@ -28,16 +40,49 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
|
||||
0 => Box::new(obj.initialize()),
|
||||
1 => Box::new(obj.close_connection()),
|
||||
2 => {
|
||||
let query = params[0].get_string().unwrap_or_default();
|
||||
let params_json = params[1].get_string().unwrap_or_default();
|
||||
let force_result = params[2].get_bool().unwrap_or(false);
|
||||
Box::new(obj.execute_query(query, params_json, force_result))
|
||||
let key = params[0].get_string().unwrap_or_default();
|
||||
Box::new(obj.execute_query(&key))
|
||||
},
|
||||
3 => {
|
||||
let use_tls = params[0].get_bool().unwrap_or(false);
|
||||
let accept_invalid_certs = params[1].get_bool().unwrap_or(false);
|
||||
let ca_cert_path = params[2].get_string().unwrap_or_default();
|
||||
Box::new(obj.set_tls(use_tls, accept_invalid_certs, &ca_cert_path))
|
||||
},
|
||||
4 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
let index = params[1].get_i32().unwrap_or(0);
|
||||
|
||||
Box::new(obj.datasets.get_row(&key, index as usize).unwrap_or_else(|| "".to_string()))
|
||||
},
|
||||
5 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
|
||||
match obj.datasets.len(&key){
|
||||
Some(len) => Box::new(len as i32),
|
||||
None => Box::new(json!(
|
||||
{"result": false, "error": format!("Dataset {} not found", key)}
|
||||
).to_string()),
|
||||
}
|
||||
},
|
||||
6 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
obj.datasets.remove(&key);
|
||||
Box::new(json!({"result": true}).to_string())
|
||||
},
|
||||
7 => {
|
||||
|
||||
let text = params[0].get_string().unwrap_or("".to_string());
|
||||
let force = params[1].get_bool().unwrap_or(false);
|
||||
|
||||
Box::new(obj.init_query(&text, force))
|
||||
},
|
||||
8 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
let param = params[1].get_string().unwrap_or("".to_string());
|
||||
|
||||
Box::new(obj.add_query_param(&key, param))
|
||||
|
||||
}
|
||||
_ => Box::new(false),
|
||||
}
|
||||
@@ -55,6 +100,7 @@ pub struct AddIn {
|
||||
use_tls: bool,
|
||||
accept_invalid_certs: bool,
|
||||
ca_cert_path: String,
|
||||
datasets: Datasets,
|
||||
}
|
||||
|
||||
impl AddIn {
|
||||
@@ -66,6 +112,7 @@ impl AddIn {
|
||||
use_tls: false,
|
||||
accept_invalid_certs: false,
|
||||
ca_cert_path: String::new(),
|
||||
datasets: Datasets::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,14 +143,62 @@ impl AddIn {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn init_query(&mut self, text: &str, force_result: bool) -> String {
|
||||
|
||||
let key = self.datasets.init_query();
|
||||
self.datasets.set_text(&key, text);
|
||||
self.datasets.set_force_result(&key, force_result);
|
||||
|
||||
key
|
||||
}
|
||||
|
||||
pub fn add_query_param(&mut self, key: &str, param: String) -> String {
|
||||
|
||||
let value: Value = match serde_json::from_str(¶m) {
|
||||
Ok(param) => param,
|
||||
Err(e) => return Self::error(&e.to_string()),
|
||||
};
|
||||
|
||||
self.datasets.add_param(key, value);
|
||||
json!({"result": true}).to_string()
|
||||
|
||||
}
|
||||
|
||||
pub fn close_connection(&mut self) -> String {
|
||||
self.initialized = false;
|
||||
json!({"result": true}).to_string()
|
||||
}
|
||||
|
||||
pub fn execute_query(&self, query: String, params_json: String, force_result: bool) -> String {
|
||||
pub fn execute_query(&self, key: &str) -> String {
|
||||
match self.backend.lock(){
|
||||
Ok(backend) => {backend.execute_query(query, params_json, force_result)},
|
||||
Ok(backend) => {
|
||||
|
||||
let query = match self.datasets.get_query(key){
|
||||
Some(q) => q,
|
||||
None => return Self::error(format!("No query found by key: {}", key).as_str()),
|
||||
};
|
||||
|
||||
let params = query.params;
|
||||
let text = query.text;
|
||||
let force_result = query.force_result;
|
||||
|
||||
let backend_result = backend.execute_query(text, params, force_result);
|
||||
|
||||
match backend_result {
|
||||
Ok(result) => {
|
||||
match result {
|
||||
Some(data) => {
|
||||
|
||||
self.datasets.set_results(&key, data);
|
||||
json!({"result": true, "data": true}).to_string()
|
||||
|
||||
},
|
||||
None => json!({"result": true, "data": false}).to_string()
|
||||
}
|
||||
},
|
||||
Err(e) => Self::error(&e.to_string()),
|
||||
}
|
||||
},
|
||||
Err(e) => Self::error(&e.to_string()),
|
||||
}
|
||||
}
|
||||
@@ -127,7 +222,6 @@ impl AddIn {
|
||||
}).to_string()
|
||||
}
|
||||
|
||||
// SERVICE METHODS
|
||||
pub fn get_field_ptr(&self, index: usize) -> *const dyn getset::ValueType {
|
||||
match index {
|
||||
0 => &self.connection_string as &dyn getset::ValueType as *const _,
|
||||
|
36
src/addins/postgres/Cargo.lock
generated
36
src/addins/postgres/Cargo.lock
generated
@@ -182,6 +182,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
@@ -192,6 +198,20 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "7.0.0-rc2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a1e35a65fe0538a60167f0ada6e195ad5d477f6ddae273943596d4a1a5730b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dateparser"
|
||||
version = "0.2.1"
|
||||
@@ -215,6 +235,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.10"
|
||||
@@ -334,6 +360,12 @@ version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
@@ -545,6 +577,7 @@ dependencies = [
|
||||
"addin1c",
|
||||
"base64",
|
||||
"chrono",
|
||||
"dashmap",
|
||||
"dateparser",
|
||||
"native-tls",
|
||||
"postgres",
|
||||
@@ -1091,6 +1124,9 @@ name = "uuid"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
|
@@ -19,9 +19,10 @@ postgres = { version = "0.19.9", features = ["with-serde_json-1", "with-chrono-0
|
||||
serde_json = "1.0"
|
||||
base64 = "0.22.1"
|
||||
chrono = "0.4.39"
|
||||
uuid = "1.12.1"
|
||||
uuid = { version = "1.12.1", features = ["v4"] }
|
||||
postgres-native-tls = "0.5"
|
||||
native-tls = "0.2.14"
|
||||
dateparser = "0.2.1"
|
||||
dashmap = "7.0.0-rc2"
|
||||
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
"MAIN ---"
|
||||
linux-vdso.so.1 (0x00007ffeea6d2000)
|
||||
libssl.so.3 => /lib64/libssl.so.3 (0x00007c2606a00000)
|
||||
libcrypto.so.3 => /lib64/libcrypto.so.3 (0x00007c2606200000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007c2605e00000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x00007c2605a00000)
|
||||
libdl.so.2 => /lib64/libdl.so.2 (0x00007c2605600000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007c2607000000)
|
||||
libz.so.1 => /lib64/libz.so.1 (0x00007c2605200000)
|
||||
linux-vdso.so.1 (0x00007ffd042e7000)
|
||||
libssl.so.3 => /lib64/libssl.so.3 (0x0000720407a00000)
|
||||
libcrypto.so.3 => /lib64/libcrypto.so.3 (0x0000720407200000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000720406e00000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x0000720406a00000)
|
||||
libdl.so.2 => /lib64/libdl.so.2 (0x0000720406600000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x0000720408000000)
|
||||
libz.so.1 => /lib64/libz.so.1 (0x0000720406200000)
|
||||
GLIBC_2.2.5
|
||||
GLIBC_2.12
|
||||
GLIBC_2.3
|
||||
|
84
src/addins/postgres/src/component/dataset.rs
Normal file
84
src/addins/postgres/src/component/dataset.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use dashmap::DashMap;
|
||||
use serde_json::Value;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct Datasets {
|
||||
data: Arc<DashMap<String, QueryData>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QueryData {
|
||||
pub results: Vec<Value>,
|
||||
pub params: Vec<Value>,
|
||||
pub text: String,
|
||||
pub force_result: bool,
|
||||
}
|
||||
|
||||
impl Datasets {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: Arc::new(DashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_query(&self) -> String {
|
||||
let key = Uuid::new_v4().to_string();
|
||||
let query = QueryData::new();
|
||||
self.data.insert(key.clone(), query);
|
||||
key
|
||||
}
|
||||
|
||||
pub fn get_query(&self, key: &str) -> Option<QueryData> {
|
||||
self.data.get(key).map(|guard| guard.value().clone())
|
||||
}
|
||||
|
||||
pub fn set_results(&self, key: &str, values: Vec<Value>) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.results = values;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_param(&self, key: &str, value: Value) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.params.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_text(&self, key: &str, text: &str) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.text = text.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_force_result(&self, key: &str, enabled: bool) {
|
||||
if let Some(mut entry) = self.data.get_mut(key) {
|
||||
entry.force_result = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self, key: &str) -> Option<usize> {
|
||||
self.data.get(key).map(|entry| entry.results.len())
|
||||
}
|
||||
|
||||
pub fn remove(&self, key: &str) {
|
||||
self.data.remove(key);
|
||||
}
|
||||
|
||||
pub fn get_row(&self, key: &str, index: usize) -> Option<String> {
|
||||
let entry = self.data.get(key)?;
|
||||
let value = entry.results.get(index)?;
|
||||
serde_json::to_string(value).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryData {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
results: Vec::new(),
|
||||
params: Vec::new(),
|
||||
text: String::new(),
|
||||
force_result: false,
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,12 +8,28 @@ use chrono::{NaiveDate, NaiveTime, FixedOffset, NaiveDateTime, DateTime};
|
||||
use uuid::Uuid;
|
||||
use dateparser::parse;
|
||||
|
||||
pub fn execute_query(
|
||||
add_in: &mut AddIn,
|
||||
query: String,
|
||||
params_json: String,
|
||||
force_result: bool,
|
||||
) -> Vec<u8> {
|
||||
pub fn init_query(add_in: &mut AddIn, text: &str, force_result: bool) -> String {
|
||||
|
||||
let key = add_in.datasets.init_query();
|
||||
add_in.datasets.set_text(&key, text);
|
||||
add_in.datasets.set_force_result(&key, force_result);
|
||||
|
||||
key
|
||||
}
|
||||
|
||||
pub fn add_query_param(add_in: &mut AddIn, key: &str, param: String) -> String {
|
||||
|
||||
let value: Value = match serde_json::from_str(¶m) {
|
||||
Ok(param) => param,
|
||||
Err(e) => return format_json_error(&e.to_string()),
|
||||
};
|
||||
|
||||
add_in.datasets.add_param(key, value);
|
||||
json!({"result": true}).to_string()
|
||||
|
||||
}
|
||||
|
||||
pub fn execute_query(add_in: &mut AddIn, key: &str) -> String {
|
||||
|
||||
let client_arc = match add_in.get_connection() {
|
||||
Some(c) => c,
|
||||
@@ -25,12 +41,15 @@ pub fn execute_query(
|
||||
Err(_) => return format_json_error("Cannot acquire client lock"),
|
||||
};
|
||||
|
||||
// Парсинг JSON параметров
|
||||
let params: Vec<Value> = match serde_json::from_str(¶ms_json) {
|
||||
Ok(params) => params,
|
||||
Err(e) => return format_json_error(&e.to_string()),
|
||||
let query = match add_in.datasets.get_query(key){
|
||||
Some(q) => q,
|
||||
None => return format_json_error(format!("No query found by key: {}", key).as_str()),
|
||||
};
|
||||
|
||||
let params = query.params;
|
||||
let text = query.text;
|
||||
let force_result = query.force_result;
|
||||
|
||||
let params_ref = match process_params(¶ms){
|
||||
Ok(params) => params,
|
||||
Err(e) => return format_json_error(&e.to_string()),
|
||||
@@ -38,22 +57,25 @@ pub fn execute_query(
|
||||
|
||||
let params_unboxed: Vec<_> = params_ref.iter().map(AsRef::as_ref).collect();
|
||||
|
||||
if query.trim_start().to_uppercase().starts_with("SELECT") || force_result {
|
||||
match client.query(&query, ¶ms_unboxed) {
|
||||
if text.trim_start().to_uppercase().starts_with("SELECT") || force_result {
|
||||
match client.query(&text, ¶ms_unboxed) {
|
||||
Ok(rows) => {
|
||||
rows_to_json(rows).into_bytes()
|
||||
|
||||
let processed_rows = rows_to_json(rows);
|
||||
add_in.datasets.set_results(key, processed_rows);
|
||||
json!({"result": true, "data": true}).to_string()
|
||||
|
||||
}
|
||||
Err(e) => format_json_error(&e.to_string()),
|
||||
}
|
||||
} else {
|
||||
match client.execute(&query, ¶ms_unboxed.as_slice()) {
|
||||
Ok(_) => json!({"result": true}).to_string().into_bytes(),
|
||||
match client.execute(&text, ¶ms_unboxed.as_slice()) {
|
||||
Ok(_) => json!({"result": true, "data": false}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Конвертирует JSON-параметры в Postgres-совместимые типы
|
||||
fn process_params(params: &Vec<Value>) -> Result<Vec<Box<dyn ToSql + Sync>>, String> {
|
||||
let mut result = Vec::new();
|
||||
for param in params {
|
||||
@@ -212,7 +234,7 @@ fn process_object(object: &Map<String, Value>) -> Result<Box<dyn ToSql + Sync>,
|
||||
}
|
||||
}
|
||||
|
||||
fn rows_to_json(rows: Vec<postgres::Row>) -> String {
|
||||
fn rows_to_json(rows: Vec<postgres::Row>) -> Vec<Value> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
for row in rows {
|
||||
@@ -230,8 +252,7 @@ fn rows_to_json(rows: Vec<postgres::Row>) -> String {
|
||||
|
||||
result.push(Value::Object(row_map));
|
||||
};
|
||||
|
||||
json!({ "result": true, "data": result }).to_string()
|
||||
result
|
||||
}
|
||||
|
||||
fn process_sql_value(column_name: &str, column_type: &str, row: &postgres::Row) -> Result<Value, postgres::Error> {
|
||||
@@ -326,12 +347,12 @@ fn process_sql_value(column_name: &str, column_type: &str, row: &postgres::Row)
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn format_json_error(error: &str) -> Vec<u8> {
|
||||
fn format_json_error(error: &str) -> String {
|
||||
json!({
|
||||
"result": false,
|
||||
"error": error
|
||||
})
|
||||
.to_string().into_bytes()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn parse_date(input: &str) -> Result<NaiveDateTime, String> {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
mod methods;
|
||||
mod dataset;
|
||||
|
||||
use addin1c::{name, Variant};
|
||||
use crate::core::getset;
|
||||
@@ -9,6 +10,7 @@ use native_tls::{TlsConnector, Certificate};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::component::dataset::Datasets;
|
||||
// МЕТОДЫ КОМПОНЕНТЫ -------------------------------------------------------------------------------
|
||||
|
||||
// Синонимы
|
||||
@@ -16,8 +18,12 @@ pub const METHODS: &[&[u16]] = &[
|
||||
name!("Connect"),
|
||||
name!("Close"),
|
||||
name!("Execute"),
|
||||
name!("SetTLS")
|
||||
|
||||
name!("SetTLS"),
|
||||
name!("GetQueryResultRow"),
|
||||
name!("GetQueryResultLength"),
|
||||
name!("RemoveQuery"),
|
||||
name!("InitQuery"),
|
||||
name!("AddQueryParam"),
|
||||
];
|
||||
|
||||
// Число параметров функций компоненты
|
||||
@@ -25,8 +31,13 @@ pub fn get_params_amount(num: usize) -> usize {
|
||||
match num {
|
||||
0 => 0,
|
||||
1 => 0,
|
||||
2 => 3,
|
||||
2 => 1,
|
||||
3 => 3,
|
||||
4 => 2,
|
||||
5 => 1,
|
||||
6 => 1,
|
||||
7 => 2,
|
||||
8 => 2,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
@@ -41,11 +52,8 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
|
||||
1 => Box::new(obj.close_connection()),
|
||||
2 => {
|
||||
|
||||
let query = String::from_utf8_lossy(params[0].get_blob().unwrap_or(&[])).to_string();
|
||||
let params_json = String::from_utf8_lossy(params[1].get_blob().unwrap_or(&[])).to_string();
|
||||
let force_result = params[2].get_bool().unwrap_or(false);
|
||||
|
||||
Box::new(methods::execute_query(obj, query, params_json, force_result))
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
Box::new(methods::execute_query(obj, &key))
|
||||
},
|
||||
3 => {
|
||||
|
||||
@@ -55,6 +63,41 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
|
||||
|
||||
Box::new(obj.set_tls(use_tls, accept_invalid_certs, &ca_cert_path))
|
||||
|
||||
},
|
||||
4 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
let index = params[1].get_i32().unwrap_or(0);
|
||||
|
||||
Box::new(obj.datasets.get_row(&key, index as usize).unwrap_or_else(|| "".to_string()))
|
||||
},
|
||||
5 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
|
||||
match obj.datasets.len(&key){
|
||||
Some(len) => Box::new(len as i32),
|
||||
None => Box::new(json!(
|
||||
{"result": false, "error": format!("Dataset {} not found", key)}
|
||||
).to_string()),
|
||||
}
|
||||
},
|
||||
6 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
obj.datasets.remove(&key);
|
||||
Box::new(json!({"result": true}).to_string())
|
||||
},
|
||||
7 => {
|
||||
|
||||
let text = params[0].get_string().unwrap_or("".to_string());
|
||||
let force = params[1].get_bool().unwrap_or(false);
|
||||
|
||||
Box::new(methods::init_query(obj, &text, force))
|
||||
},
|
||||
8 => {
|
||||
let key = params[0].get_string().unwrap_or("".to_string());
|
||||
let param = params[1].get_string().unwrap_or("".to_string());
|
||||
|
||||
Box::new(methods::add_query_param(obj, &key, param))
|
||||
|
||||
}
|
||||
_ => Box::new(false), // Неверный номер команды
|
||||
}
|
||||
@@ -77,6 +120,7 @@ pub struct AddIn {
|
||||
use_tls: bool,
|
||||
accept_invalid_certs: bool,
|
||||
ca_cert_path: String,
|
||||
datasets: Datasets,
|
||||
}
|
||||
|
||||
impl AddIn {
|
||||
@@ -88,6 +132,7 @@ impl AddIn {
|
||||
use_tls: false,
|
||||
accept_invalid_certs: false,
|
||||
ca_cert_path: String::new(),
|
||||
datasets: Datasets::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
src/en/OInt/addins/OPI_MSSQL.zip
vendored
BIN
src/en/OInt/addins/OPI_MSSQL.zip
vendored
Binary file not shown.
BIN
src/en/OInt/addins/OPI_PostgreSQL.zip
vendored
BIN
src/en/OInt/addins/OPI_PostgreSQL.zip
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/ru/OInt/addins/OPI_MSSQL.zip
vendored
BIN
src/ru/OInt/addins/OPI_MSSQL.zip
vendored
Binary file not shown.
BIN
src/ru/OInt/addins/OPI_PostgreSQL.zip
vendored
BIN
src/ru/OInt/addins/OPI_PostgreSQL.zip
vendored
Binary file not shown.
@@ -145,11 +145,6 @@
|
||||
, Знач Соединение = ""
|
||||
, Знач Tls = "") Экспорт
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
|
||||
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
|
||||
|
||||
Параметры_ = ОбработатьПараметры(Параметры);
|
||||
|
||||
Если ЭтоКоннектор(Соединение) Тогда
|
||||
ЗакрыватьСоединение = Ложь;
|
||||
Коннектор = Соединение;
|
||||
@@ -161,15 +156,17 @@
|
||||
Если Не ЭтоКоннектор(Коннектор) Тогда
|
||||
Возврат Коннектор;
|
||||
КонецЕсли;
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
|
||||
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
|
||||
|
||||
Результат = Коннектор.Execute(ТекстЗапроса, Параметры_, ФорсироватьРезультат);
|
||||
Параметры_ = ОбработатьПараметры(Параметры);
|
||||
Результат = OPI_ЗапросыSQL.ВыполнитьЗапросСОбработкой(Коннектор, ТекстЗапроса, ФорсироватьРезультат, Параметры_);
|
||||
|
||||
Если ЗакрыватьСоединение Тогда
|
||||
ЗакрытьСоединение(Коннектор);
|
||||
КонецЕсли;
|
||||
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
@@ -581,27 +578,28 @@
|
||||
Функция ОбработатьПараметры(Знач Параметры)
|
||||
|
||||
Если Не ЗначениеЗаполнено(Параметры) Тогда
|
||||
Возврат "[]";
|
||||
Возврат Новый Массив;
|
||||
КонецЕсли;
|
||||
|
||||
Параметры_ = Новый Массив;
|
||||
OPI_ПреобразованиеТипов.ПолучитьМассив(Параметры);
|
||||
|
||||
Для Н = 0 По Параметры.ВГраница() Цикл
|
||||
Счетчик = 0;
|
||||
Для Каждого Параметр Из Параметры Цикл
|
||||
|
||||
ТекущийПараметр = Параметры[Н];
|
||||
|
||||
ТекущийПараметр = ОбработатьПараметр(ТекущийПараметр);
|
||||
|
||||
Параметры[Н] = ТекущийПараметр;
|
||||
ТекущийПараметр = ОбработатьПараметр(Параметр);
|
||||
ТекущийПараметр = OPI_Инструменты.JSONСтрокой(ТекущийПараметр, , Ложь);
|
||||
|
||||
Если СтрНачинаетсяС(ТекущийПараметр, "НЕ JSON") Тогда
|
||||
ВызватьИсключение СтрШаблон("Ошибка валидации JSON параметра. Индекс массив %1", Счетчик);
|
||||
Иначе
|
||||
Параметры_.Добавить(ТекущийПараметр);
|
||||
КонецЕсли;
|
||||
|
||||
Счетчик = Счетчик + 1;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Параметры_ = OPI_Инструменты.JSONСтрокой(Параметры, , Ложь);
|
||||
|
||||
Если СтрНачинаетсяС(Параметры_, "НЕ JSON") Тогда
|
||||
ВызватьИсключение "Ошибка валидации JSON массива параметров!";
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Параметры_;
|
||||
|
||||
КонецФункции
|
||||
|
@@ -74,7 +74,7 @@
|
||||
КонецЕсли;
|
||||
|
||||
Коннектор.ConnectionString = СтрокаПодключения;
|
||||
|
||||
|
||||
Результат = Коннектор.Connect();
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
|
||||
|
||||
@@ -145,14 +145,6 @@
|
||||
, Знач Соединение = ""
|
||||
, Знач Tls = "") Экспорт
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
|
||||
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
|
||||
|
||||
Параметры_ = ОбработатьПараметры(Параметры);
|
||||
|
||||
ТекстЗапроса = ПолучитьДвоичныеДанныеИзСтроки(ТекстЗапроса);
|
||||
Параметры_ = ПолучитьДвоичныеДанныеИзСтроки(Параметры_);
|
||||
|
||||
Если ЭтоКоннектор(Соединение) Тогда
|
||||
ЗакрыватьСоединение = Ложь;
|
||||
Коннектор = Соединение;
|
||||
@@ -164,16 +156,17 @@
|
||||
Если Не ЭтоКоннектор(Коннектор) Тогда
|
||||
Возврат Коннектор;
|
||||
КонецЕсли;
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
|
||||
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
|
||||
|
||||
Результат = Коннектор.Execute(ТекстЗапроса, Параметры_, ФорсироватьРезультат);
|
||||
Результат = ПолучитьСтрокуИзДвоичныхДанных(Результат);
|
||||
Параметры_ = ОбработатьПараметры(Параметры);
|
||||
Результат = OPI_ЗапросыSQL.ВыполнитьЗапросСОбработкой(Коннектор, ТекстЗапроса, ФорсироватьРезультат, Параметры_);
|
||||
|
||||
Если ЗакрыватьСоединение Тогда
|
||||
ЗакрытьСоединение(Коннектор);
|
||||
КонецЕсли;
|
||||
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
|
||||
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
@@ -575,32 +568,33 @@
|
||||
Функция ОбработатьПараметры(Знач Параметры)
|
||||
|
||||
Если Не ЗначениеЗаполнено(Параметры) Тогда
|
||||
Возврат "[]";
|
||||
Возврат Новый Массив;
|
||||
КонецЕсли;
|
||||
|
||||
Параметры_ = Новый Массив;
|
||||
OPI_ПреобразованиеТипов.ПолучитьМассив(Параметры);
|
||||
|
||||
Для Н = 0 По Параметры.ВГраница() Цикл
|
||||
Счетчик = 0;
|
||||
Для Каждого Параметр Из Параметры Цикл
|
||||
|
||||
ТекущийПараметр = Параметры[Н];
|
||||
|
||||
ТекущийПараметр = ОбработатьПараметр(ТекущийПараметр);
|
||||
|
||||
Параметры[Н] = ТекущийПараметр;
|
||||
ТекущийПараметр = ОбработатьПараметр(Параметр);
|
||||
ТекущийПараметр = OPI_Инструменты.JSONСтрокой(ТекущийПараметр, , Ложь);
|
||||
|
||||
Если СтрНачинаетсяС(ТекущийПараметр, "НЕ JSON") Тогда
|
||||
ВызватьИсключение СтрШаблон("Ошибка валидации JSON параметра. Индекс массив %1", Счетчик);
|
||||
Иначе
|
||||
Параметры_.Добавить(ТекущийПараметр);
|
||||
КонецЕсли;
|
||||
|
||||
Счетчик = Счетчик + 1;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Параметры_ = OPI_Инструменты.JSONСтрокой(Параметры, , Ложь);
|
||||
|
||||
Если СтрНачинаетсяС(Параметры_, "НЕ JSON") Тогда
|
||||
ВызватьИсключение "Ошибка валидации JSON массива параметров!";
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Параметры_;
|
||||
|
||||
КонецФункции
|
||||
|
||||
Функция ОбработатьПараметр(ТекущийПараметр)
|
||||
Функция ОбработатьПараметр(ТекущийПараметр, Вложенный = Ложь)
|
||||
|
||||
ТекущийТип = ТипЗнч(ТекущийПараметр);
|
||||
|
||||
@@ -611,10 +605,12 @@
|
||||
ИначеЕсли ТекущийТип = Тип("УникальныйИдентификатор") Тогда
|
||||
|
||||
ТекущийПараметр = Строка(ТекущийПараметр);
|
||||
ТекущийПараметр = ?(Вложенный, ТекущийПараметр, Новый Структура("UUID", ТекущийПараметр));
|
||||
|
||||
ИначеЕсли ТекущийТип = Тип("Дата") Тогда
|
||||
|
||||
ТекущийПараметр = OPI_Инструменты.ДатаRFC3339(ТекущийПараметр);
|
||||
ТекущийПараметр = ?(Вложенный, ТекущийПараметр, Новый Структура("TIMESTAMP", ТекущийПараметр));
|
||||
|
||||
ИначеЕсли OPI_Инструменты.ПолеКоллекцииСуществует(ТекущийПараметр, "BYTEA") Тогда
|
||||
|
||||
@@ -634,14 +630,17 @@
|
||||
Продолжить;
|
||||
КонецЕсли;
|
||||
|
||||
ТекущийПараметр[ЭлементПараметра.Ключ] = ОбработатьПараметр(ТекущееЗначение);
|
||||
ТекущийПараметр[ЭлементПараметра.Ключ] = ОбработатьПараметр(ТекущееЗначение, Истина);
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Иначе
|
||||
|
||||
Если Не OPI_Инструменты.ЭтоПримитивныйТип(ТекущийПараметр) Тогда
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекущийПараметр);
|
||||
ТекущийПараметр = ?(Вложенный, ТекущийПараметр, Новый Структура("VARCHAR", ТекущийПараметр));
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
КонецЕсли;
|
||||
|
@@ -353,6 +353,28 @@
|
||||
|
||||
КонецФункции
|
||||
|
||||
Функция ВыполнитьЗапросСОбработкой(Коннектор, Знач ТекстЗапроса, Знач ФорсироватьРезультат, Знач Параметры) Экспорт
|
||||
|
||||
КлючЗапроса = Коннектор.InitQuery(ТекстЗапроса, ФорсироватьРезультат);
|
||||
|
||||
Для Каждого Параметр Из Параметры Цикл
|
||||
|
||||
Добавление = Коннектор.AddQueryParam(КлючЗапроса, Параметр);
|
||||
Добавление = OPI_Инструменты.JsonВСтруктуру(Добавление);
|
||||
|
||||
Если Не Добавление["result"] Тогда
|
||||
Возврат Добавление;
|
||||
КонецЕсли;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Результат = Коннектор.Execute(КлючЗапроса);
|
||||
Результат = ОбработатьРезультатЗапроса(Коннектор, КлючЗапроса, Результат);
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область СлужебныеПроцедурыИФункции
|
||||
@@ -1211,6 +1233,45 @@
|
||||
|
||||
КонецФункции
|
||||
|
||||
Функция ОбработатьРезультатЗапроса(Знач Коннектор, Знач КлючЗапроса, Знач Результат)
|
||||
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
|
||||
|
||||
Если Результат["result"] Тогда
|
||||
|
||||
Если Не Результат["data"] Тогда
|
||||
Результат.Удалить("data");
|
||||
Возврат Результат;
|
||||
КонецЕсли;
|
||||
|
||||
КоличествоСтрок = Коннектор.GetQueryResultLength(КлючЗапроса);
|
||||
|
||||
Если Не ТипЗнч(КоличествоСтрок) = Тип("Число") Тогда
|
||||
Возврат OPI_Инструменты.JsonВСтруктуру(КоличествоСтрок);
|
||||
КонецЕсли;
|
||||
|
||||
МассивСтрок = Новый Массив;
|
||||
|
||||
Для Н = 0 По КоличествоСтрок Цикл
|
||||
|
||||
ТекущаяСтрока = Коннектор.GetQueryResultRow(КлючЗапроса, Н);
|
||||
МассивСтрок.Добавить(ТекущаяСтрока);
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
Если МассивСтрок.Количество() > 0 Тогда
|
||||
ТекстJSON = СтрШаблон("[%1]", СтрСоединить(МассивСтрок, "," + Символы.ПС));
|
||||
МассивСтрок = OPI_Инструменты.JSONВСтруктуру(ТекстJSON);
|
||||
КонецЕсли;
|
||||
|
||||
Результат.Вставить("data", МассивСтрок);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
|
||||
Процедура РазделитьКоллекциюДанных(Знач Запись, МассивПолей, МассивЗначений)
|
||||
|
||||
ТекстОшибки = "Некорректный набор данных для обновления";
|
||||
|
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user