Ë
    Ìi×3  ã                  óD  — 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m	Z	m
Z
mZ d dlmZ d dlmZmZ d dlmZ d dlmZmZ d d	lmZmZ d d
lmZ d dlmZ d dlmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%  ejL                  e'«      Z( G d„ de!e   ee   «      Z) ed¬«       G d„ d«      «       Z*y)é    )ÚannotationsN)Ú	dataclass)ÚGenericÚListÚOptionalÚSequenceÚSet)ÚMETRIC_TIME_ELEMENT_NAME)ÚObjectBuilderItemDescriptionÚQueryItemType)ÚObjectBuilderTextProcessor)ÚConfiguredValidMethodMappingÚValidMethodMapping)ÚJinjaObjectParserÚQueryItemLocation)ÚSemanticManifestT)Ú
SavedQuery)ÚFileContextÚSavedQueryContextÚSavedQueryElementTypeÚSemanticManifestValidationRuleÚValidationErrorÚValidationIssueÚgenerate_exception_issueÚvalidate_safelyc                  ó  — e Zd ZdZe ed«      	 	 	 	 	 	 	 	 dd„«       «       Ze ed«      dd„«       «       Ze	 	 	 	 	 	 	 	 	 	 	 	 dd„«       Ze ed«      dd„«       «       Z	e ed«      dd	„«       «       Z
e ed
«      dd„«       «       Zy)ÚSavedQueryRulea�  Validates fields in a saved query.

    As the semantic model graph is not traversed completely in DSI, the validations for saved queries can't be complete.
    Consequently, the current plan is that we add a separate validation using MetricFlow in CI.

    * Check if metric names exist in the manifest.
    * Check that the where filter is valid using the same logic as WhereFiltersAreParsable
    z-Validate the group-by field in a saved query.c                ól  — g }|j                   j                  D �]Z  }	 t        j                  d|z   dz   |t        j
                  ¬«      }|j(                  D �cg c]  }|j*                  j,                  ‘Œ c}|j.                  D �cg c]  }|j0                  j,                  ‘Œ c}z   |j2                  D �cg c]  }|j4                  j,                  ‘Œ c}z   |j6                  D �cg c]  }|j8                  j,                  ‘Œ c}z   }t;        |«      dk7  s	|d   | vs�Œ|j                  t=        d|› d�t        t        j                  |j                  ¬«      t        j>                  |¬«      ¬«      «       �Œ] |S # t        $ r�}|j                  t        d|j                  › d�|t        t        j                  |j                  ¬«      t        j                  |¬«      dd	j!                  t#        j$                  |j&                  «      «      i¬
«      «       Y d }~�Œd }~ww xY wc c}w c c}w c c}w c c}w )Nz{{z}})Úwhere_sql_templateÚcustom_granularity_namesÚquery_item_locationz+trying to parse a group-by in saved query `ú`©Úmetadata©Úfile_contextÚelement_typeÚelement_valueÚ	tracebackÚ ©Úwhat_was_being_doneÚeÚcontextÚextrasé   r   z` is not a valid group-by name.©Úmessager.   ) Úquery_paramsÚgroup_byr   Úparse_call_parameter_setsr   ÚNON_ORDER_BYÚ	ExceptionÚappendr   Únamer   r   Úfrom_metadatar$   r   ÚWHEREÚjoinr)   Ú	format_tbÚ__traceback__Úentity_call_parameter_setsÚentity_referenceÚelement_nameÚdimension_call_parameter_setsÚdimension_referenceÚ"time_dimension_call_parameter_setsÚtime_dimension_referenceÚmetric_call_parameter_setsÚmetric_referenceÚlenr   ÚGROUP_BY)	Úvalid_group_by_element_namesÚsaved_queryr    ÚissuesÚgroup_by_itemÚparameter_setsr-   ÚxÚelement_names_in_group_bys	            úp/var/www/html/strategist-ai/venv/lib/python3.12/site-packages/dbt_semantic_interfaces/validations/saved_query.pyÚ_check_group_byszSavedQueryRule._check_group_bys2   sþ  € ð
 )+ˆà(×5Ñ5×>Ñ>ó )	ˆMðÜ!2×!LÑ!LØ'+¨mÑ';¸dÑ'BØ-EÜ(9×(FÑ(Fô"�ð. ;I×:cÑ:cÖd°Q�×#Ñ#×0Ó0ÒdØ?M×?kÑ?kÖl¸!�1×(Ñ(×5Ó5ÒlñmàDR×DuÑDuÖv¸q�1×-Ñ-×:Ó:Òvñwð =K×<eÑ<eÖf°q�1×%Ñ%×2Ó2Òfñgð &ô Ð,Ó-°Ò2Ð6OÐPQÑ6RÐZvÓ6vØ—‘Ü#Ø"# M ?Ð2QÐ RÜ 1Ü)4×)BÑ)BÈK×L`ÑL`Ô)aÜ)>×)GÑ)GØ*7ô!ôö	ðA)	ðT ˆøôG ò Ø—‘Ü,Ø.YÐZe×ZjÑZjÐYkÐklÐ,mØÜ 1Ü)4×)BÑ)BÈK×L`ÑL`Ô)aÜ)>×)DÑ)DØ*7ô!ð (¨¯©´×1DÑ1DÀQÇ_Á_Ó1UÓ)Vð ôôõ ûðüò$ eùÚlùÚvùÚfs0   ž,E9ÁH"ÂH'Â4H,Ã#H1Å9	HÆBHÈHz,Validate the metrics field in a saved query.c                óú   — g }|j                   j                  D ]_  }|| vsŒ|j                  t        d|› d�t	        t        j                  |j                  ¬«      t        j                  |¬«      ¬«      «       Œa |S )Nr"   z` is not a valid metric name.r#   r%   r1   )
