1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-08-10 22:41:43 +02:00

Доработки PG

This commit is contained in:
Anton Titovets
2025-02-11 22:09:10 +03:00
parent 295632d392
commit cf2f616333
7 changed files with 131 additions and 55 deletions

View File

@@ -86,11 +86,6 @@ fn process_object(object: &Map<String, Value>) -> Result<Box<dyn ToSql + Sync>,
.as_bool()
.map(|v| Box::new(v) as Box<dyn ToSql + Sync>)
.ok_or_else(|| "Invalid value for BOOL".to_string()),
"\"CHAR\"" | "OLDCHAR" => value
.as_i64()
.and_then(|v| i8::try_from(v).ok())
.map(|v| Box::new(v) as Box<dyn ToSql + Sync>)
.ok_or_else(|| "Invalid value for \"char\"".to_string()),
"SMALLINT" | "SMALLSERIAL" => value
.as_i64()
.and_then(|v| i16::try_from(v).ok())
@@ -123,6 +118,11 @@ fn process_object(object: &Map<String, Value>) -> Result<Box<dyn ToSql + Sync>,
.as_str()
.map(|v| Box::new(v.to_string()) as Box<dyn ToSql + Sync>)
.ok_or_else(|| format!("Invalid value for {}", key)),
"\"CHAR\"" | "OLDCHAR" => value
.as_i64()
.and_then(|v| i8::try_from(v).ok())
.map(|v| Box::new(v) as Box<dyn ToSql + Sync>)
.ok_or_else(|| "Invalid value for \"char\"".to_string()),
"BYTEA" => value
.as_str()
.map(|blob_str| {
@@ -160,12 +160,18 @@ fn process_object(object: &Map<String, Value>) -> Result<Box<dyn ToSql + Sync>,
.map(|ip| Box::new(ip) as Box<dyn ToSql + Sync>)
.ok_or_else(|| "Invalid value for INET".to_string()),
"JSON" | "JSONB" => {
// Если значение уже является объектом или массивом, передаем его как есть
if value.is_object() || value.is_array() {
Ok(Box::new(value.to_string()) as Box<dyn ToSql + Sync>)
Ok(Box::new(value.clone()) as Box<dyn ToSql + Sync>)
} else if value.is_string() {
Ok(Box::new(value.as_str().unwrap().to_string()) as Box<dyn ToSql + Sync>)
let json_str = value.as_str().ok_or("Expected a string value for JSON/JSONB")?;
match serde_json::from_str::<Value>(json_str) {
Ok(parsed_value) => Ok(Box::new(parsed_value) as Box<dyn ToSql + Sync>),
Err(e) => Err(format!("Invalid JSON string: {}", e)),
}
} else {
Err("Invalid value for JSON/JSONB: must be an object, array, or string".to_string())
Err("Invalid value for JSON/JSONB: must be an object, array, or valid JSON string".to_string())
}
}
_ => Err(format!("Unsupported type: {}", key)),
@@ -182,39 +188,45 @@ fn rows_to_json(rows: Vec<postgres::Row>) -> String {
let column_name = column.name();
let column_type = column.type_().name();
let value = match column_type.to_lowercase().as_str() {
"bool" => row.get::<_, Option<bool>>(column_name).map(Value::Bool).unwrap_or(Value::Null),
"int2" | "smallint" | "smallserial" => row.get::<_, Option<i16>>(column_name)
let value = match column_type.to_uppercase().as_str() {
"BOOL" => row.get::<_, Option<bool>>(column_name)
.map(Value::Bool)
.unwrap_or(Value::Null),
"INT2" | "SMALLINT" | "SMALLSERIAL" => row.get::<_, Option<i16>>(column_name)
.map(|v| Value::Number(v.into()))
.unwrap_or(Value::Null),
"int4" | "int" | "serial" => row.get::<_, Option<i32>>(column_name)
"INT4" | "INT" | "SERIAL" => row.get::<_, Option<i32>>(column_name)
.map(|v| Value::Number(v.into()))
.unwrap_or(Value::Null),
"oid" => row.get::<_, Option<u32>>(column_name)
"OID" => row.get::<_, Option<u32>>(column_name)
.map(|v| Value::Number(v.into()))
.unwrap_or(Value::Null),
"int8" | "bigint" | "bigserial" => row.get::<_, Option<i64>>(column_name)
"INT8" | "BIGINT" | "BIGSERIAL" => row.get::<_, Option<i64>>(column_name)
.map(|v| Value::Number(v.into()))
.unwrap_or(Value::Null),
"float4" | "real" => row.get::<_, Option<f32>>(column_name)
"FLOAT4" | "REAL" => row.get::<_, Option<f32>>(column_name)
.map(|v| match v {
v if v.is_nan() => Value::String("NaN".to_string()),
v if v.is_infinite() => Value::String("Infinity".to_string()),
_ => serde_json::Number::from_f64(v as f64).map(Value::Number).unwrap_or(Value::Null),
})
.unwrap_or(Value::Null),
"float8" | "double precision" => row.get::<_, Option<f64>>(column_name)
"FLOAT8" | "DOUBLE PRECISION" => row.get::<_, Option<f64>>(column_name)
.map(|v| match v {
v if v.is_nan() => Value::String("NaN".to_string()),
v if v.is_infinite() => Value::String("Infinity".to_string()),
_ => serde_json::Number::from_f64(v).map(Value::Number).unwrap_or(Value::Null),
})
.unwrap_or(Value::Null),
"varchar" | "text" | "char" | "citext" | "name" | "unknown" => row.get::<_, Option<String>>(column_name)
"\"CHAR\"" => {
row.get::<_, Option<i8>>(column_name)
.map(|v| Value::Number(v.into()))
.unwrap_or(Value::Null)
},
"VARCHAR" | "TEXT" | "CHAR" | "CITEXT" | "NAME" | "LTREE" | "LQUERY" | "LTXTQUERY" | "UNKNOWN" => row.get::<_, Option<String>>(column_name)
.map(Value::String)
.unwrap_or(Value::Null),
"bytea" => {
"BYTEA" => {
let base64_string = row.get::<_, Option<Vec<u8>>>(column_name)
.map(|v| general_purpose::STANDARD.encode(v))
.unwrap_or("Unable to make Base64 string".to_string());
@@ -223,7 +235,7 @@ fn rows_to_json(rows: Vec<postgres::Row>) -> String {
blob_object.insert("BYTEA".to_string(), Value::String(base64_string)); // Оборачиваем в объект
Value::Object(blob_object)
},
"hstore" => row.get::<_, Option<HashMap<String, Option<String>>>>(column_name)
"HSTORE" => row.get::<_, Option<HashMap<String, Option<String>>>>(column_name)
.map(|hstore| {
let mut map = Map::new();
for (k, v) in hstore {
@@ -232,7 +244,7 @@ fn rows_to_json(rows: Vec<postgres::Row>) -> String {
Value::Object(map)
})
.unwrap_or(Value::Null),
"timestamp" | "timestamptz" => row.get::<_, Option<SystemTime>>(column_name)
"TIMESTAMP" | "TIMESTAMP WITH TIME ZONE" | "TIMESTAMPTZ" => row.get::<_, Option<SystemTime>>(column_name)
.map(|time| {
match time.duration_since(SystemTime::UNIX_EPOCH) {
Ok(d) => Value::Number(d.as_secs().into()), // Положительное значение для времени после UNIX_EPOCH
@@ -241,18 +253,16 @@ fn rows_to_json(rows: Vec<postgres::Row>) -> String {
Err(_) => Value::Null, // Это вообще не должно произойти
},
}
})
.unwrap_or(Value::Null),
"inet" => row.get::<_, Option<IpAddr>>(column_name)
"INET" => row.get::<_, Option<IpAddr>>(column_name)
.map(|ip| Value::String(ip.to_string()))
.unwrap_or(Value::Null),
"json" | "jsonb" => {
row.get::<_, Option<String>>(column_name)
.and_then(|s| serde_json::from_str(&s).ok())
"JSON" | "JSONB" => {
row.get::<_, Option<Value>>(column_name)
.unwrap_or(Value::Null)
},
_ => Value::Null,
current_type => Value::String(format!("Unsupported type: {}", current_type)),
};
row_map.insert(column_name.to_string(), value);

Binary file not shown.

Binary file not shown.

View File

@@ -2324,7 +2324,8 @@
PostgreSQL_СоздатьТаблицу(ПараметрыТеста);
PostgreSQL_ПолучитьИнформациюОТаблице(ПараметрыТеста);
PostgreSQL_ДобавитьЗаписи(ПараметрыТеста);
PostgreSQL_УдалитьБазуДанных(ПараметрыТеста);
PostgreSQL_ПолучитьЗаписи(ПараметрыТеста);
//PostgreSQL_УдалитьБазуДанных(ПараметрыТеста);
КонецПроцедуры
@@ -17306,8 +17307,9 @@
База = "testbase1";
OPI_PostgreSQL.УдалитьБазуДанных(База, СтрокаПодключения); // SKIP
Удаление = OPI_PostgreSQL.УдалитьБазуДанных(База, СтрокаПодключения); // SKIP
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Удаление, "СоздатьБазуДанных (удаление)", "PostgreSQL"); // SKIP
Результат = OPI_PostgreSQL.СоздатьБазуДанных(База, СтрокаПодключения);
// END
@@ -17349,18 +17351,27 @@
Таблица = "testtable";
СтруктураКолонок = Новый Структура;
СтруктураКолонок.Вставить("bool_field" , "BOOL");
СтруктураКолонок.Вставить("char_field" , """char""");
СтруктураКолонок.Вставить("smallint_field", "SMALLINT");
СтруктураКолонок.Вставить("int_field" , "INT");
СтруктураКолонок.Вставить("oid_field" , "OID");
СтруктураКолонок.Вставить("bigint_field" , "BIGINT");
СтруктураКолонок.Вставить("real_field" , "REAL");
СтруктураКолонок.Вставить("dp_field" , "DOUBLE PRECISION");
СтруктураКолонок.Вставить("text_field" , "TEXT");
СтруктураКолонок.Вставить("bytea_field" , "BYTEA");
СтруктураКолонок.Вставить("ts_field" , "TIMESTAMP");
СтруктураКолонок.Вставить("ip_field" , "INET");
СтруктураКолонок.Вставить("bool_field" , "BOOL");
СтруктураКолонок.Вставить("oldchar_field" , """char""");
СтруктураКолонок.Вставить("smallint_field" , "SMALLINT");
СтруктураКолонок.Вставить("smallserial_field", "SMALLSERIAL");
СтруктураКолонок.Вставить("int_field" , "INT");
СтруктураКолонок.Вставить("serial_field" , "SERIAL");
СтруктураКолонок.Вставить("oid_field" , "OID");
СтруктураКолонок.Вставить("bigint_field" , "BIGINT");
СтруктураКолонок.Вставить("bigserial_field" , "BIGSERIAL");
СтруктураКолонок.Вставить("real_field" , "REAL");
СтруктураКолонок.Вставить("dp_field" , "DOUBLE PRECISION");
СтруктураКолонок.Вставить("text_field" , "TEXT");
СтруктураКолонок.Вставить("varchar_field" , "VARCHAR");
СтруктураКолонок.Вставить("char_field" , "CHAR(1)");
СтруктураКолонок.Вставить("name_field" , "NAME");
СтруктураКолонок.Вставить("bytea_field" , "BYTEA");
СтруктураКолонок.Вставить("ts_field" , "TIMESTAMP");
СтруктураКолонок.Вставить("tswtz_field" , "TIMESTAMP WITH TIME ZONE");
СтруктураКолонок.Вставить("ip_field" , "INET");
СтруктураКолонок.Вставить("json_field" , "JSON");
СтруктураКолонок.Вставить("jsonb_field" , "JSONB");
Результат = OPI_PostgreSQL.СоздатьТаблицу(Таблица, СтруктураКолонок, СтрокаПодключения);
@@ -17404,21 +17415,32 @@
Картинка = ПараметрыФункции["Picture"];
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Картинка); // Картинка - Тип: ДвоичныеДанные
СлучайнаяСтруктура = Новый Структура("key,value", "ItsKey", 10);
СтруктураЗаписи = Новый Структура;
СтруктураЗаписи.Вставить("bool_field" , Новый Структура("BOOL" , Истина));
СтруктураЗаписи.Вставить("char_field" , Новый Структура("OLDCHAR" , 1));
СтруктураЗаписи.Вставить("smallint_field", Новый Структура("SMALLINT" , 5));
СтруктураЗаписи.Вставить("int_field" , Новый Структура("INT" , 100));
СтруктураЗаписи.Вставить("oid_field" , Новый Структура("OID" , 24576));
СтруктураЗаписи.Вставить("bigint_field" , Новый Структура("BIGINT" , 9999999));
СтруктураЗаписи.Вставить("real_field" , Новый Структура("REAL" , 15.2));
СтруктураЗаписи.Вставить("dp_field" , Новый Структура("DOUBLE_PRECISION", 1.0000000000000002));
СтруктураЗаписи.Вставить("text_field" , Новый Структура("TEXT" , "Some text"));
СтруктураЗаписи.Вставить("bytea_field" , Новый Структура("BYTEA" , Картинка));
СтруктураЗаписи.Вставить("ts_field" , Новый Структура("TIMESTAMP" , 1739207915));
СтруктураЗаписи.Вставить("ip_field" , Новый Структура("INET" , "127.0.0.1"));
СтруктураЗаписи.Вставить("bool_field" , Новый Структура("BOOL" , Истина));
СтруктураЗаписи.Вставить("oldchar_field" , Новый Структура("OLDCHAR" , 1)); // или "char"
СтруктураЗаписи.Вставить("smallint_field" , Новый Структура("SMALLINT" , 5));
СтруктураЗаписи.Вставить("smallserial_field", Новый Структура("SMALLSERIAL" , 6));
СтруктураЗаписи.Вставить("int_field" , Новый Структура("INT" , 100));
СтруктураЗаписи.Вставить("serial_field" , Новый Структура("SERIAL" , 100));
СтруктураЗаписи.Вставить("oid_field" , Новый Структура("OID" , 24576));
СтруктураЗаписи.Вставить("bigint_field" , Новый Структура("BIGINT" , 9999999));
СтруктураЗаписи.Вставить("bigserial_field" , Новый Структура("BIGSERIAL" , 9999999));
СтруктураЗаписи.Вставить("real_field" , Новый Структура("REAL" , 15.2));
СтруктураЗаписи.Вставить("dp_field" , Новый Структура("DOUBLE_PRECISION" , 1.0000000000000002)); // или DOUBLE PRECISION
СтруктураЗаписи.Вставить("text_field" , Новый Структура("TEXT" , "Some text"));
СтруктураЗаписи.Вставить("varchar_field" , Новый Структура("VARCHAR" , "Some varchar"));
СтруктураЗаписи.Вставить("char_field" , Новый Структура("CHAR" , "A"));
СтруктураЗаписи.Вставить("name_field" , Новый Структура("NAME" , "Vitaly"));
СтруктураЗаписи.Вставить("bytea_field" , Новый Структура("BYTEA" , Картинка));
СтруктураЗаписи.Вставить("ts_field" , Новый Структура("TIMESTAMP" , 1739207915));
СтруктураЗаписи.Вставить("tswtz_field" , Новый Структура("TIMESTAMP_WITH_TIME_ZONE", 1739207915)); // или TIMESTAMP WITH TIME ZONE
СтруктураЗаписи.Вставить("ip_field" , Новый Структура("INET" , "127.0.0.1"));
СтруктураЗаписи.Вставить("json_field" , Новый Структура("JSON" , СлучайнаяСтруктура));
СтруктураЗаписи.Вставить("jsonb_field" , Новый Структура("JSONB" , СлучайнаяСтруктура));
Результат = OPI_PostgreSQL.ДобавитьЗаписи(Таблица, СтруктураЗаписи, Ложь, СтрокаПодключения);
// END
@@ -17428,6 +17450,50 @@
КонецПроцедуры
Процедура PostgreSQL_ПолучитьЗаписи(ПараметрыФункции)
Адрес = ПараметрыФункции["PG_IP"];
Логин = "bayselonarrend";
Пароль = ПараметрыФункции["PG_Password"];
База = "testbase1";
СтрокаПодключения = OPI_PostgreSQL.СформироватьСтрокуПодключения(Адрес, База, Логин, Пароль);
Таблица = "testtable";
Поля = Новый Массив;
Поля.Добавить("bool_field");
Поля.Добавить("oldchar_field");
Поля.Добавить("smallint_field");
Поля.Добавить("smallserial_field");
Поля.Добавить("int_field");
Поля.Добавить("serial_field");
Поля.Добавить("oid_field");
Поля.Добавить("bigint_field");
Поля.Добавить("bigserial_field");
Поля.Добавить("real_field");
Поля.Добавить("dp_field");
Поля.Добавить("text_field");
Поля.Добавить("varchar_field");
Поля.Добавить("char_field");
Поля.Добавить("name_field");
Поля.Добавить("bytea_field");
Поля.Добавить("ts_field");
Поля.Добавить("tswtz_field");
Поля.Добавить("ip_field");
Поля.Добавить("json_field");
Поля.Добавить("jsonb_field");
Результат = OPI_PostgreSQL.ПолучитьЗаписи(Таблица, Поля, , , , СтрокаПодключения);
// END
Результат["data"][0]["bytea_field"]["BYTEA"] = Лев(Результат["data"][0]["bytea_field"]["BYTEA"], 10) + "...";
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Результат, "ДобавитьЗаписи", "PostgreSQL");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(Результат);
КонецПроцедуры
#КонецОбласти
#КонецОбласти