You've already forked OpenIntegrations
							
							
				mirror of
				https://github.com/Bayselonarrend/OpenIntegrations.git
				synced 2025-10-30 23:47:46 +02:00 
			
		
		
		
	Начало SQLite
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -23,3 +23,4 @@ target/ | ||||
| !oscript.exe | ||||
| addin.zip | ||||
| src/addins/tcp_server/OPI_TCPServer.zip | ||||
| src/addins/sqlite/OPI_SQLite.zip | ||||
|   | ||||
							
								
								
									
										275
									
								
								src/addins/sqlite/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										275
									
								
								src/addins/sqlite/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,275 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 4 | ||||
|  | ||||
| [[package]] | ||||
| name = "addin1c" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ef34e8b7ff4c43e87491a4cc30a4779a9f67c50db43378a36362c7a56246e05b" | ||||
| dependencies = [ | ||||
|  "smallvec", | ||||
|  "utf16_lit", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ahash" | ||||
| version = "0.8.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "once_cell", | ||||
|  "version_check", | ||||
|  "zerocopy", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "base64" | ||||
| version = "0.22.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" | ||||
|  | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "2.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" | ||||
|  | ||||
| [[package]] | ||||
| name = "cc" | ||||
| version = "1.2.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" | ||||
| dependencies = [ | ||||
|  "shlex", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
|  | ||||
| [[package]] | ||||
| name = "fallible-iterator" | ||||
| version = "0.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" | ||||
|  | ||||
| [[package]] | ||||
| name = "fallible-streaming-iterator" | ||||
| version = "0.1.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" | ||||
|  | ||||
| [[package]] | ||||
| name = "hashbrown" | ||||
| version = "0.14.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" | ||||
| dependencies = [ | ||||
|  "ahash", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "hashlink" | ||||
| version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" | ||||
| dependencies = [ | ||||
|  "hashbrown", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "itoa" | ||||
| version = "1.0.14" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" | ||||
|  | ||||
| [[package]] | ||||
| name = "libsqlite3-sys" | ||||
| version = "0.30.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" | ||||
| dependencies = [ | ||||
|  "cc", | ||||
|  "pkg-config", | ||||
|  "vcpkg", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "memchr" | ||||
| version = "2.7.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" | ||||
|  | ||||
| [[package]] | ||||
| name = "once_cell" | ||||
| version = "1.20.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" | ||||
|  | ||||
| [[package]] | ||||
| name = "opi_sqlite" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "addin1c", | ||||
|  "base64", | ||||
|  "rusqlite", | ||||
|  "serde_json", | ||||
|  "serde_rusqlite", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "pkg-config" | ||||
| version = "0.3.31" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.92" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" | ||||
| dependencies = [ | ||||
|  "unicode-ident", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "quote" | ||||
| version = "1.0.38" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rusqlite" | ||||
| version = "0.32.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "fallible-iterator", | ||||
|  "fallible-streaming-iterator", | ||||
|  "hashlink", | ||||
|  "libsqlite3-sys", | ||||
|  "smallvec", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ryu" | ||||
| version = "1.0.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" | ||||
|  | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.217" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" | ||||
| dependencies = [ | ||||
|  "serde_derive", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.217" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "serde_json" | ||||
| version = "1.0.134" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" | ||||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "memchr", | ||||
|  "ryu", | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "serde_rusqlite" | ||||
| version = "0.36.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b741cc5ef185cd96157e762c3bba743c4e94c8dc6af0edb053c48d2b3c27e691" | ||||
| dependencies = [ | ||||
|  "rusqlite", | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "shlex" | ||||
| version = "1.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" | ||||
|  | ||||
| [[package]] | ||||
| name = "smallvec" | ||||
| version = "1.13.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "2.0.92" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "unicode-ident", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "unicode-ident" | ||||
| version = "1.0.14" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" | ||||
|  | ||||
| [[package]] | ||||
| name = "utf16_lit" | ||||
| version = "2.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "14706d2a800ee8ff38c1d3edb873cd616971ea59eb7c0d046bb44ef59b06a1ae" | ||||
|  | ||||
| [[package]] | ||||
| name = "vcpkg" | ||||
| version = "0.2.15" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | ||||
|  | ||||
| [[package]] | ||||
| name = "version_check" | ||||
| version = "0.9.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" | ||||
|  | ||||
| [[package]] | ||||
| name = "zerocopy" | ||||
| version = "0.7.35" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" | ||||
| dependencies = [ | ||||
|  "zerocopy-derive", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "zerocopy-derive" | ||||
| version = "0.7.35" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
							
								
								
									
										20
									
								
								src/addins/sqlite/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/addins/sqlite/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| [package] | ||||
| name = "opi_sqlite" | ||||
| version = "0.1.0" | ||||
| edition = "2021" | ||||
|  | ||||
| [lib] | ||||
| crate-type = ["cdylib"] | ||||
|  | ||||
| [profile.release] | ||||
| lto = true        # Enable Link Time Optimization | ||||
| codegen-units = 1 # Reduce number of codegen units to increase optimizations. | ||||
| panic = "abort"   # Abort on panic | ||||
| strip = true      # Automatically strip symbols from the binary. | ||||
|  | ||||
| [dependencies] | ||||
| addin1c = "0.5.0" | ||||
| rusqlite = {  version = "0.32.1", features = ["bundled"]} | ||||
| serde_json = "1.0" | ||||
| serde_rusqlite = "0.36.0" | ||||
| base64 = "0.22.1" | ||||
							
								
								
									
										7
									
								
								src/addins/sqlite/MANIFEST.XML
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/addins/sqlite/MANIFEST.XML
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| <?xml version='1.0' encoding='UTF-8'?> | ||||
| <bundle xmlns='http://v8.1c.ru/8.2/addin/bundle' name='OPIADDIN'> | ||||
| 	<component os='Windows' path='AddIn_x86_windows.dll' type='native' arch='i386' /> | ||||
| 	<component os='Windows' path='AddIn_x64_windows.dll' type='native' arch='x86_64' /> | ||||
| 	<component os='Linux' path='AddIn_x86_linux.so' type='native' arch='i386' /> | ||||
| 	<component os='Linux' path='AddIn_x64_linux.so' type='native' arch='x86_64' /> | ||||
| </bundle> | ||||
							
								
								
									
										69
									
								
								src/addins/sqlite/release.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/addins/sqlite/release.bat
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| @echo off | ||||
|  | ||||
| :: Установить переменную | ||||
| set CARGO_NAME=opi_sqlite | ||||
| set LIB_NAME=OPI_SQLite | ||||
| set OPENSSL_DIR=C:\msys64\mingw64 | ||||
| set OPENSSL_LIB_DIR=%OPENSSL_DIR%\lib | ||||
| set OPENSSL_INCLUDE_DIR=%OPENSSL_DIR%\include | ||||
|  | ||||
|  | ||||
| :: Перейти в директорию проекта | ||||
| cd /d "%~dp0" | ||||
|  | ||||
| :: Создать папку для артефактов | ||||
| set OUTPUT_DIR=artifacts | ||||
| if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%" | ||||
|  | ||||
| :: Сборка для x86_64-pc-windows-msvc | ||||
| cargo build --release --target x86_64-pc-windows-msvc | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Сборка для x86_64-unknown-linux-gnu | ||||
| cargo zigbuild --release --target x86_64-unknown-linux-gnu | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Сборка для i686-pc-windows-msvc | ||||
| cargo build --release --target i686-pc-windows-msvc | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Сборка для i686-unknown-linux-gnu | ||||
| cargo zigbuild --release --target i686-unknown-linux-gnu | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Копирование файлов .dll и .so | ||||
| copy /y target\x86_64-pc-windows-msvc\release\%CARGO_NAME%.dll "%OUTPUT_DIR%\AddIn_x64_windows.dll" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y target\i686-pc-windows-msvc\release\%CARGO_NAME%.dll "%OUTPUT_DIR%\AddIn_x86_windows.dll" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y target\x86_64-unknown-linux-gnu\release\lib%CARGO_NAME%.so "%OUTPUT_DIR%\AddIn_x64_linux.so" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y target\i686-unknown-linux-gnu\release\lib%CARGO_NAME%.so "%OUTPUT_DIR%\AddIn_x86_linux.so" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y MANIFEST.XML "%OUTPUT_DIR%\MANIFEST.XML" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Архивация | ||||
| powershell -Command "Compress-Archive -Path '%OUTPUT_DIR%\*' -Force -DestinationPath '%LIB_NAME%.zip'" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y "%LIB_NAME%.zip" "../../ru/OInt/addins/%LIB_NAME%.zip" | ||||
| copy /y "%LIB_NAME%.zip" "../../en/OInt/addins/%LIB_NAME%.zip" | ||||
|  | ||||
| copy /y "%LIB_NAME%.zip" "../../ru/OPI/src/CommonTemplates/%LIB_NAME%/Template.addin" | ||||
| copy /y "%LIB_NAME%.zip" "../../en/OPI/src/CommonTemplates/%LIB_NAME%/Template.addin" | ||||
|  | ||||
| if exist "%OUTPUT_DIR%" ( | ||||
|     rmdir /S /Q "%OUTPUT_DIR%" | ||||
| ) | ||||
|  | ||||
| @echo Build and packaging completed successfully. | ||||
| exit /b 0 | ||||
|  | ||||
| :error | ||||
| @echo An error occurred during the build or packaging process. | ||||
| exit /b 1 | ||||
							
								
								
									
										126
									
								
								src/addins/sqlite/src/component/methods.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/addins/sqlite/src/component/methods.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | ||||
| use rusqlite::{types::ValueRef}; | ||||
| use serde_json::{Value, json, Map}; | ||||
| use crate::component; | ||||
| use serde_rusqlite::{to_params}; | ||||
| use base64::{engine::general_purpose, Engine as _}; | ||||
|  | ||||
| pub fn execute_query( | ||||
|     client: &mut component::AddIn, | ||||
|     query: String, | ||||
|     params_json: String, | ||||
| ) -> String { | ||||
|  | ||||
|     let conn = match client.get_connection() { | ||||
|         Some(c) => c, | ||||
|         None => return r#"{"result": false, "error": "No connection initialized"}"#.to_string(), | ||||
|     }; | ||||
|  | ||||
|     // Парсинг JSON параметров | ||||
|     let parsed_params: Value = match serde_json::from_str(¶ms_json) { | ||||
|         Ok(params) => params, | ||||
|         Err(e) => { | ||||
|             return format!( | ||||
|                 r#"{{"result": false, "error": "Invalid JSON parameters: {}"}}"#, | ||||
|                 e.to_string() | ||||
|             ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     let params_array = match parsed_params.as_array() { | ||||
|         Some(array) => array, | ||||
|         None => { | ||||
|             return r#"{"result": false, "error": "Parameters must be a JSON array"}"#.to_string(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     let convert = to_params(params_array).unwrap(); | ||||
|  | ||||
|     // Определяем тип запроса | ||||
|     if query.trim_start().to_uppercase().starts_with("SELECT") { | ||||
|         // Выполняем SELECT | ||||
|         match conn.prepare(&query) { | ||||
|             Ok(mut query_result) => { | ||||
|  | ||||
|                 let cols: Vec<String> = query_result | ||||
|                     .column_names() | ||||
|                     .iter() | ||||
|                     .map(|name| name.to_string()) | ||||
|                     .collect(); | ||||
|  | ||||
|                 let res = query_result.query(convert); | ||||
|  | ||||
|                 match res{ | ||||
|                     Ok(mut rows) => { | ||||
|                         rows_to_json_array(&mut rows, &cols) | ||||
|                     } | ||||
|                     Err(e) => { | ||||
|                         format!(r#"{{"result": false, "error": "{}"}}"#, e.to_string()) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 format!(r#"{{"result": false, "error": "{}"}}"#, e.to_string()) | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|  | ||||
|         match conn.execute(&query, convert) { | ||||
|             Ok(_) => r#"{"result": true}"#.to_string(), | ||||
|             Err(e) => format!(r#"{{"result": false, "error": "{}"}}"#, e.to_string()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn rows_to_json_array(rows: &mut rusqlite::Rows, cols: &Vec<String>) -> String { | ||||
|  | ||||
|     let mut json_array = Vec::new(); | ||||
|  | ||||
|     loop { | ||||
|  | ||||
|         let mut current: Map<String, Value> = Map::new(); | ||||
|  | ||||
|         match rows.next() { | ||||
|  | ||||
|             Ok(Some(row)) => { | ||||
|  | ||||
|                 for i in 0..cols.len() { | ||||
|  | ||||
|                     let val = row.get_ref_unwrap(i); | ||||
|                     let jval = from_sql_to_json(val); | ||||
|  | ||||
|                     current.insert(cols[i].to_string(), jval); | ||||
|                 }; | ||||
|  | ||||
|                 json_array.push(current); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             Ok(None) => break, | ||||
|             Err(e) => { | ||||
|                 current.insert("error".to_string(), Value::String(e.to_string())); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     json!(json_array).to_string() | ||||
| } | ||||
|  | ||||
| fn from_sql_to_json(value: ValueRef) -> Value { | ||||
|     match value { | ||||
|         ValueRef::Null => Value::Null, | ||||
|         ValueRef::Integer(i) => Value::Number(i.into()), | ||||
|         ValueRef::Real(f) => { | ||||
|             serde_json::Number::from_f64(f).map(Value::Number).unwrap_or(Value::Null) | ||||
|         } | ||||
|         ValueRef::Text(t) => Value::String(String::from_utf8_lossy(t).into_owned()), | ||||
|         ValueRef::Blob(b) => { | ||||
|             let base64_string = general_purpose::STANDARD.encode(b); // Кодируем в Base64 | ||||
|             let mut blob_object = serde_json::Map::new(); | ||||
|             blob_object.insert("blob".to_string(), Value::String(base64_string)); // Оборачиваем в объект | ||||
|             Value::Object(blob_object) | ||||
|         }, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										108
									
								
								src/addins/sqlite/src/component/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/addins/sqlite/src/component/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| mod methods; | ||||
|  | ||||
| use addin1c::{name, Variant}; | ||||
| use crate::core::getset; | ||||
| use rusqlite::{Connection}; | ||||
|  | ||||
| // МЕТОДЫ КОМПОНЕНТЫ ------------------------------------------------------------------------------- | ||||
|  | ||||
| // Синонимы | ||||
| pub const METHODS: &[&[u16]] = &[ | ||||
|     name!("Connect"), | ||||
|     name!("Execute"),    // 0 | ||||
|  | ||||
| ]; | ||||
|  | ||||
| // Число параметров функций компоненты | ||||
| pub fn get_params_amount(num: usize) -> usize { | ||||
|     match num { | ||||
|         0 => 0, | ||||
|         1 => 2, | ||||
|         _ => 0, | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Соответствие функций Rust функциям компоненты | ||||
| // Вызовы должны быть обернуты в Box::new | ||||
| pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn getset::ValueType> { | ||||
|  | ||||
|     match num { | ||||
|  | ||||
|         0 =>{ | ||||
|             Box::new(obj.initialize()) | ||||
|         }, | ||||
|  | ||||
|         1 => { | ||||
|  | ||||
|             let query = params[0].get_string().unwrap_or("".to_string()); | ||||
|             let params_json = params[1].get_string().unwrap_or("".to_string()); | ||||
|  | ||||
|             Box::new(methods::execute_query(obj, query, params_json)) | ||||
|         }, | ||||
|         _ => Box::new(false), // Неверный номер команды | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| // ------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| // ПОЛЯ КОМПОНЕНТЫ --------------------------------------------------------------------------------- | ||||
|  | ||||
| // Синонимы | ||||
| pub const PROPS: &[&[u16]] = &[ | ||||
|     name!("Database") | ||||
| ]; | ||||
|  | ||||
|  | ||||
| pub struct AddIn { | ||||
|     connection_string: String, | ||||
|     connection: Option<Connection>, | ||||
| } | ||||
|  | ||||
| impl AddIn { | ||||
|     /// Создает новый объект | ||||
|     pub fn new() -> Self { | ||||
|         AddIn { | ||||
|             connection_string: String::new(), | ||||
|             connection: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn initialize(&mut self) -> String { | ||||
|         let conn_result = if self.connection_string.is_empty() { | ||||
|             Connection::open_in_memory() | ||||
|         } else { | ||||
|             Connection::open(&self.connection_string) | ||||
|         }; | ||||
|  | ||||
|         match conn_result { | ||||
|             Ok(conn) => { | ||||
|                 self.connection = Some(conn); | ||||
|                 r#"{"result": true}"#.to_string() | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 format!(r#"{{"result": false, "error": "{}"}}"#, e.to_string()) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn get_connection(&self) -> Option<&Connection> { | ||||
|         self.connection.as_ref() | ||||
|     } | ||||
|  | ||||
|     pub fn get_field_ptr(&self, index: usize) -> *const dyn getset::ValueType { | ||||
|         match index { | ||||
|             0 => &self.connection_string as &dyn getset::ValueType as *const _, | ||||
|             _ => panic!("Index out of bounds"), | ||||
|         } | ||||
|     } | ||||
|     pub fn get_field_ptr_mut(&mut self, index: usize) -> *mut dyn getset::ValueType { self.get_field_ptr(index) as *mut _ } | ||||
| } | ||||
| // ------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| // УНИЧТОЖЕНИЕ ОБЪЕКТА ----------------------------------------------------------------------------- | ||||
|  | ||||
| // Обработка удаления объекта | ||||
| impl Drop for AddIn { | ||||
|     fn drop(&mut self) {} | ||||
| } | ||||
							
								
								
									
										78
									
								
								src/addins/sqlite/src/core/getset.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/addins/sqlite/src/core/getset.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| use addin1c::{Variant, Tm}; | ||||
|  | ||||
|  | ||||
| pub trait ValueType { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool; | ||||
|     fn set_value(&mut self, val: &Variant); | ||||
| } | ||||
|  | ||||
| // Реализация для i32 | ||||
| impl ValueType for i32 { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool { | ||||
|         val.set_i32(*self); | ||||
|         true | ||||
|     } | ||||
|  | ||||
|     fn set_value(&mut self, val: &Variant) { | ||||
|         *self = val.get_i32().unwrap_or(0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Реализация для f64 | ||||
| impl ValueType for f64 { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool { | ||||
|         val.set_f64(*self); | ||||
|         true | ||||
|     } | ||||
|  | ||||
|     fn set_value(&mut self, val: &Variant) { | ||||
|         *self = val.get_f64().unwrap_or(0.0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Реализация для bool | ||||
| impl ValueType for bool { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool { | ||||
|         val.set_bool(*self); | ||||
|         true | ||||
|     } | ||||
|  | ||||
|     fn set_value(&mut self, val: &Variant) { | ||||
|         *self = val.get_bool().unwrap_or(false); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Реализация для tm | ||||
| impl ValueType for Tm { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool { | ||||
|         val.set_date(*self); | ||||
|         true | ||||
|     } | ||||
|  | ||||
|     fn set_value(&mut self, val: &Variant) { | ||||
|         *self = val.get_date().unwrap_or(Tm::default()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Реализация для String | ||||
| impl ValueType for String { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool { | ||||
|         let s: Vec<u16> = self.encode_utf16().collect(); | ||||
|         val.set_str1c(s.as_slice()).is_ok() | ||||
|     } | ||||
|  | ||||
|     fn set_value(&mut self, val: &Variant) { | ||||
|         *self = val.get_string().unwrap_or("".to_string()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Реализация для Vec<u8> | ||||
| impl ValueType for Vec<u8> { | ||||
|     fn get_value(&self, val: &mut Variant) -> bool { | ||||
|         val.set_blob(self.as_slice()).is_ok() | ||||
|     } | ||||
|  | ||||
|     fn set_value(&mut self, val: &Variant) { | ||||
|         *self = val.get_blob().unwrap_or(&[]).to_vec() | ||||
|     } | ||||
| } | ||||
							
								
								
									
										53
									
								
								src/addins/sqlite/src/core/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/addins/sqlite/src/core/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| pub mod getset; | ||||
|  | ||||
| use addin1c::{name, RawAddin, Variant}; | ||||
|  | ||||
| use crate::component::METHODS; | ||||
| use crate::component::PROPS; | ||||
| use crate::component::get_params_amount; | ||||
| use crate::component::cal_func; | ||||
| use crate::component::AddIn; | ||||
|  | ||||
| // Определение класса | ||||
| impl RawAddin for AddIn { | ||||
|  | ||||
|     fn register_extension_as(&mut self) -> &'static [u16] { | ||||
|         name!("Main") | ||||
|     } | ||||
|     fn get_n_props(&mut self) -> usize { | ||||
|         PROPS.len() | ||||
|     } | ||||
|     fn find_prop(&mut self, name: &[u16]) -> Option<usize> { | ||||
|         PROPS.iter().position(|&x| x == name) | ||||
|     } | ||||
|     fn get_prop_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> { PROPS.get(num).copied() } | ||||
|     fn get_prop_val(&mut self, num: usize, val: &mut Variant) -> bool {let field: &dyn getset::ValueType = &self[num]; field.get_value(val) } | ||||
|     fn set_prop_val(&mut self, num: usize, val: &Variant) -> bool {let field: &mut dyn getset::ValueType = &mut self[num]; field.set_value(val); true } | ||||
|     fn is_prop_readable(&mut self, _num: usize) -> bool { true } | ||||
|     fn is_prop_writable(&mut self, _num: usize) -> bool { true } | ||||
|     fn get_n_methods(&mut self) -> usize { METHODS.len() } | ||||
|     fn find_method(&mut self, name: &[u16]) -> Option<usize> { METHODS.iter().position(|&x| x == name) } | ||||
|     fn get_method_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> { METHODS.get(num).copied() } | ||||
|     fn get_n_params(&mut self, num: usize) -> usize { get_params_amount(num) } | ||||
|     fn get_param_def_value(&mut self, _method_num: usize, _param_num: usize, _value: Variant, ) -> bool { true } | ||||
|     fn has_ret_val(&mut self, _num: usize) -> bool { true } | ||||
|     fn call_as_proc(&mut self, _num: usize, _params: &mut [Variant]) -> bool { false } | ||||
|     fn call_as_func(&mut self, num: usize, params: &mut [Variant], ret_value: &mut Variant, ) -> bool { cal_func(self, num, params).get_value(ret_value) } | ||||
|  | ||||
| } | ||||
|  | ||||
| impl std::ops::Index<usize> for AddIn { | ||||
|     type Output = dyn getset::ValueType; | ||||
|  | ||||
|     fn index(&self, index: usize) -> &Self::Output { | ||||
|         unsafe { &*self.get_field_ptr(index) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl std::ops::IndexMut<usize> for AddIn { | ||||
|     fn index_mut(&mut self, index: usize) -> &mut Self::Output { | ||||
|         unsafe { &mut *self.get_field_ptr_mut(index) } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										49
									
								
								src/addins/sqlite/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/addins/sqlite/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| pub mod component; | ||||
| mod core; | ||||
|  | ||||
|  | ||||
| use std::{ | ||||
|     ffi::{c_int, c_long, c_void}, | ||||
|     sync::atomic::{AtomicI32, Ordering}, | ||||
| }; | ||||
|  | ||||
| use component::AddIn; | ||||
| use addin1c::{create_component, destroy_component, name, AttachType}; | ||||
|  | ||||
| pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1); | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[no_mangle] | ||||
| pub unsafe extern "C" fn GetClassObject(_name: *const u16, component: *mut *mut c_void) -> c_long { | ||||
|  | ||||
|     let addin = AddIn::new(); | ||||
|     create_component(component, addin) | ||||
|  | ||||
| } | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[no_mangle] | ||||
| pub unsafe extern "C" fn DestroyObject(component: *mut *mut c_void) -> c_long { | ||||
|     destroy_component(component) | ||||
| } | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[no_mangle] | ||||
| pub extern "C" fn GetClassNames() -> *const u16 { | ||||
|     // small strings for performance | ||||
|     name!("Main").as_ptr() | ||||
| } | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[no_mangle] | ||||
| #[allow(static_mut_refs)] | ||||
| pub unsafe extern "C" fn SetPlatformCapabilities(capabilities: c_int) -> c_int { | ||||
|     PLATFORM_CAPABILITIES.store(capabilities, Ordering::Relaxed); | ||||
|     3 | ||||
| } | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[no_mangle] | ||||
| pub extern "C" fn GetAttachType() -> AttachType { | ||||
|     AttachType::Any | ||||
| } | ||||
| @@ -1,7 +1,8 @@ | ||||
| @echo off | ||||
|  | ||||
| :: Установить переменную | ||||
| set LIB_NAME=opi_addin | ||||
| set CARGO_NAME=opi_addin | ||||
| set LIB_NAME=OPI_AddIn | ||||
| set OPENSSL_DIR=C:\msys64\mingw64 | ||||
| set OPENSSL_LIB_DIR=%OPENSSL_DIR%\lib | ||||
| set OPENSSL_INCLUDE_DIR=%OPENSSL_DIR%\include | ||||
| @@ -31,26 +32,31 @@ cargo zigbuild --release --target i686-unknown-linux-gnu | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Копирование файлов .dll и .so | ||||
| copy /y target\x86_64-pc-windows-msvc\release\%LIB_NAME%.dll "%OUTPUT_DIR%\AddIn_x64_windows.dll" | ||||
| copy /y target\x86_64-pc-windows-msvc\release\%CARGO_NAME%.dll "%OUTPUT_DIR%\AddIn_x64_windows.dll" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y target\i686-pc-windows-msvc\release\%LIB_NAME%.dll "%OUTPUT_DIR%\AddIn_x86_windows.dll" | ||||
| copy /y target\i686-pc-windows-msvc\release\%CARGO_NAME%.dll "%OUTPUT_DIR%\AddIn_x86_windows.dll" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y target\x86_64-unknown-linux-gnu\release\lib%LIB_NAME%.so "%OUTPUT_DIR%\AddIn_x64_linux.so" | ||||
| copy /y target\x86_64-unknown-linux-gnu\release\lib%CARGO_NAME%.so "%OUTPUT_DIR%\AddIn_x64_linux.so" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y target\i686-unknown-linux-gnu\release\lib%LIB_NAME%.so "%OUTPUT_DIR%\AddIn_x86_linux.so" | ||||
| copy /y target\i686-unknown-linux-gnu\release\lib%CARGO_NAME%.so "%OUTPUT_DIR%\AddIn_x86_linux.so" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y MANIFEST.XML "%OUTPUT_DIR%\MANIFEST.XML" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| :: Архивация | ||||
| set ZIP_NAME=addin.zip | ||||
| powershell -Command "Compress-Archive -Path '%OUTPUT_DIR%\*' -Force -DestinationPath '%ZIP_NAME%'" | ||||
| powershell -Command "Compress-Archive -Path '%OUTPUT_DIR%\*' -Force -DestinationPath '%LIB_NAME%.zip'" | ||||
| if errorlevel 1 goto :error | ||||
|  | ||||
| copy /y "%LIB_NAME%.zip" "../../ru/OInt/addins/%LIB_NAME%.zip" | ||||
| copy /y "%LIB_NAME%.zip" "../../en/OInt/addins/%LIB_NAME%.zip" | ||||
|  | ||||
| copy /y "%LIB_NAME%.zip" "../../ru/OPI/src/CommonTemplates/%LIB_NAME%/Template.addin" | ||||
| copy /y "%LIB_NAME%.zip" "../../en/OPI/src/CommonTemplates/%LIB_NAME%/Template.addin" | ||||
|  | ||||
| if exist "%OUTPUT_DIR%" ( | ||||
|     rmdir /S /Q "%OUTPUT_DIR%" | ||||
| ) | ||||
|   | ||||
| @@ -24,13 +24,13 @@ impl RawAddin for AddIn { | ||||
|     fn get_prop_val(&mut self, num: usize, val: &mut Variant) -> bool {let field: &dyn getset::ValueType = &self[num]; field.get_value(val) } | ||||
|     fn set_prop_val(&mut self, num: usize, val: &Variant) -> bool {let field: &mut dyn getset::ValueType = &mut self[num]; field.set_value(val); true } | ||||
|     fn is_prop_readable(&mut self, _num: usize) -> bool { true } | ||||
|     fn is_prop_writable(&mut self, num: usize) -> bool { true } | ||||
|     fn is_prop_writable(&mut self, _num: usize) -> bool { true } | ||||
|     fn get_n_methods(&mut self) -> usize { METHODS.len() } | ||||
|     fn find_method(&mut self, name: &[u16]) -> Option<usize> { METHODS.iter().position(|&x| x == name) } | ||||
|     fn get_method_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> { METHODS.get(num).copied() } | ||||
|     fn get_n_params(&mut self, num: usize) -> usize { get_params_amount(num) } | ||||
|     fn get_param_def_value(&mut self, _method_num: usize, _param_num: usize, _value: Variant, ) -> bool { true } | ||||
|     fn has_ret_val(&mut self, num: usize) -> bool { true } | ||||
|     fn has_ret_val(&mut self, _num: usize) -> bool { true } | ||||
|     fn call_as_proc(&mut self, _num: usize, _params: &mut [Variant]) -> bool { false } | ||||
|     fn call_as_func(&mut self, num: usize, params: &mut [Variant], ret_value: &mut Variant, ) -> bool { cal_func(self, num, params).get_value(ret_value) } | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1); | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[no_mangle] | ||||
| pub unsafe extern "C" fn GetClassObject(name: *const u16, component: *mut *mut c_void) -> c_long { | ||||
| pub unsafe extern "C" fn GetClassObject(_name: *const u16, component: *mut *mut c_void) -> c_long { | ||||
|  | ||||
|     let addin = AddIn::new(); | ||||
|     create_component(component, addin) | ||||
| @@ -35,6 +35,7 @@ pub extern "C" fn GetClassNames() -> *const u16 { | ||||
| } | ||||
|  | ||||
| #[allow(non_snake_case)] | ||||
| #[allow(static_mut_refs)] | ||||
| #[no_mangle] | ||||
| pub unsafe extern "C" fn SetPlatformCapabilities(capabilities: c_int) -> c_int { | ||||
|     PLATFORM_CAPABILITIES.store(capabilities, Ordering::Relaxed); | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								src/en/OInt/addins/OPI_SQLite.zip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/en/OInt/addins/OPI_SQLite.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/ru/OInt/addins/OPI_SQLite.zip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/ru/OInt/addins/OPI_SQLite.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										9
									
								
								src/ru/OPI/src/CommonTemplates/OPI_SQLite/OPI_SQLite.mdo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/ru/OPI/src/CommonTemplates/OPI_SQLite/OPI_SQLite.mdo
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <mdclass:CommonTemplate xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="b732dedd-b9cd-40d8-9482-847467424ab2"> | ||||
|   <name>OPI_SQLite</name> | ||||
|   <synonym> | ||||
|     <key>ru</key> | ||||
|     <value>SQLite</value> | ||||
|   </synonym> | ||||
|   <templateType>AddIn</templateType> | ||||
| </mdclass:CommonTemplate> | ||||
							
								
								
									
										
											BIN
										
									
								
								src/ru/OPI/src/CommonTemplates/OPI_SQLite/Template.addin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/ru/OPI/src/CommonTemplates/OPI_SQLite/Template.addin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -40,6 +40,7 @@ | ||||
|   </configurationInformationAddress> | ||||
|   <subsystems>Subsystem.OPI_Интеграция</subsystems> | ||||
|   <commonTemplates>CommonTemplate.OPI_TCPClient</commonTemplates> | ||||
|   <commonTemplates>CommonTemplate.OPI_SQLite</commonTemplates> | ||||
|   <commonModules>CommonModule.OPI_Инструменты</commonModules> | ||||
|   <commonModules>CommonModule.OPI_Криптография</commonModules> | ||||
|   <commonModules>CommonModule.OPI_ПреобразованиеТипов</commonModules> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user