r3   Úmetricsr8   r   r   r   r:   r$   r   ÚMETRIC)Úvalid_metric_namesrK   rL   Úmetric_names       rQ   Ú_check_metricszSavedQueryRule._check_metricse   s}   € ð )+ˆØ&×3Ñ3×;Ñ;ò 	ˆKØÐ"4Ò4Ø—‘Ü#Ø"# K =Ð0MÐ NÜ 1Ü)4×)BÑ)BÈK×L`ÑL`Ô)aÜ)>×)EÑ)EØ*5ô!ôõ	ð	ð ˆó    c                ón  — 	 |j                  ||«      }t        |d¬«      S # t        $ rŠ}t        dt        d| j                  ›d�|t        t        j                  | j                  ¬«      ||¬«      ddj                  t        j                  |j                  «      «      i¬	«      ¬«      cY d}~S d}~ww xY w)
zAParse a Jinja syntax object into an ObjectBuilderItemDescription.N©Úitem_descriptionÚvalidation_issuezparsing a field in z£. Note that metrics need to be specified using the object-builder syntax (`Metric('metric_name')`) and if `.descending(...)` is specified, it should be at the end.r#   r%   r)   r*   r+   )Úget_descriptionÚ_ParseQueryItemResultr7   r   r9   r   r   r:   r$   r<   r)   r=   r>   )rK   Útext_processorÚquery_item_inputr'   Úvalid_method_mappingr\   r-   s          rQ   Úparse_query_itemzSavedQueryRule.parse_query_itemw   s·   € ð	Ø-×=Ñ=Ð>NÐPdÓeÐÜ(Ð:JÐ]aÔbÐbøÜò 	Ü(Ø!%Ü!9à-¨k×.>Ñ.>Ð-Að B ð !ð
 Ü-Ü%0×%>Ñ%>È×H\ÑH\Ô%]Ø%1Ø&6ôð $ R§W¡W¬Y×-@Ñ-@ÀÇÁÓ-QÓ%Rðô"ôõ ûð	ús   ‚! ¡	B4ªA?B/Â)B4Â/B4z-Validate the order-by field in a saved query.c                óF  — g }t        | j                  j                  «      dk(  r|S t        «       }t	        «       }| j                  j
                  D ]¥  }t        j                  | |t        j                  j                  › d|› d�t        j                  t        j                  ¬«      }|j                  �|j                  |j                  «       |j                   €Œ‹|j#                  |j                   «       Œ§ | j                  j$                  D ]‡  }t        j                  | ||t        j&                  t        j                  ¬«      }|j                  �|j                  |j                  «       |j                   €Œm|j#                  |j                   «       Œ‰ t        |«      dkD  r|S | j                  j                  D ]ß  }t        j                  | ||t        j&                  t        j(                  ¬«      }|j                   �|j#                  |j                   «       Œa|j                  }|€J d«       ‚|j+                  «       |vsŒ‰|j#                  t-        |› d�t/        t1        j2                  | j4                  ¬«      t        j6                  |¬«      ¬	«      «       Œá |S )
