edgarodriguez commited on
Commit
2f87354
·
verified ·
1 Parent(s): 67aea1e

Upload 2 files

Browse files
Files changed (2) hide show
  1. 10.11_draw_query_indicators_v10_HF.R +176 -73
  2. helpers.R +5 -0
10.11_draw_query_indicators_v10_HF.R CHANGED
@@ -1386,6 +1386,15 @@ server <- function(input, output, session) {
1386
  is_3d <- reactiveVal(FALSE)
1387
  is_grid_on <- reactiveVal(FALSE)
1388
 
 
 
 
 
 
 
 
 
 
1389
  rv <- reactiveValues(
1390
  n_incidents = "---", n_fatalities = "---",
1391
  n_graves = "---", n_facilities = "---",
@@ -1481,19 +1490,42 @@ server <- function(input, output, session) {
1481
  )
1482
  }
1483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1484
  # Central visibility updater
1485
  apply_visibility <- function(active, grid_on, crime_type, nivel, envipe_type, fosas_type = "fosas") {
1486
  prx <- maplibre_proxy("map")
1487
 
1488
  for (orig_lid in names(GRID_LAYER_CFG)) {
1489
  if (orig_lid == "fosas-choro" && !has_fosas_tbl) next
 
1490
  vis <- if (!grid_on && orig_lid %in% active) "visible" else "none"
1491
  prx <- prx |> set_layout_property(orig_lid, "visibility", vis)
1492
  }
1493
- prx <- prx |> set_layout_property(
1494
- "crime-border", "visibility",
1495
- if (!grid_on && "crime-choro" %in% active) "visible" else "none"
1496
- )
 
1497
 
1498
  # Sync crime fill color to selected type when grid is OFF
1499
  if (!grid_on && "crime-choro" %in% active) {
@@ -1504,7 +1536,7 @@ server <- function(input, output, session) {
1504
  }
1505
 
1506
  # Sync fosas fill color to selected sub-type when grid is OFF
1507
- if (has_fosas_tbl && !grid_on && "fosas-choro" %in% active) {
1508
  prx <- prx |> set_paint_property(
1509
  "fosas-choro", "fill-color",
1510
  fosas_step_expr(fosas_type)
@@ -1512,6 +1544,7 @@ server <- function(input, output, session) {
1512
  }
1513
 
1514
  for (lid in NON_GRID_LAYERS) {
 
1515
  prx <- prx |> set_layout_property(
1516
  lid, "visibility",
1517
  if (lid %in% active) "visible" else "none"
@@ -1527,9 +1560,15 @@ server <- function(input, output, session) {
1527
  )
1528
  }
1529
 
1530
- # Grid fill layers (opacity-based to avoid always-visible init bug)
1531
- niv_seq <- if (grid7_loaded()) WEB_SPEC$niveles else c("4", "5", "6")
1532
- for (niv in niv_seq) {
 
 
 
 
 
 
1533
  for (orig_lid in names(GRID_LAYER_CFG)) {
1534
  if (orig_lid == "fosas-choro" && !has_fosas_tbl) next
1535
  key <- GRID_LAYER_CFG[[orig_lid]]
@@ -1748,63 +1787,12 @@ server <- function(input, output, session) {
1748
  }, error = function(e) { message("grid_nivel", niv, ": ", e$message); NULL })
1749
  }
1750
 
1751
- # N7 (113k rows) is lazy-loaded; only N4-6 pre-loaded so the map renders fast.
1752
- RENDER_NIVELES <- c("4", "5", "6")
1753
- grid_sf_list <- setNames(
1754
- lapply(RENDER_NIVELES, \(n) load_grid_unified(as.integer(n))),
1755
- RENDER_NIVELES
1756
- )
1757
- grid4_sf <- grid_sf_list[["4"]]
1758
- grid5_sf <- grid_sf_list[["5"]]
1759
- grid6_sf <- grid_sf_list[["6"]]
1760
- # grid7_sf stays NULL until user first selects N7 (see lazy observer below)
1761
- desap_sf <- tryCatch({
1762
- DBI::dbGetQuery(con, web_sql("src_desap")) |>
1763
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1764
- dplyr::select(-wkt)
1765
- }, error = function(e) { message("desap: ", e$message); NULL })
1766
-
1767
- remesas_sf <- tryCatch({
1768
- DBI::dbGetQuery(con, web_sql("src_remesas")) |>
1769
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1770
- dplyr::select(-wkt)
1771
- }, error = function(e) { message("remesas: ", e$message); NULL })
1772
-
1773
- pam_sf <- tryCatch({
1774
- DBI::dbGetQuery(con, web_sql("src_pam")) |>
1775
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1776
- dplyr::select(-wkt)
1777
- }, error = function(e) { message("pam: ", e$message); NULL })
1778
-
1779
- fosas_sf <- tryCatch({
1780
- DBI::dbGetQuery(con, web_sql("src_fosas")) |>
1781
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1782
- dplyr::select(-wkt)
1783
- }, error = function(e) { message("dim_fosas_mun: ", e$message); NULL })
1784
-
1785
- state_sf <- tryCatch({
1786
- DBI::dbGetQuery(con, web_sql("src_state")) |>
1787
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1788
- dplyr::select(-wkt)
1789
- }, error = function(e) { message("state_polygons: ", e$message); NULL })
1790
-
1791
- routes_sf <- tryCatch({
1792
- DBI::dbGetQuery(con, web_sql("src_routes")) |>
1793
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1794
- dplyr::select(-wkt)
1795
- }, error = function(e) { message("routes: ", e$message); NULL })
1796
-
1797
- via_sf <- tryCatch({
1798
- DBI::dbGetQuery(con, web_sql("src_via")) |>
1799
- sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1800
- dplyr::select(-wkt)
1801
- }, error = function(e) { message("viaferrea: ", e$message); NULL })
1802
-
1803
- migrants_pts <- load_pts("migrants", 8000)
1804
- graves_pts <- load_pts("graves", 5000)
1805
- infra_pts <- load_pts("support_infrastructure", 5000)
1806
- ocved_pts <- load_pts("ocved_events", 80000)
1807
- ged_pts <- load_pts("ged_events", 80000)
1808
 
1809
  m <- maplibre(
1810
  style = carto_style("positron"),
@@ -1927,9 +1915,8 @@ server <- function(input, output, session) {
1927
  )
1928
  }
1929
 
1930
- # --- Grid layers: N4-6 pre-loaded; N7 added lazily by observer below -------
1931
- for (nv in RENDER_NIVELES)
1932
- m <- add_typed_grid_layers(m, grid_sf_list[[nv]], nv)
1933
 
1934
  # --- Line layers ------------------------------------------------------------
1935
  if (!is.null(routes_sf)) {
@@ -1999,14 +1986,129 @@ server <- function(input, output, session) {
1999
  }
2000
  }, ignoreNULL = TRUE, ignoreInit = TRUE)
2001
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2002
  observeEvent(input$clear_btn, {
2003
  clear_drawn_features(maplibre_proxy("map"))
2004
  load_national_totals()
2005
  })
2006
 
2007
- if (!is.null(con)) {
 
 
 
2008
  load_national_totals()
2009
- # Populate state filter at startup — avoids renderUI lifecycle issues
2010
  tbl_cols <- tryCatch(
2011
  DBI::dbGetQuery(con, "DESCRIBE state_polygons")$column_name,
2012
  error = function(e) character(0)
@@ -2022,7 +2124,7 @@ server <- function(input, output, session) {
2022
  )
2023
  updateSelectInput(session, "state_select",
2024
  choices = c("Choose a state..." = "", state_ch))
2025
- }
2026
 
2027
  observeEvent(input$grid_icon_click, {
2028
  new_on <- !is_grid_on()
@@ -2173,8 +2275,9 @@ server <- function(input, output, session) {
2173
  df <- rv$mun_df
2174
  if (is.null(df) || nrow(df) == 0)
2175
  return(div(class = "dp-empty", "Draw a polygon or click a municipality to filter."))
2176
- col_name <- CRIME_COLS[[input$crime_type]]$col
2177
- if (!col_name %in% names(df)) col_name <- "homicidio"
 
2178
  df_sorted <- df[order(df[[col_name]], decreasing = TRUE, na.last = TRUE), ]
2179
  top <- head(df_sorted, 5L)
2180
  mx <- max(top[[col_name]], na.rm = TRUE)
 
1386
  is_3d <- reactiveVal(FALSE)
1387
  is_grid_on <- reactiveVal(FALSE)
1388
 
1389
+ # Lazy-load flags: each flips to TRUE the first time the layer is added via proxy.
1390
+ lazy_added <- reactiveValues(
1391
+ desap = FALSE, remesas = FALSE, pam = FALSE, fosas = FALSE,
1392
+ state = FALSE, routes = FALSE, via = FALSE,
1393
+ migrants = FALSE, graves = FALSE, infra = FALSE,
1394
+ ocved = FALSE, ged = FALSE,
1395
+ grid4 = FALSE, grid5 = FALSE, grid6 = FALSE
1396
+ )
1397
+
1398
  rv <- reactiveValues(
1399
  n_incidents = "---", n_fatalities = "---",
1400
  n_graves = "---", n_facilities = "---",
 
1490
  )
1491
  }
1492
 
1493
+ # Returns TRUE if the layer has been added to the map (either at render time
1494
+ # or via a lazy proxy call). Prevents set_layout_property on absent layers.
1495
+ layer_ready <- function(id) {
1496
+ switch(id,
1497
+ "crime-choro" = TRUE, "crime-border" = TRUE,
1498
+ "desap-choro" = isTRUE(lazy_added$desap),
1499
+ "remesas-choro" = isTRUE(lazy_added$remesas),
1500
+ "pam-choro" = isTRUE(lazy_added$pam),
1501
+ "fosas-choro" = isTRUE(lazy_added$fosas),
1502
+ "envipe-state" = isTRUE(lazy_added$state),
1503
+ "routes-lines" = isTRUE(lazy_added$routes),
1504
+ "viaferrea-lines"= isTRUE(lazy_added$via),
1505
+ "migrants-pts" = isTRUE(lazy_added$migrants),
1506
+ "graves-pts" = isTRUE(lazy_added$graves),
1507
+ "infra-pts" = isTRUE(lazy_added$infra),
1508
+ "ocved-pts" = isTRUE(lazy_added$ocved),
1509
+ "ged-pts" = isTRUE(lazy_added$ged),
1510
+ grepl("^grid-", id)
1511
+ )
1512
+ }
1513
+
1514
  # Central visibility updater
1515
  apply_visibility <- function(active, grid_on, crime_type, nivel, envipe_type, fosas_type = "fosas") {
1516
  prx <- maplibre_proxy("map")
1517
 
1518
  for (orig_lid in names(GRID_LAYER_CFG)) {
1519
  if (orig_lid == "fosas-choro" && !has_fosas_tbl) next
1520
+ if (!layer_ready(orig_lid)) next
1521
  vis <- if (!grid_on && orig_lid %in% active) "visible" else "none"
1522
  prx <- prx |> set_layout_property(orig_lid, "visibility", vis)
1523
  }
1524
+ if (layer_ready("crime-border"))
1525
+ prx <- prx |> set_layout_property(
1526
+ "crime-border", "visibility",
1527
+ if (!grid_on && "crime-choro" %in% active) "visible" else "none"
1528
+ )
1529
 
1530
  # Sync crime fill color to selected type when grid is OFF
1531
  if (!grid_on && "crime-choro" %in% active) {
 
1536
  }
1537
 
1538
  # Sync fosas fill color to selected sub-type when grid is OFF
1539
+ if (has_fosas_tbl && !grid_on && "fosas-choro" %in% active && layer_ready("fosas-choro")) {
1540
  prx <- prx |> set_paint_property(
1541
  "fosas-choro", "fill-color",
1542
  fosas_step_expr(fosas_type)
 
1544
  }
1545
 
1546
  for (lid in NON_GRID_LAYERS) {
1547
+ if (!layer_ready(lid)) next
1548
  prx <- prx |> set_layout_property(
1549
  lid, "visibility",
1550
  if (lid %in% active) "visible" else "none"
 
1560
  )
1561
  }
1562
 
1563
+ # Grid fill layers (opacity-based to avoid always-visible init bug).
1564
+ # Skip niveles that haven't been lazy-loaded yet.
1565
+ loaded_niv <- c(
1566
+ if (isTRUE(lazy_added$grid4)) "4",
1567
+ if (isTRUE(lazy_added$grid5)) "5",
1568
+ if (isTRUE(lazy_added$grid6)) "6",
1569
+ if (grid7_loaded()) "7"
1570
+ )
1571
+ for (niv in loaded_niv) {
1572
  for (orig_lid in names(GRID_LAYER_CFG)) {
1573
  if (orig_lid == "fosas-choro" && !has_fosas_tbl) next
1574
  key <- GRID_LAYER_CFG[[orig_lid]]
 
1787
  }, error = function(e) { message("grid_nivel", niv, ": ", e$message); NULL })
1788
  }
1789
 
1790
+ # Only crime_sf is loaded at render time (the only visible-by-default layer).
1791
+ # All other layers load lazily the first time the user enables them.
1792
+ desap_sf <- NULL; remesas_sf <- NULL; pam_sf <- NULL
1793
+ fosas_sf <- NULL; state_sf <- NULL; routes_sf <- NULL; via_sf <- NULL
1794
+ migrants_pts <- NULL; graves_pts <- NULL; infra_pts <- NULL
1795
+ ocved_pts <- NULL; ged_pts <- NULL
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1796
 
1797
  m <- maplibre(
1798
  style = carto_style("positron"),
 
1915
  )
1916
  }
1917
 
1918
+ # Grid N4-6 load lazily on first user interaction (see lazy_add_grid observer).
1919
+ # Nothing added here at render time.
 
1920
 
1921
  # --- Line layers ------------------------------------------------------------
1922
  if (!is.null(routes_sf)) {
 
1986
  }
1987
  }, ignoreNULL = TRUE, ignoreInit = TRUE)
1988
 
1989
+ # Lazy layer loader helpers — load on first use via proxy.
1990
+ lazy_add_fill <- function(key, sql_name, id, make_layer_fn) {
1991
+ if (isTRUE(lazy_added[[key]]) || is.null(con)) return()
1992
+ sf_data <- tryCatch({
1993
+ DBI::dbGetQuery(con, web_sql(sql_name)) |>
1994
+ sf::st_as_sf(wkt = "wkt", crs = 4326) |>
1995
+ dplyr::select(-wkt)
1996
+ }, error = function(e) { message("lazy ", id, ": ", e$message); NULL })
1997
+ if (!is.null(sf_data)) {
1998
+ make_layer_fn(maplibre_proxy("map"), sf_data)
1999
+ lazy_added[[key]] <<- TRUE
2000
+ }
2001
+ }
2002
+ lazy_add_pts <- function(key, tbl, id, color, radius = 2, limit = 80000) {
2003
+ if (isTRUE(lazy_added[[key]]) || is.null(con)) return()
2004
+ pts <- load_pts(tbl, limit)
2005
+ if (!is.null(pts)) {
2006
+ maplibre_proxy("map") |>
2007
+ add_circle_layer(
2008
+ id = id, source = pts,
2009
+ circle_color = color, circle_radius = radius,
2010
+ circle_opacity = 0.75,
2011
+ circle_stroke_color = "rgba(0,0,0,0.4)",
2012
+ circle_stroke_width = 0.7,
2013
+ visibility = if (id %in% (input$active_layers %||% "")) "visible" else "none"
2014
+ )
2015
+ lazy_added[[key]] <<- TRUE
2016
+ }
2017
+ }
2018
+ lazy_add_grid <- function(nv_chr) {
2019
+ key <- paste0("grid", nv_chr)
2020
+ if (isTRUE(lazy_added[[key]]) || is.null(con)) return()
2021
+ sf_data <- tryCatch({
2022
+ DBI::dbGetQuery(con, web_sql_grid_unified(as.integer(nv_chr), has_fosas_tbl)) |>
2023
+ sf::st_as_sf(wkt = "wkt", crs = 4326) |>
2024
+ dplyr::select(-wkt)
2025
+ }, error = function(e) { message("lazy grid n", nv_chr, ": ", e$message); NULL })
2026
+ if (!is.null(sf_data)) {
2027
+ maplibre_proxy("map") |> add_typed_grid_layers(sf_data, nv_chr)
2028
+ lazy_added[[key]] <<- TRUE
2029
+ }
2030
+ }
2031
+
2032
+ # Observer fires when any layer toggle or grid state changes.
2033
+ # Loads each dataset the first time its layer becomes potentially visible.
2034
+ observeEvent(
2035
+ eventExpr = list(input$active_layers, is_grid_on(), input$grid_nivel),
2036
+ handlerExpr = {
2037
+ active <- input$active_layers %||% character(0)
2038
+ grid_on <- is_grid_on()
2039
+ nivel <- input$grid_nivel %||% "6"
2040
+
2041
+ # Choropleth / line layers (all hidden by default)
2042
+ if (!grid_on && "desap-choro" %in% active)
2043
+ lazy_add_fill("desap", "src_desap", "desap-choro", function(prx, d)
2044
+ prx |> add_fill_layer("desap-choro", source = d,
2045
+ fill_color = desap_qstep_expr(), fill_opacity = 0.6,
2046
+ tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
2047
+ "<br>Disappearances: ", list("to-string", list("get","desap_per_100k")), " /100k")))
2048
+ if (!grid_on && "remesas-choro" %in% active)
2049
+ lazy_add_fill("remesas", "src_remesas", "remesas-choro", function(prx, d)
2050
+ prx |> add_fill_layer("remesas-choro", source = d,
2051
+ fill_color = giim_match_expr(), fill_opacity = 0.75,
2052
+ tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
2053
+ "<br>Migration intensity: <b>", list("get","giim_mun"), "</b>")))
2054
+ if (!grid_on && "pam-choro" %in% active)
2055
+ lazy_add_fill("pam", "src_pam", "pam-choro", function(prx, d)
2056
+ prx |> add_fill_layer("pam-choro", source = d,
2057
+ fill_color = pam_qstep_expr(), fill_opacity = 0.7,
2058
+ tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
2059
+ "<br>Irregular migration events: ", list("to-string", list("get","pam_n")))))
2060
+ if (!grid_on && "fosas-choro" %in% active && has_fosas_tbl)
2061
+ lazy_add_fill("fosas", "src_fosas", "fosas-choro", function(prx, d)
2062
+ prx |> add_fill_layer("fosas-choro", source = d,
2063
+ fill_color = fosas_step_expr("fosas"), fill_opacity = 0.65,
2064
+ tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
2065
+ "<br>Burial pits: ", list("to-string", list("get","fosas_total")),
2066
+ "<br>Bodies: ", list("to-string", list("get","cuerpos_total")))))
2067
+ if ("envipe-state" %in% active)
2068
+ lazy_add_fill("state", "src_state", "envipe-state", function(prx, d)
2069
+ prx |> add_fill_layer("envipe-state", source = d,
2070
+ fill_color = step_expr("insecurity_perc", c(40,55,65,75,85), ENVIPE_PAL),
2071
+ fill_opacity = 0.6,
2072
+ tooltip = list("concat", "<b>", list("get","desc_entidad"), "</b>",
2073
+ "<br>Insecurity: ", list("to-string", list("get","insecurity_perc")), "%",
2074
+ "<br>Dark figures: ", list("to-string", list("get","dark_figures_perc")), "%")))
2075
+ if ("routes-lines" %in% active)
2076
+ lazy_add_fill("routes", "src_routes", "routes-lines", function(prx, d)
2077
+ prx |> add_line_layer("routes-lines", source = d,
2078
+ line_color = COL_AMBER,
2079
+ line_width = list("interpolate", list("linear"), list("zoom"), 5, 0.5, 10, 2.0),
2080
+ line_opacity = 0.1))
2081
+ if ("viaferrea-lines" %in% active)
2082
+ lazy_add_fill("via", "src_via", "viaferrea-lines", function(prx, d)
2083
+ prx |> add_line_layer("viaferrea-lines", source = d,
2084
+ line_color = "#990f0f", line_width = 1.5, line_opacity = 0.9,
2085
+ line_dasharray = c(4, 2)))
2086
+
2087
+ # Point layers
2088
+ if ("migrants-pts" %in% active) lazy_add_pts("migrants", "migrants", "migrants-pts", COL_YEL, 2, 8000)
2089
+ if ("graves-pts" %in% active) lazy_add_pts("graves", "graves", "graves-pts", COL_RED, 2, 5000)
2090
+ if ("infra-pts" %in% active) lazy_add_pts("infra", "support_infrastructure", "infra-pts", COL_GREEN, 2, 5000)
2091
+ if ("ocved-pts" %in% active) lazy_add_pts("ocved", "ocved_events", "ocved-pts", COL_AMBER, 1, 80000)
2092
+ if ("ged-pts" %in% active) lazy_add_pts("ged", "ged_events", "ged-pts", COL_LIGHT_BLUE, 1, 80000)
2093
+
2094
+ # Grid niveles N4-N6 load the first time the user enables grid mode
2095
+ if (grid_on) {
2096
+ for (nv in c("4", "5", "6")) lazy_add_grid(nv)
2097
+ }
2098
+ },
2099
+ ignoreNULL = TRUE, ignoreInit = TRUE
2100
+ )
2101
+
2102
  observeEvent(input$clear_btn, {
2103
  clear_drawn_features(maplibre_proxy("map"))
2104
  load_national_totals()
2105
  })
2106
 
2107
+ # Defer sidebar data queries to after the first UI flush so the map renders
2108
+ # immediately and the user sees the interface before numbers arrive.
2109
+ session$onFlushed(function() {
2110
+ if (is.null(con)) return()
2111
  load_national_totals()
 
2112
  tbl_cols <- tryCatch(
2113
  DBI::dbGetQuery(con, "DESCRIBE state_polygons")$column_name,
2114
  error = function(e) character(0)
 
2124
  )
2125
  updateSelectInput(session, "state_select",
2126
  choices = c("Choose a state..." = "", state_ch))
2127
+ }, once = TRUE)
2128
 
2129
  observeEvent(input$grid_icon_click, {
2130
  new_on <- !is_grid_on()
 
2275
  df <- rv$mun_df
2276
  if (is.null(df) || nrow(df) == 0)
2277
  return(div(class = "dp-empty", "Draw a polygon or click a municipality to filter."))
2278
+ col_name <- (CRIME_COLS[[input$crime_type %||% ""]] %||%
2279
+ CRIME_COLS[["Homicide rate"]])$col
2280
+ if (is.null(col_name) || !col_name %in% names(df)) col_name <- "homicidio"
2281
  df_sorted <- df[order(df[[col_name]], decreasing = TRUE, na.last = TRUE), ]
2282
  top <- head(df_sorted, 5L)
2283
  mx <- max(top[[col_name]], na.rm = TRUE)
helpers.R CHANGED
@@ -54,6 +54,11 @@ ddb_connect <- function(path = ":memory:", remote = FALSE, read_only = FALSE) {
54
  DBI::dbExecute(con, "LOAD httpfs")
55
  }
56
  )
 
 
 
 
 
57
  }
58
  con
59
  }
 
54
  DBI::dbExecute(con, "LOAD httpfs")
55
  }
56
  )
57
+ # Cache parquet footers and keep TCP connections alive across queries.
58
+ tryCatch({
59
+ DBI::dbExecute(con, "SET enable_http_metadata_cache = true")
60
+ DBI::dbExecute(con, "SET http_keep_alive = true")
61
+ }, error = function(e) invisible(NULL))
62
  }
63
  con
64
  }