Skip to content

Commit 0d36c15

Browse files
fix: load paths, imports, transpile, and CI permissions
Quote/escape datadirs and passwords in loaders, accept plain CSV in duckdb/sqlite imports, utf-8 transpile writes, and don't fail sqlfluff annotate on fork PRs. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 3a914fc commit 0d36c15

24 files changed

Lines changed: 284 additions & 131 deletions

File tree

.github/workflows/lint_sqlfluff.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ jobs:
3535
shell: bash
3636
run: sqlfluff lint --format github-annotation --annotation-level failure --nofail ${{ steps.get_files_to_lint.outputs.lintees }} > annotations.json
3737
- name: Annotate
38+
# Fork PRs cannot create check runs with GITHUB_TOKEN; lint already ran.
39+
continue-on-error: true
40+
if: steps.get_files_to_lint.outputs.lintees != ''
3841
uses: yuzutech/annotations-action@v0.6.0
3942
with:
4043
repo-token: "${{ secrets.GITHUB_TOKEN }}"
4144
title: "SQLFluff Lint"
42-
input: "./annotations.json"
45+
input: "./annotations.json"
46+
ignore-missing-file: true

mimic-iii/buildmimic/duckdb/import_duckdb.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ usage () {
2929
die "
3030
USAGE: ./import_duckdb.sh mimic_data_dir [output_db]
3131
WHERE:
32-
mimic_data_dir directory that contains csv.gz or csv files
32+
mimic_data_dir directory that contains csv.tar.gz or csv files
3333
output_db: optional filename for duckdb file (default: mimic3.db)\
3434
"
3535
}
@@ -85,9 +85,11 @@ make_table_name () {
8585
# load data into database
8686
find "$MIMIC_DIR" -type f -regex '.*\.csv\(.gz\)*' | while IFS= read -r FILE; do
8787
make_table_name "$FILE"
88-
echo "Loading $FILE .. \c"
88+
# Escape single quotes for SQL string literal
89+
FILE_SQL=$(printf '%s' "$FILE" | sed "s/'/''/g")
90+
printf "Loading %s .. " "$FILE"
8991
try duckdb "$OUTFILE" <<-EOSQL
90-
COPY $TABLE_NAME FROM '$FILE' (HEADER, DELIM ',', QUOTE '"', ESCAPE '"');
92+
COPY $TABLE_NAME FROM '$FILE_SQL' (HEADER, DELIM ',', QUOTE '"', ESCAPE '"');
9193
EOSQL
9294
echo "done!"
9395
done && echo "Successfully finished loading data into $OUTFILE."

mimic-iii/buildmimic/postgres/Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ mimic-build-gz:
104104
@echo '------------------'
105105
@echo ''
106106
@sleep 2
107-
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data_gz.sql -v mimic_data_dir=${datadir}
107+
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data_gz.sql -v "mimic_data_dir=$(DATADIR)"
108108
@echo ''
109109
@echo '--------------------'
110110
@echo '-- Adding indexes --'
@@ -151,7 +151,7 @@ mimic-build:
151151
@echo '------------------'
152152
@echo ''
153153
@sleep 2
154-
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data.sql -v mimic_data_dir=${DATADIR}
154+
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data.sql -v "mimic_data_dir=$(DATADIR)"
155155
@echo ''
156156
@echo '--------------------'
157157
@echo '-- Adding indexes --'
@@ -184,15 +184,15 @@ ifeq ("$(physionetuser)","")
184184
@echo 'Call the makefile again with physionetuser=<USERNAME>'
185185
@echo ' e.g. make eicu-download datadir=/path/to/data physionetuser=hello@physionet.org'
186186
else
187-
wget --user $(physionetuser) --ask-password -P $(DATADIR) -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETURL)"
187+
wget --user $(physionetuser) --ask-password -P "$(DATADIR)" -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETURL)"
188188
endif
189189

190190
mimic-demo-download:
191191
@echo '------------------------------------------'
192192
@echo '-- Downloading MIMIC-III from PhysioNet --'
193193
@echo '------------------------------------------'
194194
@echo ''
195-
wget --user $(physionetuser) --ask-password -P $(DATADIR) -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETDEMOURL)"
195+
wget --user $(physionetuser) --ask-password -P "$(DATADIR)" -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETDEMOURL)"
196196

197197
#This is fairly inelegant and could be tidied with a for loop and an if to check for gzip,
198198
#but need to maintain compatibility with Windows, which baffling lacks these things
@@ -281,7 +281,7 @@ concepts:
281281
@echo '---------------------'
282282
@echo ''
283283
@sleep 2
284-
cd ../../concepts_postgres/ && psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -c "CREATE SCHEMA IF NOT EXISTS mimiciii_derived;" -f postgres-make-concepts.sql
284+
cd ../../concepts/ && psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f make-concepts.sql
285285

286286

287287
.PHONY: help mimic clean

mimic-iii/buildmimic/postgres/create_mimic_user.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ else
2020
echo "User is set to '$MIMIC_USER'";
2121
fi
2222

23+
# escape ' in password for SQL string literal
24+
MIMIC_PASSWORD_SQL=$(printf '%s' "$MIMIC_PASSWORD" | sed "s/'/''/g")
25+
# quote SQL identifiers (double any embedded ")
26+
sql_ident () { printf '%s' "$1" | sed 's/"/""/g; s/^/"/; s/$/"/'; }
27+
MIMIC_USER_SQL=$(sql_ident "$MIMIC_USER")
28+
MIMIC_DB_SQL=$(sql_ident "$MIMIC_DB")
29+
2330
PSQL='psql'
2431