z¶Check that the order-by items in a saved query are valid.

        The order-by item without the `.descending()` should match with one of the metric items or group-by items.
        r   z('z'))rK   r`   ra   r'   rb   z2This should have been ensured by the result class.z= does not match any of the listed metrics or group-by items. r#   r%   r1   )rH   r3   Úorder_byÚsetr   rT   r   rc   r   rU   Úvaluer   r   ÚDEFAULT_MAPPINGr\   Úaddr]   r8   r4   rI   ÚDEFAULT_MAPPING_FOR_ORDER_BYÚwith_descending_unsetr   r   r   r:   r$   ÚORDER_BY)	rK   Úvalidation_issuesÚvalid_query_item_descriptionsr`   ÚmetricÚresultr4   re   r\   s	            rQ   Ú_check_order_byzSavedQueryRule._check_order_by™   s~  € ð 46ÐÜˆ{×'Ñ'×0Ñ0Ó1°QÒ6Ø$Ð$ä(+«Ð%Ü3Ó5ˆØ!×.Ñ.×6Ñ6ò 	BˆFô $×4Ñ4Ø'Ø-Ü$1×$8Ñ$8×$>Ñ$>Ð#?¸rÀ&ÀÈÐ!LÜ2×9Ñ9Ü%A×%QÑ%Qð 5ó ˆFð ×&Ñ&Ð2Ø-×1Ñ1°&×2IÑ2IÔJØ×&Ñ&Ñ2Ø!×(Ñ(¨×)@Ñ)@ÕAð	Bð $×0Ñ0×9Ñ9ò 	BˆHÜ#×4Ñ4Ø'Ø-Ø!)Ü2×;Ñ;Ü%A×%QÑ%Qð 5ó ˆFð ×&Ñ&Ð2Ø-×1Ñ1°&×2IÑ2IÔJØ×&Ñ&Ñ2Ø!×(Ñ(¨×)@Ñ)@ÕAð	Bô Ð Ó! AÒ%Ø$Ð$à#×0Ñ0×9Ñ9ò 	ˆHÜ#×4Ñ4Ø'Ø-Ø!)Ü2×;Ñ;Ü%A×%^Ñ%^ð 5ó ˆFð ×&Ñ&Ð2Ø!×(Ñ(¨×)@Ñ)@ÔAØØ%×6Ñ6ÐØ#Ð/ÐeÐ1eÓeÐ/ð  ×5Ñ5Ó7Ð?\Ò\Ø!×(Ñ(Ü#Ø#+ *Ð,iÐ jÜ 1Ü)4×)BÑ)BÈK×L`ÑL`Ô)aÜ)>×)GÑ)GØ*2ô!ôõ	ð!	ð6 !Ð rY   c                ó
  — g }| j                   j                  }|€|S |dk  ra|j                  t        d|› d�t	        t        j                  | j                  ¬«      t        j                  t        |«      ¬«      ¬«      «       |S )Nr   zInvalid limit value: z (should be >= 0)r#   r%   r1   )r3   Úlimitr8   r   r   r   r:   r$   r   ÚLIMITÚstr)rK   rm   rs   s      rQ   Ú_check_limitzSavedQueryRule._check_limitã   s„   € ð 46ÐØ×(Ñ(×.Ñ.ˆØˆ=Ø$Ð$à�1Š9Ø×$Ñ$ÜØ3°E°7Ð:KÐLÜ-Ü%0×%>Ñ%>È×H\ÑH\Ô%]Ü%:×%@Ñ%@Ü&)¨%£jôôô	ð !Ð rY   z2Validate all saved queries in a semantic manifest.c                óÐ  — g }| j                   j                  D ��cg c]  }|j                  D ]  }|j                  ‘Œ Œ! }}}| j                  D �ch c]  }|j                  ’Œ }}|j                  t        h«      }| j                  D ]Z  }|j                  D ]  }	|j                  |	j                  «       Œ |j                  D ]  }
|j                  |
j                  «       Œ Œ\ | j                  D ]g  }|t        j                  ||¬«      z  }|t        j                  |||¬«      z  }|t        j                  |«      z  }|t        j!                  |«      z  }Œi |S c c}}w c c}w )N)rV   rK   )rJ   rK   r    )Úproject_configurationÚtime_spinesÚcustom_granularitiesr9   rT   Úunionr
   Úsemantic_modelsÚ
