@@ -184,6 +184,7 @@ class QueryRender(ABC):
184184 details : PlatformDetails = None
185185 is_single_line_comment : bool = False
186186 unsupported_functions_text = "Unsupported functions were excluded from the result query:"
187+ unmapped_fields_text = "Unmapped fields: "
187188
188189 platform_functions : PlatformFunctions = None
189190
@@ -206,6 +207,11 @@ def wrap_with_not_supported_functions(self, query: str, not_supported_functions:
206207
207208 return query
208209
210+ def wrap_with_unmapped_fields (self , query : str , fields : Optional [list [str ]]) -> str :
211+ if fields :
212+ return query + "\n \n " + self .wrap_with_comment (f"{ self .unmapped_fields_text } { ', ' .join (fields )} " )
213+ return query
214+
209215 def wrap_with_comment (self , value : str ) -> str :
210216 return f"{ self .comment_symbol } { value } "
211217
@@ -216,7 +222,6 @@ def generate(self, query_container: Union[RawQueryContainer, TokenizedQueryConta
216222
217223class PlatformQueryRender (QueryRender ):
218224 mappings : BasePlatformMappings = None
219- is_strict_mapping : bool = False
220225
221226 or_token = "or"
222227 and_token = "and"
@@ -247,22 +252,10 @@ def generate_prefix(self, log_source_signature: Optional[LogSourceSignature], fu
247252 def generate_functions (self , functions : list [Function ], source_mapping : SourceMapping ) -> RenderedFunctions :
248253 return self .platform_functions .render (functions , source_mapping )
249254
250- def map_field (self , field : Field , source_mapping : SourceMapping ) -> list [str ]:
251- generic_field_name = field .get_generic_field_name (source_mapping .source_id )
252- # field can be mapped to corresponding platform field name or list of platform field names
253- mapped_field = source_mapping .fields_mapping .get_platform_field_name (generic_field_name = generic_field_name )
254- if not mapped_field and self .is_strict_mapping :
255- raise StrictPlatformException (field_name = field .source_name , platform_name = self .details .name )
256-
257- if isinstance (mapped_field , str ):
258- mapped_field = [mapped_field ]
259-
260- return mapped_field if mapped_field else [generic_field_name ] if generic_field_name else [field .source_name ]
261-
262255 def map_predefined_field (self , predefined_field : PredefinedField ) -> str :
263256 if not (mapped_predefined_field_name := self .predefined_fields_map .get (predefined_field .name )):
264- if self .is_strict_mapping :
265- raise StrictPlatformException (field_name = predefined_field . name , platform_name = self . details . name )
257+ if self .mappings . is_strict_mapping :
258+ raise StrictPlatformException (platform_name = self . details . name , fields = [ predefined_field . name ] )
266259
267260 return predefined_field .name
268261
@@ -275,7 +268,7 @@ def apply_token(self, token: QUERY_TOKEN_TYPE, source_mapping: SourceMapping) ->
275268 elif token .predefined_field :
276269 mapped_fields = [self .map_predefined_field (token .predefined_field )]
277270 else :
278- mapped_fields = self .map_field (token .field , source_mapping )
271+ mapped_fields = self .mappings . map_field (token .field , source_mapping )
279272 joined = self .logical_operators_map [LogicalOperatorType .OR ].join (
280273 [
281274 self .field_value_render .apply_field_value (field = field , operator = token .operator , value = token .value )
@@ -285,9 +278,13 @@ def apply_token(self, token: QUERY_TOKEN_TYPE, source_mapping: SourceMapping) ->
285278 return self .group_token % joined if len (mapped_fields ) > 1 else joined
286279 if isinstance (token , FieldField ):
287280 alias_left , field_left = token .alias_left , token .field_left
288- mapped_fields_left = [alias_left .name ] if alias_left else self .map_field (field_left , source_mapping )
281+ mapped_fields_left = (
282+ [alias_left .name ] if alias_left else self .mappings .map_field (field_left , source_mapping )
283+ )
289284 alias_right , field_right = token .alias_right , token .field_right
290- mapped_fields_right = [alias_right .name ] if alias_right else self .map_field (field_right , source_mapping )
285+ mapped_fields_right = (
286+ [alias_right .name ] if alias_right else self .mappings .map_field (field_right , source_mapping )
287+ )
291288 cross_paired_fields = list (itertools .product (mapped_fields_left , mapped_fields_right ))
292289 joined = self .logical_operators_map [LogicalOperatorType .OR ].join (
293290 [
@@ -311,14 +308,9 @@ def apply_token(self, token: QUERY_TOKEN_TYPE, source_mapping: SourceMapping) ->
311308
312309 def generate_query (self , tokens : list [QUERY_TOKEN_TYPE ], source_mapping : SourceMapping ) -> str :
313310 result_values = []
314- unmapped_fields = set ()
315311 for token in tokens :
316- try :
317- result_values .append (self .apply_token (token = token , source_mapping = source_mapping ))
318- except StrictPlatformException as err :
319- unmapped_fields .add (err .field_name )
320- if unmapped_fields :
321- raise StrictPlatformException (self .details .name , "" , source_mapping .source_id , sorted (unmapped_fields ))
312+ result_values .append (self .apply_token (token = token , source_mapping = source_mapping ))
313+
322314 return "" .join (result_values )
323315
324316 def wrap_with_meta_info (self , query : str , meta_info : Optional [MetaInfoContainer ]) -> str :
@@ -351,11 +343,13 @@ def finalize_query(
351343 meta_info : Optional [MetaInfoContainer ] = None ,
352344 source_mapping : Optional [SourceMapping ] = None , # noqa: ARG002
353345 not_supported_functions : Optional [list ] = None ,
346+ unmapped_fields : Optional [list [str ]] = None ,
354347 * args , # noqa: ARG002
355348 ** kwargs , # noqa: ARG002
356349 ) -> str :
357350 query = self ._join_query_parts (prefix , query , functions )
358351 query = self .wrap_with_meta_info (query , meta_info )
352+ query = self .wrap_with_unmapped_fields (query , unmapped_fields )
359353 return self .wrap_with_not_supported_functions (query , not_supported_functions )
360354
361355 @staticmethod
@@ -417,8 +411,10 @@ def generate_raw_log_fields(self, fields: list[Field], source_mapping: SourceMap
417411 mapped_field = source_mapping .fields_mapping .get_platform_field_name (
418412 generic_field_name = generic_field_name
419413 )
420- if not mapped_field and self .is_strict_mapping :
421- raise StrictPlatformException (field_name = field .source_name , platform_name = self .details .name )
414+ if not mapped_field and self .mappings .is_strict_mapping :
415+ raise StrictPlatformException (
416+ platform_name = self .details .name , fields = [field .source_name ], mapping = source_mapping .source_id
417+ )
422418 if prefix_list := self .process_raw_log_field_prefix (field = mapped_field , source_mapping = source_mapping ):
423419 for prefix in prefix_list :
424420 if prefix not in defined_raw_log_fields :
@@ -428,6 +424,9 @@ def generate_raw_log_fields(self, fields: list[Field], source_mapping: SourceMap
428424 def _generate_from_tokenized_query_container_by_source_mapping (
429425 self , query_container : TokenizedQueryContainer , source_mapping : SourceMapping
430426 ) -> str :
427+ unmapped_fields = self .mappings .check_fields_mapping_existence (
428+ query_container .meta_info .query_fields , source_mapping
429+ )
431430 rendered_functions = self .generate_functions (query_container .functions .functions , source_mapping )
432431 prefix = self .generate_prefix (source_mapping .log_source_signature , rendered_functions .rendered_prefix )
433432
@@ -443,6 +442,7 @@ def _generate_from_tokenized_query_container_by_source_mapping(
443442 query = query ,
444443 functions = rendered_functions .rendered ,
445444 not_supported_functions = not_supported_functions ,
445+ unmapped_fields = unmapped_fields ,
446446 meta_info = query_container .meta_info ,
447447 source_mapping = source_mapping ,
448448 )
0 commit comments