2532
# add in the host/port, if they were specified (not null, -n)
@@ -58,11 +65,11 @@ fi
5865
if [ "$MIMIC_USER" != "postgres" ]; then
5966
# we need to create this user via postgres
6067
# use SUDO to login as postgres
61-
$PSQL -U postgres -d postgres -c "DROP USER IF EXISTS $MIMIC_USER; CREATE USER $MIMIC_USER WITH PASSWORD '$MIMIC_PASSWORD';"
68+
$PSQL -U postgres -d postgres -c "DROP USER IF EXISTS $MIMIC_USER_SQL; CREATE USER $MIMIC_USER_SQL WITH PASSWORD '$MIMIC_PASSWORD_SQL';"
6269
fi
6370

6471
if [ "$MIMIC_DB" != "postgres" ]; then
6572
# drop and recreate the database
66-
$PSQL -U postgres -d postgres -c "DROP DATABASE IF EXISTS $MIMIC_DB;"
67-
$PSQL -U postgres -d postgres -c "CREATE DATABASE $MIMIC_DB OWNER $MIMIC_USER;"
68-
fi
73+
$PSQL -U postgres -d postgres -c "DROP DATABASE IF EXISTS $MIMIC_DB_SQL;"
74+
$PSQL -U postgres -d postgres -c "CREATE DATABASE $MIMIC_DB_SQL OWNER $MIMIC_USER_SQL;"
75+
fi

mimic-iii/buildmimic/sqlite/import.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,34 @@
1010
CHUNKSIZE = 10 ** 6
1111
CONNECTION_STRING = "sqlite:///{}".format(DATABASE_NAME)
1212

13+
# Column dtypes for tables that trigger pandas mixed-type warnings when
14+
# loaded with the default low_memory chunked inference (see #1237).
15+
# Types mirror mimic-iii/buildmimic/postgres/postgres_create_tables.sql.
16+
TABLE_DTYPES = {
17+
"chartevents": {
18+
"WARNING": "Int64",
19+
"ERROR": "Int64",
20+
"RESULTSTATUS": "string",
21+
"STOPPED": "string",
22+
},
23+
"datetimeevents": {
24+
"WARNING": "Int64",
25+
"ERROR": "Int64",
26+
"RESULTSTATUS": "string",
27+
"STOPPED": "string",
28+
},
29+
"inputevents_cv": {
30+
"ORIGINALRATE": "float64",
31+
"ORIGINALRATEUOM": "string",
32+
"ORIGINALSITE": "string",
33+
},
34+
"noteevents": {
35+
"CHARTTIME": "string",
36+
"STORETIME": "string",
37+
"ISERROR": "string",
38+
},
39+
}
40+
1341

1442
def _table_name_from_csv(filename: str) -> str:
1543
"""Derive SQL table name from a CSV path (literal suffix, not str.strip)."""
@@ -21,20 +49,39 @@ def _table_name_from_csv(filename: str) -> str:
2149
return name.lower()
2250

2351

52+
def _read_csv(path, table, **kwargs):
53+
# low_memory=False avoids dtype re-inference across chunks; table-specific
54+
# dtypes pin the columns that otherwise flip between numeric/object.
55+
return pd.read_csv(
56+
path,
57+
index_col="ROW_ID",
58+
low_memory=False,
59+
dtype=TABLE_DTYPES.get(table),
60+
**kwargs,
61+
)
62+
63+
2464
if os.path.exists(DATABASE_NAME):
2565
msg = "File {} already exists.".format(DATABASE_NAME)
2666
print(msg)
2767
sys.exit()
2868

69+
# Prefer .csv.gz when both exist for the same table; also load plain .csv
70+
# (import.sh already accepts both).
71+
files_by_table = {}
72+
for f in glob("*.csv"):
73+
files_by_table[_table_name_from_csv(f)] = f
2974
for f in glob("*.csv.gz"):
75+
files_by_table[_table_name_from_csv(f)] = f
76+
77+
for table, f in sorted(files_by_table.items()):
3078
print("Starting processing {}".format(f))
31-
table = _table_name_from_csv(f)
3279
if os.path.getsize(f) < THRESHOLD_SIZE:
33-
df = pd.read_csv(f, index_col="ROW_ID")
80+
df = _read_csv(f, table)
3481
df.to_sql(table, CONNECTION_STRING)
3582
else:
3683
# If the file is too large, let's do the work in chunks
37-
for chunk in pd.read_csv(f, index_col="ROW_ID", chunksize=CHUNKSIZE):
84+
for chunk in _read_csv(f, table, chunksize=CHUNKSIZE):
3885
chunk.to_sql(table, CONNECTION_STRING, if_exists="append")
3986
print("Finished processing {}".format(f))
4087

mimic-iii/buildmimic/sqlite/import.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@ for FILE in *; do
2828
TABLE_NAME=$(echo "${FILE%%.*}" | tr "[:upper:]" "[:lower:]")
2929
case "$FILE" in
3030
*csv)
31-
IMPORT_CMD=".import $FILE $TABLE_NAME"
31+
IMPORT_CMD=".import \"$FILE\" $TABLE_NAME"
3232
;;
3333
# need to decompress csv before load
3434
*csv.gz)
35-
IMPORT_CMD=".import \"|gzip -dc $FILE\" $TABLE_NAME"
35+
IMPORT_CMD=".import \"|gzip -dc \\\"$FILE\\\"\" $TABLE_NAME"
3636
;;
3737
# not a data file so skip
3838
*)
3939
continue
4040
;;
4141
esac
4242
echo "Loading $FILE."
43-
sqlite3 $OUTFILE <<EOF
43+
sqlite3 "$OUTFILE" <<EOF
4444
.headers on
4545
.mode csv
4646
$IMPORT_CMD

0 commit comments

Comments
 (0)