Ë
    Vçxj  ã            	      óÊ   — d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 dZ
e
de	diZd	Ze
ee	eiZd
Zdddddddddh	e£ZdhZdhZ	 	 	 	 	 	 	 	 	 	 	 	 dd„Zdd„Zdd„Zdd„Zdd„Zy) zKCreate a compact transactional SQLite patch between two NextLimit datasets.é    )ÚannotationsN)ÚPath)ÚROAD_SEGMENT_COLUMNSÚSCHEMA_VERSIONé   znextlimit-sqlite-diff-v1znextlimit-sqlite-diff-v2)Ú
segment_idÚ
osm_way_idÚfrom_node_idÚ
to_node_idÚ	directionÚlength_metersÚgeometryÚhighwayÚmaxspeedÚmaxspeed_forwardÚmaxspeed_backwardÚonewayÚjunctionÚaccessÚmotor_vehicleÚmotorcarÚsurfaceÚlanesÚrefÚnameÚzone_maxspeedÚsource_maxspeedÚmaxspeed_type)Ú
min_lat_e7Ú
max_lat_e7Ú
min_lon_e7Ú
max_lon_e7r	   r
   r   r   Ú
road_classÚspeed_limit_kmhÚspeed_sourceÚspeed_confidenceÚ
road_flagsr   r   c                óÂ  — t        | «      }t        |«      }|d   |d   k7  rt        d«      ‚|d   |d   k7  rt        d«      ‚t        |d   «      }t        j	                  |«      }t
        j	                  |«      }	|�|	€t        d|› �«      ‚|j                  j                  dd¬«       |j                  |j                  d	z   «      }
