162162function parse_object_env (name:: AbstractString )
163163 raw = strip (get (ENV , name, " " ))
164164 isempty (raw) && return Dict {String,Any} ()
165- value = JSON. parse (raw)
165+ value = JSON. parse (raw; dicttype = Dict{String,Any} )
166166 value isa AbstractDict || error (" $(name) must contain a JSON object." )
167167 Dict {String,Any} (String (key) => item for (key, item) in pairs (value))
168168end
@@ -470,18 +470,19 @@ function validate_table_columns(db::SQLite.DB, path::AbstractString, table::Abst
470470end
471471
472472function read_schema_version (db:: SQLite.DB , path:: AbstractString )
473- metadata_table = DBInterface. execute (db, " SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'benchledger_metadata' LIMIT 1" ) do result
474- iterate (result)
473+ metadata_table_found = DBInterface. execute (db, " SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'benchledger_metadata' LIMIT 1" ) do result
474+ iterate (result) != = nothing
475475 end
476- metadata_table === nothing && error (" Unsupported BenchLedger database in $(path) : missing benchledger_metadata." )
476+ metadata_table_found || error (" Unsupported BenchLedger database in $(path) : missing benchledger_metadata." )
477477
478478 # Avoid collect(...) here: SQLite.jl can materialize this single-column result as missing.
479- # Use the callback form so the statement is closed after taking the single required row.
480- schema_iter = DBInterface. execute (db, " SELECT value FROM benchledger_metadata WHERE key = 'schema_version' LIMIT 1" ) do result
481- iterate (result)
479+ # Materialize the scalar inside the callback before the statement is closed.
480+ schema_version = DBInterface. execute (db, " SELECT value FROM benchledger_metadata WHERE key = 'schema_version' LIMIT 1" ) do result
481+ row_iter = iterate (result)
482+ row_iter === nothing ? nothing : String (row_iter[1 ]. value)
482483 end
483- schema_iter === nothing && error (" Unsupported BenchLedger database in $(path) : missing benchledger_metadata.schema_version." )
484- String (schema_iter[ 1 ] . value)
484+ schema_version === nothing && error (" Unsupported BenchLedger database in $(path) : missing benchledger_metadata.schema_version." )
485+ schema_version
485486end
486487
487488function validate_schema_version! (db:: SQLite.DB , path:: AbstractString )
@@ -603,7 +604,7 @@ function migrate_v4_to_v5!(db::SQLite.DB, path::AbstractString)
603604 for row in DBInterface. execute (db, " SELECT code_state_id, label, code_date, metadata FROM benchmark_code_states_v4" )
604605 old_id = String (row. code_state_id)
605606 new_id = migrate_v4_code_state_id (old_id)
606- parsed_metadata = JSON. parse (String (row. metadata))
607+ parsed_metadata = JSON. parse (String (row. metadata); dicttype = Dict{String,Any} )
607608 identity, metadata = split_v4_code_state_metadata (parsed_metadata)
608609 persist_labeled_entity! (db, " benchmark_code_states" , new_id, canonical_json (identity), canonical_json (metadata), String (row. label); code_date= String (row. code_date))
609610 code_state_id_map[old_id] = new_id
@@ -612,7 +613,7 @@ function migrate_v4_to_v5!(db::SQLite.DB, path::AbstractString)
612613 environment_id_map = Dict {String,String} ()
613614 for row in DBInterface. execute (db, " SELECT environment_id, label, metadata FROM benchmark_environments_v4" )
614615 old_id = String (row. environment_id)
615- parsed_metadata = JSON. parse (String (row. metadata))
616+ parsed_metadata = JSON. parse (String (row. metadata); dicttype = Dict{String,Any} )
616617 identity, metadata = split_v4_environment_metadata (parsed_metadata)
617618 identity_json = canonical_json (identity)
618619 new_id = string (" env-" , bytes2hex (sha256 (codeunits (identity_json))))
@@ -630,11 +631,12 @@ function migrate_v4_to_v5!(db::SQLite.DB, path::AbstractString)
630631 (String (row. run_id), code_state_id_map[old_code_state_id], environment_id_map[old_environment_id], String (row. measured_at), String (row. notes), String (row. metadata)))
631632 end
632633
633- SQLite. execute (db, """
634- INSERT INTO benchmark_results (run_id, benchmark_id, benchmark_path, benchmark_label, metric_name, statistic, unit, value, better)
635- SELECT run_id, benchmark_id, benchmark_path, benchmark_label, metric_name, statistic, unit, value, better
636- FROM benchmark_results_v4
637- """ )
634+ SQLite. execute (db,
635+ """
636+ INSERT INTO benchmark_results (run_id, benchmark_id, benchmark_path, benchmark_label, metric_name, statistic, unit, value, better)
637+ SELECT run_id, benchmark_id, benchmark_path, benchmark_label, metric_name, statistic, unit, value, better
638+ FROM benchmark_results_v4
639+ """ )
638640
639641 SQLite. execute (db, " DROP TABLE benchmark_results_v4" )
640642 SQLite. execute (db, " DROP TABLE benchmark_runs_v4" )
@@ -649,8 +651,10 @@ FROM benchmark_results_v4
649651 SQLite. execute (db, " PRAGMA foreign_keys=ON" )
650652 end
651653
652- fk_violation = iterate (DBInterface. execute (db, " PRAGMA foreign_key_check" ))
653- fk_violation === nothing || error (" Foreign-key validation failed after migrating $(path) from schema v4 to v5." )
654+ fk_violation = DBInterface. execute (db, " PRAGMA foreign_key_check" ) do result
655+ iterate (result) != = nothing
656+ end
657+ fk_violation && error (" Foreign-key validation failed after migrating $(path) from schema v4 to v5." )
654658 validate_schema_version! (db, path)
655659 println (" BenchLedger schema migration v4 -> v5 completed." )
656660end
@@ -788,24 +792,27 @@ function benchmark_result_row(run_id::AbstractString, row::BenchmarkMetricRow)
788792end
789793
790794function persist_labeled_entity! (db:: SQLite.DB , table:: AbstractString , id_value:: AbstractString , identity:: AbstractString , metadata:: AbstractString , label:: AbstractString ; code_date:: Union{Nothing,AbstractString} = nothing )
791- code_date === nothing ?
792- DBInterface. execute (db, " INSERT INTO $(table) (id, label, identity, metadata) VALUES (?, ?, ?, ?) ON CONFLICT (id) DO NOTHING" , (id_value, label, identity, metadata)) :
795+ code_date === nothing ? DBInterface. execute (db, " INSERT INTO $(table) (id, label, identity, metadata) VALUES (?, ?, ?, ?) ON CONFLICT (id) DO NOTHING" , (id_value, label, identity, metadata)) :
793796 DBInterface. execute (db, " INSERT INTO $(table) (id, label, code_date, identity, metadata) VALUES (?, ?, ?, ?, ?) ON CONFLICT (id) DO NOTHING" , (id_value, label, code_date, identity, metadata))
794797
795- row_iter = DBInterface. execute (db, code_date === nothing ? " SELECT label, identity, metadata FROM $(table) WHERE id = ? LIMIT 1" : " SELECT label, code_date, identity, metadata FROM $(table) WHERE id = ? LIMIT 1" , (id_value,)) do result
796- iterate (result)
798+ row = DBInterface. execute (db, code_date === nothing ? " SELECT label, identity, metadata FROM $(table) WHERE id = ? LIMIT 1" : " SELECT label, code_date, identity, metadata FROM $(table) WHERE id = ? LIMIT 1" , (id_value,)) do result
799+ row_iter = iterate (result)
800+ row_iter === nothing && return nothing
801+ value = row_iter[1 ]
802+ code_date === nothing ?
803+ (label= String (value. label), identity= String (value. identity), metadata= String (value. metadata)) :
804+ (label= String (value. label), code_date= String (value. code_date), identity= String (value. identity), metadata= String (value. metadata))
797805 end
798- row_iter === nothing && error (" Failed to persist $(table) $(id_value) ." )
799- row = row_iter[1 ]
800- code_date === nothing || String (row. code_date) == code_date || error (" Conflicting code_date for id=$(id_value) in $(table) ." )
801- String (row. identity) == identity || error (" Conflicting identity for id=$(id_value) in $(table) ." )
806+ row === nothing && error (" Failed to persist $(table) $(id_value) ." )
807+ code_date === nothing || row. code_date == code_date || error (" Conflicting code_date for id=$(id_value) in $(table) ." )
808+ row. identity == identity || error (" Conflicting identity for id=$(id_value) in $(table) ." )
802809
803810 # Identity is immutable. Metadata is descriptive/extensible, so merge new values
804811 # into the stored object instead of making metadata part of entity identity.
805- merged_metadata = JSON. parse (String ( row. metadata) )
806- merge_metadata! (merged_metadata, JSON. parse (metadata))
812+ merged_metadata = JSON. parse (row. metadata; dicttype = Dict{String,Any} )
813+ merge_metadata! (merged_metadata, JSON. parse (metadata; dicttype = Dict{String,Any} ))
807814 merged_metadata_json = canonical_json (merged_metadata)
808- if String ( row. label) != label || String ( row. metadata) != merged_metadata_json
815+ if row. label != label || row. metadata != merged_metadata_json
809816 DBInterface. execute (db, " UPDATE $(table) SET label = ?, metadata = ? WHERE id = ?" , (label, merged_metadata_json, id_value))
810817 end
811818end
0 commit comments