From 7a5a23420acc2fc8ebff59b4c6a821690f22cbb9 Mon Sep 17 00:00:00 2001 From: tomwilsonsco Date: Fri, 13 Sep 2024 09:42:35 +0100 Subject: [PATCH] line continuation reformat glue strings --- R/create_replace_table.R | 97 ++++++++---------- R/db_table_metadata.R | 41 ++++---- R/drop_table.R | 22 ++-- R/read_table.R | 13 +-- R/show_schema_tables.R | 22 ++-- R/utils.R | 19 ++-- tests/testthat/test-create_replace_table.R | 14 +-- tests/testthat/test-db_table_metadata.R | 13 ++- tests/testthat/test-drop_table.R | 12 +-- tests/testthat/test-read_table.R | 10 +- tests/testthat/test-show_schema_tables.R | 20 ++-- .../testdata/test_columns_info_sql.rds | Bin 314 -> 300 bytes 12 files changed, 132 insertions(+), 151 deletions(-) diff --git a/R/create_replace_table.R b/R/create_replace_table.R index 75cbf4c..911941a 100644 --- a/R/create_replace_table.R +++ b/R/create_replace_table.R @@ -138,10 +138,9 @@ check_existing_table <- function(db_params, resize_datatypes(compare_col_df, db_params) message(glue::glue( - "Checked existing columns in ", - "{db_params$schema}.{db_params$table_name}", - "are compatible with those in the dataframe to be loaded.", - .sep = " " + "Checked existing columns in \\ + {db_params$schema}.{db_params$table_name} \\ + are compatible with those in the dataframe to be loaded." )) } @@ -149,9 +148,9 @@ check_existing_table <- function(db_params, alter_sql_character_col <- function(db_params, column_name, new_char_type) { - sql <- glue::glue_sql("ALTER TABLE ", - "{`quoted_schema_tbl(db_params$schema, db_params$table_name)`} ", - "ALTER COLUMN {`column_name`} {DBI::SQL(new_char_type)};", + sql <- glue::glue_sql("ALTER TABLE \\ + {`quoted_schema_tbl(db_params$schema, db_params$table_name)`} \\ + ALTER COLUMN {`column_name`} {DBI::SQL(new_char_type)};", .con = DBI::ANSI() ) @@ -162,9 +161,9 @@ alter_sql_character_col <- function(db_params, FALSE ) message(glue::glue( - "Resizing column {column_name}", - "to {new_char_type}." - ), .sep = " ") + "Resizing column {column_name} \\ + to {new_char_type}." + )) } id_col_name <- function(table_name) { @@ -177,9 +176,9 @@ sql_create_table <- function(schema, table_name, metadata_df) { metadata_df$column_name != paste0(table_name, "ID"), ] - initial_sql <- glue::glue_sql("CREATE TABLE ", - "{`quoted_schema_tbl(schema, table_name)`} (", - "{`id_col_name(table_name)`} INT NOT NULL IDENTITY PRIMARY KEY,", + initial_sql <- glue::glue_sql("CREATE TABLE \\ + {`quoted_schema_tbl(schema, table_name)`} (\\ + {`id_col_name(table_name)`} INT NOT NULL IDENTITY PRIMARY KEY,", .con = DBI::ANSI() ) @@ -203,11 +202,11 @@ sql_versioned_table <- function(sql, db_params) { ) # The versioned table sql glue::glue_sql(sql, - " \"SysStartTime\" DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL, ", - "\"SysEndTime\" DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL, ", - "PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)) ", - "WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = ", - "{`history_table`}));", + " \"SysStartTime\" DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL, \\ + \"SysEndTime\" DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL, \\ + PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)) \\ + WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = \\ + {`history_table`}));", .con = DBI::ANSI() ) } @@ -245,9 +244,8 @@ create_staging_table <- function(db_params, dataframe) { FALSE ) message(glue::glue( - "Table: {db_params$schema}.{staging_name}", - "successfully created in database.", - .sep = " " + "Table: {db_params$schema}.{staging_name} \\ + successfully created in database." )) } @@ -276,9 +274,8 @@ populate_staging_table <- function(db_params, ) batch_list <- get_df_batches(dataframe = dataframe, batch_size = batch_size) message(glue::glue( - "Loading to staging in {length(batch_list$batch_starts)}", - "batches of up to {format(batch_size, scientific = FALSE)} rows...", - .sep = " " + "Loading to staging in {length(batch_list$batch_starts)} \\ + batches of up to {format(batch_size, scientific = FALSE)} rows..." )) for (i in seq_along(batch_list$batch_starts)) { batch_start <- batch_list$batch_starts[[i]] @@ -296,17 +293,15 @@ populate_staging_table <- function(db_params, }, error = function(cond) { stop(glue::glue( - "Failed to write staging", - "data to database.\n", cond, - .sep = " " + "Failed to write staging \\ + data to database.\n", cond ), call. = FALSE) } ) message(glue::glue( - "Loaded rows {format(batch_start, scientific = FALSE)}", - "- {format(batch_end, scientific = FALSE)} of", - "{tail(batch_list$batch_ends, 1)}", - .sep = " " + "Loaded rows {format(batch_start, scientific = FALSE)} \\ + - {format(batch_end, scientific = FALSE)} of \\ + {tail(batch_list$batch_ends, 1)}" )) } DBI::dbDisconnect(connection) @@ -317,10 +312,10 @@ create_insert_sql <- function(db_params, metadata_df) { paste0(db_params$table_name, "ID"), ] glue::glue_sql( - "INSERT INTO ", - "{`quoted_schema_tbl(db_params$schema, db_params$table_name)`} ", - "({`metadata_df$column_name`*}) select {`metadata_df$column_name`*} from ", - "{`quoted_schema_tbl(db_params$schema, + "INSERT INTO \\ + {`quoted_schema_tbl(db_params$schema, db_params$table_name)`} \\ + ({`metadata_df$column_name`*}) select {`metadata_df$column_name`*} from \\ + {`quoted_schema_tbl(db_params$schema, paste0(db_params$table_name,'_staging_'))`};", .con = DBI::ANSI() ) @@ -338,9 +333,8 @@ populate_table_from_staging <- function(db_params) { execute_sql(db_params$server, db_params$database, sql, FALSE) message(glue::glue( - "Table: {db_params$schema}.{db_params$table_name}", - "successfully populated from staging", - .sep = " " + "Table: {db_params$schema}.{db_params$table_name} \\ + successfully populated from staging" )) } @@ -357,9 +351,8 @@ delete_staging_table <- function(db_params, silent = FALSE) { ) if (!silent) { message(glue::glue( - "Staging table: {db_params$schema}.{db_params$table_name}_staging_", - "successfully deleted from database.", - .sep = " " + "Staging table: {db_params$schema}.{db_params$table_name}_staging_ \\ + successfully deleted from database." )) } } @@ -390,9 +383,8 @@ create_table <- function(db_params, silent = FALSE) { ) if (!silent) { message(glue::glue( - "Table: {db_params$schema}.{db_params$table_name}", - "successfully created in database", - .sep = " " + "Table: {db_params$schema}.{db_params$table_name} \\ + successfully created in database" )) } } @@ -407,10 +399,9 @@ clean_table_name <- function(table_name) { # Advise if changing target table name if (new_name != table_name) { warning(glue::glue( - "Cannot name a table {table_name}", - "replacing with name {new_name}", - "(see ODBC table name limitations)", - .sep = " " + "Cannot name a table {table_name} \\ + replacing with name {new_name} \\ + (see ODBC table name limitations)" )) } return(new_name) @@ -553,9 +544,8 @@ write_dataframe_to_db <- function(server, # If not appending and exists then inform that will be overwritten } else { warning(glue::glue( - "Database table: {schema}.{table_name} already exists", - "attempting to drop and replace it...", - .sep = " " + "Database table: {schema}.{table_name} already exists \\ + attempting to drop and replace it..." ), call. = FALSE) # Drop the existing table drop_table_from_db( @@ -587,8 +577,7 @@ write_dataframe_to_db <- function(server, } end_time <- Sys.time() message(glue::glue( - "Loading completed in", - "{round(difftime(end_time, start_time,units = 'mins')[[1]], 2)} minutes.", - .sep = " " + "Loading completed in \\ + {round(difftime(end_time, start_time,units = 'mins')[[1]], 2)} minutes." )) } diff --git a/R/db_table_metadata.R b/R/db_table_metadata.R index ceb4e74..75c1cbe 100644 --- a/R/db_table_metadata.R +++ b/R/db_table_metadata.R @@ -1,10 +1,10 @@ # basic column name, datatype and length query col_query <- function(database, schema, table_name) { glue::glue_sql(" - SELECT column_name, data_type, CHARACTER_MAXIMUM_LENGTH - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_CATALOG = {database} - AND TABLE_SCHEMA = {schema} + SELECT column_name, data_type, CHARACTER_MAXIMUM_LENGTH \\ + FROM INFORMATION_SCHEMA.COLUMNS \\ + WHERE TABLE_CATALOG = {database} \\ + AND TABLE_SCHEMA = {schema} \\ AND TABLE_NAME = {table_name}", .con = DBI::ANSI()) } @@ -12,9 +12,9 @@ col_query <- function(database, schema, table_name) { update_col_query <- function(columns_info) { # To add the length of nvarchar column so appears as e.g. nvarchar(50) update_char <- glue::glue( - "{columns_info[! is.na(columns_info$CHARACTER_MAXIMUM_LENGTH), 2]}", - "({as.character(columns_info", - "[! is.na(columns_info$CHARACTER_MAXIMUM_LENGTH), 3])})" + "{columns_info[! is.na(columns_info$CHARACTER_MAXIMUM_LENGTH), 2]}\\ + ({as.character(columns_info\\ + [! is.na(columns_info$CHARACTER_MAXIMUM_LENGTH), 3])})" ) columns_info$data_type[!is.na(columns_info$CHARACTER_MAXIMUM_LENGTH)] <- @@ -32,12 +32,12 @@ get_table_stats <- function(i, columns_info, schema, table_name) { # Generate the min/max query based on the data type min_max_query <- if (data_type != "bit") { - glue::glue_sql("(SELECT MIN(CAST({`col`} AS NVARCHAR(225))) - FROM {`schema`}.{`table_name`} - WHERE {col} IS NOT NULL) AS minimum_value, - (SELECT MAX(CAST({`col`} AS NVARCHAR(225))) - FROM {`schema`}.{`table_name`} - WHERE {col} IS NOT NULL) AS maximum_value", + glue::glue_sql("(SELECT MIN(CAST({`col`} AS NVARCHAR(225))) \\ + FROM {`schema`}.{`table_name`} \\ + WHERE {col} IS NOT NULL) AS minimum_value, \\ + (SELECT MAX(CAST({`col`} AS NVARCHAR(225))) \\ + FROM {`schema`}.{`table_name`} \\ + WHERE {col} IS NOT NULL) AS maximum_value", .con = DBI::ANSI() ) } else { @@ -45,14 +45,13 @@ get_table_stats <- function(i, columns_info, schema, table_name) { } # Building the full SQL query - glue::glue_sql(" - SELECT {col} AS column_name, {data_type} AS data_type, - (SELECT COUNT(*) FROM {`schema`}.{`table_name`}) AS row_count, - (SELECT COUNT(*) FROM {`schema`}.{`table_name`} WHERE {col} IS NULL) - AS null_count, - (SELECT COUNT(DISTINCT {`col`}) FROM {`schema`}.{`table_name`} - WHERE {col} IS NOT NULL) AS distinct_values, - {min_max_query}", + glue::glue_sql( +"SELECT {col} AS column_name, {data_type} AS data_type, \\ +(SELECT COUNT(*) FROM {`schema`}.{`table_name`}) AS row_count, \\ +(SELECT COUNT(*) FROM {`schema`}.{`table_name`} WHERE {col} IS NULL) \\ +AS null_count, \\ +(SELECT COUNT(DISTINCT {`col`}) FROM {`schema`}.{`table_name`} \\ +WHERE {col} IS NOT NULL) AS distinct_values, {min_max_query}", .con = DBI::ANSI() ) } diff --git a/R/drop_table.R b/R/drop_table.R index ea2f048..419da7a 100644 --- a/R/drop_table.R +++ b/R/drop_table.R @@ -1,10 +1,10 @@ # create versioned table sql create_drop_sql_versioned <- function(schema, table_name) { history_table <- quoted_schema_tbl(schema, glue::glue(table_name, "History")) - glue::glue_sql("ALTER TABLE {`quoted_schema_tbl(schema, table_name)`} ", - "SET ( SYSTEM_VERSIONING = OFF );", - "DROP TABLE {`quoted_schema_tbl(schema, table_name)`};", - "DROP TABLE {`history_table`};", + glue::glue_sql("ALTER TABLE {`quoted_schema_tbl(schema, table_name)`} \\ + SET ( SYSTEM_VERSIONING = OFF ); \\ + DROP TABLE {`quoted_schema_tbl(schema, table_name)`}; \\ + DROP TABLE {`history_table`};", .con = DBI::ANSI() ) } @@ -104,10 +104,10 @@ drop_table_from_db <- function(server, error = function(cond) { if (drop_sql$versioned) { cond$message <- glue::glue( - "{cond$message}\n\n", - "{schema}.{table_name} is a VERSIONED TABLE.\n\n", - "Contact a system admin to request that they drop this versioned ", - "table for you as you do not have sufficient permissions.", + "{cond$message}\n\n \\ + {schema}.{table_name} is a VERSIONED TABLE.\n\n \\ + Contact a system admin to request that they drop this versioned \\ + table for you as you do not have sufficient permissions.", ) } else { cond$message <- glue::glue("Error dropping table: {cond}") @@ -119,9 +119,7 @@ drop_table_from_db <- function(server, # Output message if required if (!silent) { - message(glue::glue("Table: {schema}.{table_name}", - "successfully deleted.", - .sep = " " - )) + message(glue::glue("Table: {schema}.{table_name} \\ + successfully deleted.")) } } diff --git a/R/read_table.R b/R/read_table.R index d4ed1b6..8663585 100644 --- a/R/read_table.R +++ b/R/read_table.R @@ -42,8 +42,8 @@ table_select_list <- function(server, # Cast datetime2 columns to datetime- workaround due to old ODBC client drivers col_select <- function(column_name, datetime2_cols_to_cast) { if (column_name %in% datetime2_cols_to_cast) { - return(glue::glue_sql("CAST({`column_name`} AS datetime) ", - "AS {`column_name`}", + return(glue::glue_sql("CAST({`column_name`} AS datetime) \\ + AS {`column_name`}", .con = DBI::ANSI() )) } else { @@ -86,13 +86,10 @@ create_read_sql <- function(schema, ) if (!is.null(filter_stmt)) { filter_stmt <- format_filter(filter_stmt) - glue::glue( - initial_sql, - "WHERE {filter_stmt};", - .sep = " " - ) + glue::glue_sql(glue::glue(initial_sql, " WHERE {filter_stmt};"), + .con = DBI::ANSI()) } else { - glue::glue(initial_sql, ";") + glue::glue_sql(glue::glue(initial_sql, ";"), .con = DBI::ANSI()) } } diff --git a/R/show_schema_tables.R b/R/show_schema_tables.R index bf2cde8..a4b115f 100644 --- a/R/show_schema_tables.R +++ b/R/show_schema_tables.R @@ -1,18 +1,18 @@ table_sql <- function(schema) { - glue::glue_sql("SELECT name AS 'table', - create_date AS 'creation_date' - FROM sys.tables - WHERE SCHEMA_NAME(schema_id) = {schema} - order by 2", .con = DBI::ANSI()) + glue::glue_sql("SELECT name AS 'table', \\ + create_date AS 'creation_date' \\ + FROM sys.tables \\ + WHERE SCHEMA_NAME(schema_id) = {schema} \\ + order by 2", .con = DBI::ANSI()) } table_view_sql <- function(schema) { - glue::glue_sql("SELECT name AS 'table', - type_desc AS 'object_type', - create_date AS 'creation_date' - FROM sys.objects - WHERE type IN ('U', 'V') -- 'U'ser tables, 'V'iews - AND SCHEMA_NAME(schema_id) = {schema} + glue::glue_sql("SELECT name AS 'table', \\ + type_desc AS 'object_type', \\ + create_date AS 'creation_date' \\ + FROM sys.objects \\ + WHERE type IN ('U', 'V') -- 'U'ser tables, 'V'iews \\ + AND SCHEMA_NAME(schema_id) = {schema} \\ order by type, name", .con = DBI::ANSI()) } diff --git a/R/utils.R b/R/utils.R index 72364fb..a5fb8a6 100644 --- a/R/utils.R +++ b/R/utils.R @@ -12,10 +12,9 @@ create_sqlserver_connection <- function(server, database, timeout = 10) { }, error = function(cond) { stop(glue::glue( - "Failed to create connection to database:", - "{database} on server: {server}", - "\n{cond}", - .sep = " " + "Failed to create connection to database: \\ + {database} on server: {server} \\ + \n{cond}" ), call. = FALSE) } ) @@ -135,12 +134,12 @@ get_pk_name <- function(server, schema, table_name) { sql <- glue::glue_sql( - "select C.COLUMN_NAME FROM - INFORMATION_SCHEMA.TABLE_CONSTRAINTS T - JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE C - ON C.CONSTRAINT_NAME = T.CONSTRAINT_NAME - WHERE C.TABLE_NAME = {table_name} - AND T.CONSTRAINT_SCHEMA = {schema} + "select C.COLUMN_NAME FROM \\ + INFORMATION_SCHEMA.TABLE_CONSTRAINTS T \\ + JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE C \\ + ON C.CONSTRAINT_NAME = T.CONSTRAINT_NAME \\ + WHERE C.TABLE_NAME = {table_name} \\ + AND T.CONSTRAINT_SCHEMA = {schema} \\ AND T.CONSTRAINT_TYPE = 'PRIMARY KEY';", .con = DBI::ANSI() ) diff --git a/tests/testthat/test-create_replace_table.R b/tests/testthat/test-create_replace_table.R index e9377a5..d86c8b6 100644 --- a/tests/testthat/test-create_replace_table.R +++ b/tests/testthat/test-create_replace_table.R @@ -18,13 +18,13 @@ test_that("cleaning column names works", { test_that("create table sql correct", { correct_sql <- glue::glue_sql( - "CREATE TABLE \"test\".\"test_tbl\" ", - "(\"test_tblID\" INT NOT NULL IDENTITY PRIMARY KEY,", - "\"Sepal.Length\" float, ", - "\"Sepal.Width\" float, ", - "\"Petal.Length\" float, ", - "\"Petal.Width\" float, ", - "\"Species\" nvarchar(50));" + "CREATE TABLE \"test\".\"test_tbl\" \\ + (\"test_tblID\" INT NOT NULL IDENTITY PRIMARY KEY,\\ + \"Sepal.Length\" float, \\ + \"Sepal.Width\" float, \\ + \"Petal.Length\" float, \\ + \"Petal.Width\" float, \\ + \"Species\" nvarchar(50));" ) metadata_df <- df_to_metadata(iris) expect_equal( diff --git a/tests/testthat/test-db_table_metadata.R b/tests/testthat/test-db_table_metadata.R index 8e0c407..f8f1ab9 100644 --- a/tests/testthat/test-db_table_metadata.R +++ b/tests/testthat/test-db_table_metadata.R @@ -1,11 +1,10 @@ test_that("basic sql created correctly", { - check_sql <- glue::glue_sql( - "SELECT column_name, data_type, CHARACTER_MAXIMUM_LENGTH - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_CATALOG = 'test_db' - AND TABLE_SCHEMA = 'test_schema' - AND TABLE_NAME = 'test_tbl'" - ) + check_sql <- glue::glue_sql(" + SELECT column_name, data_type, CHARACTER_MAXIMUM_LENGTH \\ + FROM INFORMATION_SCHEMA.COLUMNS \\ + WHERE TABLE_CATALOG = 'test_db' \\ + AND TABLE_SCHEMA = 'test_schema' \\ + AND TABLE_NAME = 'test_tbl'") expect_equal( col_query("test_db", "test_schema", "test_tbl"), diff --git a/tests/testthat/test-drop_table.R b/tests/testthat/test-drop_table.R index 07641ff..60f13d1 100644 --- a/tests/testthat/test-drop_table.R +++ b/tests/testthat/test-drop_table.R @@ -5,12 +5,12 @@ test_that("table not exist error works", { test_that("versioned drop sql created correctly", { - drop_ver_sql <- DBI::SQL(paste0( - "ALTER TABLE \"test_schema\".\"test_tbl\" ", - "SET ( SYSTEM_VERSIONING = OFF );", - "DROP TABLE \"test_schema\".\"test_tbl\";", - "DROP TABLE \"test_schema\".\"test_tblHistory\";" - )) + drop_ver_sql <- glue::glue_sql( + "ALTER TABLE \"test_schema\".\"test_tbl\" \\ + SET ( SYSTEM_VERSIONING = OFF ); \\ + DROP TABLE \"test_schema\".\"test_tbl\"; \\ + DROP TABLE \"test_schema\".\"test_tblHistory\";" + ) mockery::stub(create_drop_sql, "is_versioned", TRUE) diff --git a/tests/testthat/test-read_table.R b/tests/testthat/test-read_table.R index 0c6f3e9..afdbdf2 100644 --- a/tests/testthat/test-read_table.R +++ b/tests/testthat/test-read_table.R @@ -1,7 +1,7 @@ test_that("select sql works", { - test_sql <- paste0( - "SELECT \"col_a\", \"col_b\" FROM \"test_schema\".\"test_tbl\"", - " WHERE \"col_a\" = 'test1' AND \"col_b\" = 'test2';" + test_sql <- glue::glue_sql( + "SELECT \"col_a\", \"col_b\" FROM \"test_schema\".\"test_tbl\" \\ + WHERE \"col_a\" = 'test1' AND \"col_b\" = 'test2';" ) select_list <- c("col_a", "col_b") @@ -14,12 +14,12 @@ test_that("select sql works", { test_read_md <- readRDS(test_path("testdata", "test_read_md.rds")) - expect_equal(as.character(create_read_sql( + expect_equal(create_read_sql( schema = "test_schema", select_list = select_list, table_name = "test_tbl", table_metadata = test_read_md, filter_stmt = "col_a == 'test1' & col_b == 'test2'", cast_datetime2 = TRUE - )), test_sql) + ), test_sql) }) diff --git a/tests/testthat/test-show_schema_tables.R b/tests/testthat/test-show_schema_tables.R index 0c6c31f..4a4b640 100644 --- a/tests/testthat/test-show_schema_tables.R +++ b/tests/testthat/test-show_schema_tables.R @@ -1,8 +1,8 @@ test_that("table sql created correctly", { - sql <- glue::glue_sql("SELECT name AS 'table', - create_date AS 'creation_date' - FROM sys.tables - WHERE SCHEMA_NAME(schema_id) = 'test_schema' + sql <- glue::glue_sql("SELECT name AS 'table', \\ + create_date AS 'creation_date' \\ + FROM sys.tables \\ + WHERE SCHEMA_NAME(schema_id) = 'test_schema' \\ order by 2") @@ -11,12 +11,12 @@ test_that("table sql created correctly", { test_that("table and view sql created correctly", { - sql <- glue::glue_sql("SELECT name AS 'table', - type_desc AS 'object_type', - create_date AS 'creation_date' - FROM sys.objects - WHERE type IN ('U', 'V') -- 'U'ser tables, 'V'iews - AND SCHEMA_NAME(schema_id) = 'test_schema' + sql <- glue::glue_sql("SELECT name AS 'table', \\ + type_desc AS 'object_type', \\ + create_date AS 'creation_date' \\ + FROM sys.objects \\ + WHERE type IN ('U', 'V') -- 'U'ser tables, 'V'iews \\ + AND SCHEMA_NAME(schema_id) = 'test_schema' \\ order by type, name") diff --git a/tests/testthat/testdata/test_columns_info_sql.rds b/tests/testthat/testdata/test_columns_info_sql.rds index 672d9193d1c098f5ff2e0d7a3d2625e03107c1c4..60b411bad45701a30005549c1c4dbf59d6480547 100644 GIT binary patch literal 300 zcmV+{0n`2;iwFP!000002ECHOPlGTR#lOLb(UX5d(+gnK!x9s(2rMIE5TWR9q+vuG zp)6}r_s<&(8exkUjq%X5--A3)KPtuLEh*)PfnkVrR;a*1+ zk7Z5qCH_*yc8719m%M0NE`N-p`-PwQ2Qh;bMOhg3(!8yz@3p-kB|)S{Jc9AB4P!Ex zu9=XG7czgQRa=U|c^O2O>!ifm^X!o5&Pm*blUTFam2Lk?ikfj&xAjMeQ3hxAj~VFe ykO5TdhK_+zR8$C6wo&mwPjAD6e@7cyJkbY*!`@HtCQ#Q~cisUFB^#>M0ssIE#fypn literal 314 zcmV-A0mc3wiwFP!000002ECGBPlGTN#qVIm$dezT;RP_$hb1PyBCw2vLFA9}Mj9mA z2xVD|x-V}m%m`at7GHd5+S}Z7&achQQ~;1+DoG$K;s{EbEUs>0B43DN0#i5#kh0kI zT{}TKFB#9thA_|3krkt&soI+66xZbp>4ftB_6c*G^XiecDtZ7?Szk54goOppKwUJmm z6{sEy43k}G{~d&JLJOY1;i@g!ki7B&!?xnY*vsrB!GjgqODi(w^BdDN)l(QpA3o-& z2_