|
j                  d¬
«       t        j                  |
«      }	 |j                  dt        | j                  «       «      f«       |j                  dt        |j                  «       «      f«       t!        ||«       |j                  d|	|d   ||f«       |j                  d«       dj#                  d„ |dd D «       «      }|ddj#                  d„ t$        D «       «      z   z  }dj#                  d„ |D «       «      }|ddj#                  d„ t$        D «       «      z   z  }|j                  d|› d|› d�«       t'        |dd«      }dj#                  |«      }|j                  d|› d�«       |j)                  «        t        |j                  d«      j+                  «       d   «      }t        |j                  d«      j+                  «       d   «      }|j                  d «      j+                  «       }|d!k7  rt-        d"|› �«      ‚|j                  d#«       |j                  d$«       |j                  d%«       |j/                  «        t1        j2                  |
|«       ||fS # t4        $ r$ |j/                  «        |
j                  d¬
«       ‚ w xY w)&zFCreate `output` atomically and return deleted/upserted segment counts.Úregion_codez$datasets belong to different regionsÚschema_versionz6dataset schema changed; publish a full package insteadNzunsupported dataset schema: T)ÚparentsÚexist_okz.staging)Ú
missing_okzATTACH DATABASE ? AS previouszATTACH DATABASE ? AS currentz-INSERT INTO diff_metadata VALUES (?, ?, ?, ?)a  
            INSERT INTO deleted_segments(segment_id)
            SELECT old.segment_id
            FROM previous.road_segments old
            LEFT JOIN current.road_segments new ON new.segment_id = old.segment_id
            WHERE new.segment_id IS NULL
            z OR c              3  ó.   K  — | ]  }d |› d|› d�–— Œ y­w)z	NOT (new.z IS old.Ú)N© ©Ú.0Úcolumns     ú*/project/tools/osm-dataset/dataset_diff.pyÚ	<genexpr>zcreate_diff.<locals>.<genexpr>h   s"   è ø€ Ð!gÑVfÈF I¨f¨X°X¸f¸XÀQÔ"GÑVfùó   ‚r   c              3  ó.   K  — | ]  }d |› d|› d�–— Œ y­w)zNOT (new_bounds.z IS old_bounds.r/   Nr0   r1   s     r4   r5   zcreate_diff.<locals>.<genexpr>i   s$   è ø€ ð ,
ÙN\ÀFÐ˜v˜h o°f°X¸QÔ?Énùr6   ú, c              3  ó&   K  — | ]	  }d |› �–— Œ y­w)znew.Nr0   r1   s     r4   r5   zcreate_diff.<locals>.<genexpr>l   s   è ø€ ÐH¹<°˜t F 8œ_¹<ùó   ‚c              3  ó&   K  — | ]	  }d |› �–— Œ y­w)znew_bounds.Nr0   r1   s     r4   r5   zcreate_diff.<locals>.<genexpr>m   s   è ø€ Ð$YÉ.À {°6°(Ô%;É.ùr:   z<
            INSERT INTO upsert_segments
            SELECT ad  
            FROM current.road_segments new
            JOIN current.road_segment_rtree new_bounds ON new_bounds.row_id = new.row_id
            LEFT JOIN previous.road_segments old ON old.segment_id = new.segment_id
            LEFT JOIN previous.road_segment_rtree old_bounds ON old_bounds.row_id = old.row_id
            WHERE old.segment_id IS NULL OR z
            ÚcurrentÚdataset_metadataz#INSERT INTO target_metadata SELECT z& FROM current.dataset_metadata LIMIT 1z%SELECT COUNT(*) FROM deleted_segmentsr   z$SELECT COUNT(*) FROM upsert_segmentszPRAGMA quick_check(1))Úokz$diff SQLite integrity check failed: zDETACH DATABASE previouszDETACH DATABASE currentÚVACUUM)Úread_metadataÚ
ValueErrorÚintÚROAD_COLUMNS_BY_SCHEMAÚgetÚDIFF_FORMATSÚparentÚmkdirÚwith_suffixÚsuffixÚunlinkÚsqlite3ÚconnectÚexecuteÚstrÚresolveÚ_create_patch_schemaÚjoinÚBOUNDS_COLUMNSÚ_table_columnsÚcommitÚfetchoneÚRuntimeErrorÚcloseÚosÚreplaceÚ	Exception)Úpreviousr<   ÚoutputÚfrom_versionÚ
to_versionÚprevious_metadataÚcurrent_metadatar*   Úroad_columnsÚdiff_formatÚstagingÚ
connectionÚcomparisonsÚselectedÚmetadata_columnsÚcolumnsÚdeletedÚupsertedÚ	integritys                      r4   Úcreate_diffrl   ?   sl  € ô & hÓ/ÐÜ$ WÓ-ÐØ˜Ñ'Ð+;¸MÑ+JÒJÜÐ?Ó@Ð@ØÐ)Ñ*Ð.>Ð?OÑ.PÒPÜÐQÓRÐRÜÐ)Ð*:Ñ;Ó<€NÜ)×-Ñ-¨nÓ=€LÜ×"Ñ" >Ó2€KØÐ˜{Ð2ÜÐ7¸Ð7GÐHÓIÐIà
‡M�M×Ñ ¨tÐÔ4Ø× Ñ  §¡°Ñ!;Ó<€GØ‡N�N˜d€NÔ#Ü—‘ Ó)€Jð4Ø×ÑÐ:¼SÀ×AQÑAQÓASÓ=TÐ<VÔWØ×ÑÐ9¼CÀÇÁÓ@QÓ<RÐ;TÔUÜ˜Z¨Ô6Ø×ÑØ;ØÐ*¨=Ñ9¸<ÈÐTô	
ð 	×Ñðô	
ð —k‘kÑ!gÐVbÐcdÐceÑVfÓ!gÓgˆØ�v §¡ñ ,
ÝN\ó,
ó !
ñ 
ñ 	
ˆð —9‘9ÑH¹<ÓHÓHˆØ�D˜4Ÿ9™9Ñ$YÍ.Ó$YÓYÑYÑYˆØ×Ñðà�:ð -ð
 .9¨Mð :ðô
	
ô *¨*°iÐASÓTÐØ—)‘)Ð,Ó-ˆØ×ÑÐ@ÀÀ	ÐIoÐpÔqØ×ÑÔÜ�j×(Ñ(Ð)PÓQ×ZÑZÓ\Ð]^Ñ_Ó`ˆÜ�z×)Ñ)Ð*PÓQ×ZÑZÓ\Ð]^Ñ_Ó`ˆØ×&Ñ&Ð'>Ó?×HÑHÓJˆ	Ø˜ÒÜÐ!EÀiÀ[ÐQÓRÐRØ×ÑÐ5Ô6Ø×ÑÐ4Ô5Ø×Ñ˜8Ô$Ø×ÑÔÜ
�
‰
�7˜FÔ#Ø˜Ð Ð øÜò Ø×ÑÔØ�‰ $ˆÔ'Øðús   Ã0I L1 Ì1-Mc                ól  — t        j                  d| j                  «       › d�d¬«      }	 t        |dd«      }|j	                  ddj                  |«      › d	�«      j                  «       }|€t        d
| › �«      ‚t        t        ||d¬«      «      |j                  «        S # |j                  «        w xY w)Nzfile:z?mode=roT)ÚuriÚmainr=   zSELECT r8   z FROM dataset_metadata LIMIT 1zmissing dataset metadata: )Ústrict)rK   rL   rO   rS   rM   rQ   rU   rA   ÚdictÚziprW   )Údatasetrd   rh   Úrows       r4   r@   r@   Ž   s¦   € Ü—‘ 5¨¯©Ó):Ð(;¸8Ð!DÈ$ÔO€JðÜ  ¨VÐ5GÓHˆØ× Ñ  7¨4¯9©9°WÓ+=Ð*>Ð>\Ð!]Ó^×gÑgÓiˆØˆ;ÜÐ9¸'¸ÐCÓDÐDÜ”C˜ ¨TÔ2Ó3à×ÑÕøˆ
×ÑÕús   «A%B! Â!B3c                ól   — dj                  d„ |t        z   D «       «      }| j                  d|› d�«       y )Nz,
            c              3  ó2   K  — | ]  }t        |«      –— Œ y ­w)N)Ú_column_definitionr1   s     r4   r5   z'_create_patch_schema.<locals>.<genexpr>›   s   è ø€ Ð+sÑUrÈ6Ô,>¸v×,FÑUrùs   ‚a=  
        CREATE TABLE diff_metadata (
            format TEXT NOT NULL,
            region_id TEXT NOT NULL,
            from_version TEXT NOT NULL,
            to_version TEXT NOT NULL
        );
        CREATE TABLE deleted_segments (segment_id TEXT PRIMARY KEY);
        CREATE TABLE upsert_segments (
            a¯  
        );
        CREATE TABLE target_metadata (
            schema_version INTEGER NOT NULL,
            dataset_id TEXT NOT NULL,
            country_code TEXT NOT NULL,
            region_code TEXT NOT NULL,
            source_file TEXT NOT NULL,
            source_timestamp TEXT NOT NULL,
            generated_at TEXT NOT NULL,
            min_lat_e7 INTEGER NOT NULL,
            max_lat_e7 INTEGER NOT NULL,
            min_lon_e7 INTEGER NOT NULL,
            max_lon_e7 INTEGER NOT NULL,
            segment_count INTEGER NOT NULL,
            osm_attribution TEXT NOT NULL,
            osm_license TEXT NOT NULL,
            osm_license_url TEXT NOT NULL
        );
        )rQ   rR   Úexecutescript)rd   ra   Úupsert_columnss      r4   rP   rP   š   sD   € Ø&×+Ñ+Ñ+sÐUaÔdrÒUrÓ+sÓs€NØ×Ñð	ð Ðð 	ð	õó    c                óf   — | dk(  ry| t         v r| › d�S | t        v r| › d�S | t        v r| › d�S | › d�S )Nr   zsegment_id TEXT PRIMARY KEYz INTEGERz REALz BLOBz TEXT)ÚINTEGER_COLUMNSÚREAL_COLUMNSÚBLOB_COLUMNS)r3   s    r4   rw   rw   ½   sY   € Ø�ÒØ,Ø”Ñ Ø�˜Ð"Ð"Ø”ÑØ�˜ÐÐØ”ÑØ�˜ÐÐØˆX�UÐÐrz   c                óp   — | j                  d|› d|› d�«      D �cg c]  }t        |d   «      ‘Œ c}S c c}w )NzPRAGMA z.table_info(r/   r   )rM   rN   )rd   ÚdatabaseÚtablert   s       r4   rS   rS   É   sA   € Ø#-×#5Ñ#5¸À¸zÈÐV[ÐU\Ð\]Ð6^Ô#_Ó`Ñ#_˜CŒC��A‘�KÐ#_Ñ`Ð`ùÒ`s   ›3)r[   r   r<   r   r\   r   r]   rN   r^   rN   Úreturnztuple[int, int])rs   r   r‚   zdict[str, object])rd   úsqlite3.Connectionra   ztuple[str, ...]r‚   ÚNone)r3   rN   r‚   rN   )rd   rƒ   r€   rN   r�   rN   r‚   z	list[str])Ú__doc__Ú
__future__r   rX   rK   Úpathlibr   Údataset_schemar   r   ÚLEGACY_SCHEMA_VERSIONrE   ÚLEGACY_ROAD_COLUMNSrC   rR   r|   r}   r~   rl   r@   rP   rw   rS   r0   rz   r4   Ú<module>r‹      sî   ðá Qå "ã 	Û Ý ç ?àÐ àÐ5ØÐ.ð€ðÐ ð4 Ð.ØÐ(ðÐ ð J€àØØØØØØØØðð ð€ð  Ð €Øˆ|€ðLØðLàðLð ðLð ð	Lð
 ðLð óLó^	ó óF	ôarz   