Open abelloir-zz opened 2 months ago
@ThomasSoeiro proposait :
DBI::dbExecute(conn, glue::glue("INSERT INTO {output_table_name} {query}"), overwrite = overwrite)
et
DBI::dbExecute(conn, glue::glue("CREATE TABLE {output_table_name} AS {query}"), append = append)
Mais je ne crois pas que ces options overwrite et append existent dans dbExecute. Je propose de garder les deux fonctions wrapper
create_table_from_query
etinsert_into_table_from_query
même s'il ne s'agit que deux fois trois lignes de code : je trouve ça intéressant de garder la syntaxe SQL brut à part
Quelle nouille je suis, tu as raison ! (pour le reste je réponds quand j'y aurai réfléchi)
Une source d'inspiration : https://github.com/r-dbi/odbc/blob/455c937eb787cde8535b3ceac466e7b3c63f7efb/R/dbi-table.R#L33-L95
Je pencherais pour éviter de se trimballer plusieurs fonctions surtout si on utilise ce schéma d'écriture dans plusieurs extracteurs. Ça risque d'être assez lourd et de rendre la logique snds moins bien lisible.
Le lien envoyé par thomas a l'air pas trop mal comme inspiration il me semble.
J'ai l'impression qu'il nous faut les arguments overwrite
et append
et je ne suis pas sûr d'avoir en tête s'il faut qu'on garde leur argument temporary.
Je regarde à tête reposée cette fin de semaine pour proposer une implémentation condensée (sauf si vous pensez que c'est vraiment mieux de garder les deux fonctions séparées).
Une autre source d'inspiration qui m'a l'air plus simple à copier pour notre usage : https://github.com/duckdb/duckdb-r/blob/main/R/dbWriteTable__duckdb_connection_character_data.frame.R
Je n'ai pas de préférence pour utiliser ou non plusieurs fonctions pour la création ou complétion de tables SQL. Juste une remarque : pour la fonction create_or_insert_table_from_query
l'intérêt était d'avoir un comportement en interne qui détermine si on doit créer (CREATE TABLE) ou append (INSERT INTO) automatiquement. Rajouter un argument append n'a donc pas trop d'intérêt.
Mais Thomas a raison en fait c'est vrai que l'on peut remplacer (par exemple dans extract_drug_dispenses
) directement
create_table_or_insert_from_query(
conn = conn,
output_table_name =output_table_name,
query = query
)
par
if (DBI::dbExistsTable(conn, output_table_name)) {
DBI::dbExecute(
conn,
glue::glue("INSERT INTO {output_table_name} {query}")
)
} else {
DBI::dbExecute(
conn,
glue::glue("CREATE TABLE {output_table_name} AS {query}")
)
}
Puisque dans le code de cette fonction on a déjà géré en amont l'écrasage de la table existante si overwrite
est TRUE
(voir #34 ).
En fait on fait déjà de la syntaxe SQL dans les filtres et c'est mieux de d'exposer les commandes SQL de base là où elles sont utilisées pour quelqu'un qui voudrait un peu regarder comment le code fonctionne.
Il me semble que c'est plus clair d'avoir une seule fonction similaire à celle de duckdb ou de r-dbi, avec la signature suivante : write_table_from_query(con, output_table_name, query, overwrite = FALSE, append = FALSE)
. Cette fonction permet de gérer les différents cas où l'on veut écrire une table dans oracle à partir d'une query. Mais j'ai peut-être pas tous les cas en tête, n'hésitez pas à me dire si je loupe un truc.
Du coup le code suivant:
if (DBI::dbExistsTable(conn, output_table_name)) {
DBI::dbExecute(
conn,
glue::glue("INSERT INTO {output_table_name} {query}")
)
} else {
DBI::dbExecute(
conn,
glue::glue("CREATE TABLE {output_table_name} AS {query}")
)
}
Me semble plus clairement remplacé par :
write_table_from_query(con, output_table_name, query, append=TRUE)
En revanche, je ne suis pas sûr d'avoir compris ce passage : En fait on fait déjà de la syntaxe SQL dans les filtres et c'est mieux de d'exposer les commandes SQL de base là où elles sont utilisées pour quelqu'un qui voudrait un peu regarder comment le code fonctionne.
En vrai, c'est un peu du chipotage : le fond de ce qui me gêne est d'avoir une dizaine de lignes de codes qui ont trait à de la gestion de l'écriture des tables au lieu du métier sur l'extraction SNDS dans les fonctions d'extraction. Mais si ça vous pose pas de pb, on garde le if else avec les requêtes DBI sans les mettre dans un utilitaire :)
Je vote pour le if ... else ...
explicite car :
overwrite
ou append
.Ok :) Je changerai ça dans une petite PR sur https://github.com/strayMat/sndsTools/blob/main/R/extract_hospital_consultations.R
J'ai initialement créé la fonction wrapper
create_table_from_query
car je voulais pourvoir réaliser une étape du type :mais qui puisse marcher également pour mettre à jour une table donnée : par exemple créer une requête basée sur "MY_TABLE" à partir de laquelle on met à jour "MY_TABLE", ce qui implique créer une table temporaire, supprimer "MY_TABLE" et créer à nouveau "MY_TABLE" à partir de la table temporaire. D'où la création de la fonction suivante :
A la réflexion, ce cas particulier n'est pas souhaitable donc la fonction
create_table_from_query
peut être largement épurée : je la mets à jour dans #34Par ailleurs, le regroupement de CREATE TABLE et de INSERT INTO au sein d'une même fonction me parait finalement apporter plus de confusion que de concision. J'ai remplacé dans #34
create_table_or_insert_from_query
parcreate_table_from_query
et une nouvelle fonctioninsert_into_table_from_query
.Est ce que cela vous va si j'applique ce remplacement de
create_table_or_insert_from_query
parcreate_table_from_query
et la nouvelle fonctioninsert_into_table_from_query
pour l'ensemble des fonctions d'extraction concernées ?@ThomasSoeiro proposait :
et
Mais je ne crois pas que ces options overwrite et append existent dans dbExecute. Je propose de garder les deux fonctions wrapper
create_table_from_query
etinsert_into_table_from_query
même s'il ne s'agit que deux fois trois lignes de code : je trouve ça intéressant de garder la syntaxe SQL brut à partQu'est ce que vous en pensez ?