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 => "16–18°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