Files
GeneralUtils/src/dbUtil.jl
2026-06-07 15:32:49 +07:00

233 lines
7.5 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module dbUtil
export dictToPostgresKeyValueString, generateInsertSQL, generateUpdateSQL
using JSON, DataStructures, Distributions, Random, Dates, UUIDs, DataFrames,
SHA
using ..util
#[PENDING] update code to use JSON
# ---------------------------------------------- 100 --------------------------------------------- #
"""
dictToPostgresKeyValueString - Convert dictionary to PostgreSQL key-value string format
This function takes a dictionary and converts it into a PostgreSQL-compatible key-value string
format suitable for storage in a TEXT field. The output format uses curly braces with comma-separated
key-value pairs, where string values are quoted.
# Function Workflow:
1. Iterates through dictionary key-value pairs
2. Handles nested dictionaries by recursively converting them
3. Wraps string values in double quotes
4. Formats numeric and other values without quotes
5. Returns a PostgreSQL-compatible key-value string enclosed in curly braces
# Arguments:
- `dict::Dict` - Dictionary containing key-value pairs to convert
# Return:
- A String in PostgreSQL key-value format: "{key1: value1, key2: \"value2\", ...}"
# Example
```jldoctest
julia> data = Dict{String, Any}(
"name" => "John",
"age" => 30,
"city" => "New York"
);
julia> dictToPostgresKeyValueString(data)
"{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}"
```
"""
function dictToPostgresKeyValueString(dict)
parts = []
for (k, v) in dict
if isa(v, Dict)
push!(parts, "\"$k\": " * dict_to_string(v))
elseif isa(v, AbstractString)
push!(parts, "\"$k\": \"$v\"")
else
push!(parts, "\"$k\": $v")
end
end
return "{" * join(parts, ", ") * "}"
end
""" generateInsertSQL - Generate SQL INSERT statement from dictionary data
This function constructs a SQL INSERT statement by extracting values for specified columns
from a dictionary and formatting them into a valid PostgreSQL INSERT query.
# Function Workflow:
1. Iterates through the dictionary key-value pairs
2. Filters keys to only include those present in `columnToInsert`
3. Collects column names and their corresponding values
4. Constructs the final SQL INSERT statement
# Arguments:
- `table_name::String` - Name of the database table to insert into
- `columnToInsert::Vector{Symbol}` - List of column names to include in the INSERT statement
- `data::Dict{Symbol, Any}` - Dictionary containing column-value pairs for the insert
# Return:
- A String containing the SQL INSERT statement
# Example
```jldoctest
julia> using UUIDs
# Insert a single record with specific columns
table_name = "wine"
columnToInsert = [:acidity, :tannin, :country, :region, :winery]
data = Dict{Symbol, Any}(
:grape => "Cabernet Sauvignon",
:acidity => "medium", # using descriptive scale (low/medium/full)
:tannin => "medium-plus", # common wine descriptor
:country => "France",
:description => "A rich and structured red wine with notes of blackcurrant, cedar, and subtle oak.",
:region => "Bordeaux",
:winery => "Château Margaux",
:intensity => "medium", # intensity is usually low/medium/full
:sweetness => "dry", # dry/medium-dry/medium/medium-sweet/sweet
:tasting_notes => "Blackberry, graphite, tobacco, vanilla, and subtle earth.",
:wine_name => "Château Margaux Grand Cru",
:wine_id => "8f3c7a2e-1b4d-4a9f-9c2e-4a8b3d6e5f7a", # UUID-like (valid hex)
:wine_type => "Red",
:other_attributes => Dict{String, Any}(
"vintage" => 2018,
"alcohol_percent" => 13.5,
"ph" => 3.6,
" aging_years" => 24, # years in barrel
" producer_code" => "CM-GRAND"
),
:fizziness => "still",
:serving_temperature => "1618°C",
:additional_search_term => ["Cabernet", "Bordeaux red", "premium wine", "CabSav"]
)
julia> generateInsertSQL(table_name, columnToInsert, data)
"INSERT INTO wine (acidity, tannin, country, region, winery) VALUES ('medium', 'medium-plus', 'France', 'Bordeaux', 'Château Margaux');"
```
"""
function generateInsertSQL(table_name::String, columnToInsert::Vector{Symbol}, data::Dict{Symbol, Any})
columns = String[]
values = String[]
for (key, value) in data
if key columnToInsert
push!(columns, string(key))
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(values, value_str)
end
end
columns_str = join(columns, ", ")
values_str = join(values, ", ")
return "INSERT INTO $table_name ($columns_str) VALUES ($values_str);"
end
function generateInsertSQL(table_name::String, data::AbstractDict{String, Any})
columns = String[]
values = String[]
for (key, value) in data
if key columnToInsert
push!(columns, string(key))
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(values, value_str)
end
end
columns_str = join(columns, ", ")
values_str = join(values, ", ")
return "INSERT INTO $table_name ($columns_str) VALUES ($values_str);"
end
# ---------------------------------------------- 100 --------------------------------------------- #
""" generateUpdateSQL - Generate SQL UPDATE statement from dictionary data
This function constructs a SQL UPDATE statement by updating multiple columns
based on a primary key condition.
# Arguments:
- `table_name::String` - Name of the database table to update
- `pk_column::Symbol` - The primary key column name
- `pk_value` - The primary key value (used in WHERE clause)
- `data::Dict{Symbol, Any}` - Dictionary containing column-value pairs to update
# Return:
- A String containing the SQL UPDATE statement
# Example
```jldoctest
julia> using UUIDs
# Update multiple columns using a dictionary
table_name = "wine"
pk_column = :wine_id
pk_value = "8f3c7a2e-1b4d-4a9f-9c2e-4a8b3d6e5f7a"
data = Dict{Symbol, Any}(
:acidity => "full",
:tannin => "medium",
:country => "Italy"
)
julia> generateUpdateSQL(table_name, pk_column, pk_value, data)
"UPDATE wine SET acidity = 'full', tannin = 'medium', country = 'Italy' WHERE wine_id = '8f3c7a2e-1b4d-4a9f-9c2e-4a8b3d6e5f7a';"
```
"""
function generateUpdateSQL(table_name::String, pk_column::String, pk_value,
data::AbstractDict{String, Any})
# Build SET clause
set_parts = String[]
for (key, value) in data
if key [pk_column]
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(set_parts, "$(string(key)) = $value_str")
end
end
set_clause = join(set_parts, ", ")
# Handle primary key value
pk_val_str = isa(pk_value, AbstractString) ? "'$pk_value'" : "$pk_value"
return "UPDATE $table_name SET $set_clause WHERE $pk_column = $pk_val_str;"
end
function generateUpdateSQL(table_name::String, pk_dict::AbstractDict{String, Any},
data::AbstractDict{String, Any})
# Build SET clause
set_parts = String[]
for (key, value) in data
if key keys(data)
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(set_parts, "$(string(key)) = $value_str")
end
end
set_clause = join(set_parts, ", ")
# Build WHERE clause for composite keys
where_parts = String[]
for (col, val) in pk_dict
val_str = isa(val, AbstractString) ? "'$val'" : "$val"
push!(where_parts, "$(string(col)) = $val_str")
end
where_clause = join(where_parts, " AND ")
return "UPDATE $table_name SET $set_clause WHERE $where_clause;"
end
end # module