dimensionsri   ÚentitiesÚsaved_queriesr   rX   rR   rq   rv   )Úsemantic_manifestrL   Ú
time_spineÚgranularityr    ro   rV   rJ   Úsemantic_modelÚ	dimensionÚentityrK   s               rQ   Úvalidate_manifestz SavedQueryRule.validate_manifestù   s�  € ð )+ˆð 0×EÑE×QÑQ÷$
àØ)×>Ñ>ò$
ð ð ×Óð$
Øð$
Ð ñ $
ð
 9J×8QÑ8QÖR¨f˜fŸk›kÐRÐÐRØ'9×'?Ñ'?ÔAYÐ@ZÓ'[Ð$Ø/×?Ñ?ò 	>ˆNØ+×6Ñ6ò A�	Ø,×0Ñ0°·±Õ@ðAà(×1Ñ1ò >�Ø,×0Ñ0°·±Õ=ñ>ð	>ð -×:Ñ:ò 	?ˆKØ”n×3Ñ3Ø#5Ø'ð 4ó ñ ˆFð ”n×5Ñ5Ø-IØ'Ø)Að 6ó ñ ˆFð
 ”n×4Ñ4°[ÓAÑAˆFØ”n×1Ñ1°+Ó>Ñ>‰Fð	?ð ˆùó3$
ùò
 Ss   œ$EÁE#N)rJ   úSet[str]rK   r   r    zSequence[str]ÚreturnúSequence[ValidationIssue])rV   r‡   rK   r   rˆ   r‰   )rK   r   r`   r   ra   ru   r'   r   rb   r   rˆ   r_   )rK   r   rˆ   r‰   )r€   r   rˆ   r‰   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr   rR   rX   rc   rq   rv   r†   © rY   rQ   r   r   (   s'  „ ñð ÙÐDÓEð/Ø&.ð/Ø=Gð/Øcpð/à	"ò/ó Fó ð/ðb ÙÐCÓDòó Eó ðð  ðØðà2ðð ðð ,ð	ð
 1ðð 
òó ððB ÙÐDÓEòF!ó Fó ðF!ðP ÙÐDÓEò!ó Fó ð!ð( ÙÐIÓJòó Kó ñrY   r   T)Úfrozenc                  ó.   — e Zd ZU dZded<   ded<   dd„Zy)	r_   z@Result of parsing a string like `Dimension('listing__country')`.z&Optional[ObjectBuilderItemDescription]r\   zOptional[ValidationIssue]r]   c                óB   — | j                   d u| j                  d uz  sJ ‚y )Nr[   )Úselfs    rQ   Ú__post_init__z#_ParseQueryItemResult.__post_init__   s'   € Ø×%Ñ%¨TÐ1°d×6KÑ6KÐSWÐ6WÒXÐXÑXrY   N)rˆ   ÚNone)rŠ   r‹   rŒ   r�   Ú__annotations__r”   r�   rY   rQ   r_   r_     s   … áJà<Ó<Ø/Ó/ôYrY   r_   )+Ú
__future__r   Úloggingr)   Údataclassesr   Útypingr   r   r   r   r	   Ú'dbt_semantic_interfaces.naming.keywordsr
   Ú9dbt_semantic_interfaces.parsing.text_input.ti_descriptionr   r   Ú7dbt_semantic_interfaces.parsing.text_input.ti_processorr   Ú7dbt_semantic_interfaces.parsing.text_input.valid_methodr   r   Ú@dbt_semantic_interfaces.parsing.where_filter.jinja_object_parserr   r   Ú!dbt_semantic_interfaces.protocolsr   Ú-dbt_semantic_interfaces.protocols.saved_queryr   Ú5dbt_semantic_interfaces.validations.validator_helpersr   r   r   r   r   r   r   r   Ú	getLoggerrŠ   Úloggerr   r_   r�   rY   rQ   ú<module>r¥      s™   ðÝ "ã Û Ý !ß 9Õ 9å L÷õ÷÷õ @Ý D÷	÷ 	ó 	ð 
ˆ×	Ñ	˜8Ó	$€ônÐ3Ð4EÑFÈÐPaÑHbô nñb �$Ô÷Yð Yó ñYrY   