@@ -56,44 +56,61 @@ def write_stats_table(
5656 FROM read_parquet('{ stats_parquet_path } ')
5757 """ )
5858
59- # create geojson with metadata at top level
60- con .execute (f"""
61- COPY (
62- SELECT json_object(
63- 'type', 'FeatureCollection',
64- 'metadata', '{ metadata_json } '::JSON,
65- 'features', (
66- SELECT json_group_array(
67- json_object(
68- 'type', 'Feature',
69- 'properties', json_object(
70- 'GEOID', GEOID,
71- { "'STUSPS', STUSPS, 'NAME', NAME," if stats_table_name == 'states' else "'NAME', NAME," if stats_table_name == 'counties' else '' }
72- 'building_count', building_count,
73- 'rps_2011_mean', rps_2011_mean,
74- 'rps_2047_mean', rps_2047_mean,
75- 'bp_2011_mean', bp_2011_mean,
76- 'bp_2047_mean', bp_2047_mean,
77- 'crps_scott_mean', crps_scott_mean,
78- 'bp_2011_riley_mean', bp_2011_riley_mean,
79- 'bp_2047_riley_mean', bp_2047_riley_mean,
80- 'rps_2011_median', rps_2011_median,
81- 'rps_2047_median', rps_2047_median,
82- 'bp_2011_median', bp_2011_median,
83- 'bp_2047_median', bp_2047_median,
84- 'crps_scott_median', crps_scott_median,
85- 'bp_2011_riley_median', bp_2011_riley_median,
86- 'bp_2047_riley_median', bp_2047_riley_median
87- ),
88- 'geometry', json(ST_AsGeoJSON(geometry))
89- )
90- )
91- FROM { stats_table_name }
92- )
93- )::VARCHAR as content
94- ) TO '{ region_stats_path } /stats.geojson' (FORMAT csv, HEADER false, QUOTE '');
95- """ )
59+ # Stream features row-by-row via fetchone() to avoid json_group_array overflow
60+ name_props = (
61+ "'STUSPS', STUSPS, 'NAME', NAME,"
62+ if stats_table_name == 'states'
63+ else "'NAME', NAME,"
64+ if stats_table_name == 'counties'
65+ else ''
66+ )
9667
68+ feature_query = f"""
69+ SELECT json_object(
70+ 'type', 'Feature',
71+ 'properties', json_object(
72+ 'GEOID', GEOID,
73+ { name_props }
74+ 'building_count', building_count,
75+ 'rps_2011_mean', rps_2011_mean,
76+ 'rps_2047_mean', rps_2047_mean,
77+ 'bp_2011_mean', bp_2011_mean,
78+ 'bp_2047_mean', bp_2047_mean,
79+ 'crps_scott_mean', crps_scott_mean,
80+ 'bp_2011_riley_mean', bp_2011_riley_mean,
81+ 'bp_2047_riley_mean', bp_2047_riley_mean,
82+ 'rps_2011_median', rps_2011_median,
83+ 'rps_2047_median', rps_2047_median,
84+ 'bp_2011_median', bp_2011_median,
85+ 'bp_2047_median', bp_2047_median,
86+ 'crps_scott_median', crps_scott_median,
87+ 'bp_2011_riley_median', bp_2011_riley_median,
88+ 'bp_2047_riley_median', bp_2047_riley_median,
89+ 'risk_score_2011_hist', risk_score_2011_hist,
90+ 'risk_score_2047_hist', risk_score_2047_hist
91+ ),
92+ 'geometry', json(ST_AsGeoJSON(geometry))
93+ )::VARCHAR as feature
94+ FROM { stats_table_name }
95+ """
96+
97+ geojson_path = region_stats_path / 'stats.geojson'
98+ with geojson_path .open ('w' ) as out :
99+ out .write ('{"type":"FeatureCollection",' )
100+ out .write (f'"metadata":{ metadata_json } ,' )
101+ out .write ('"features":[' )
102+
103+ result = con .execute (feature_query )
104+ first = True
105+ while row := result .fetchone ():
106+ if not first :
107+ out .write (',' )
108+ out .write (row [0 ])
109+ first = False
110+
111+ out .write (']}' )
112+
113+ # CSV output
97114 csv_path = region_stats_path / 'stats.csv'
98115
99116 temp_csv_path = region_stats_path / 'stats_temp.csv'
0 commit comments