Returns an instance of a basic function that has all of it's arguments either set to None or another instance of a function that has it's arguments set likewise. The caller should replace the None values with column references or constants as desired. The depth of the tree is de
(self, return_type, allow_subquery=False)
| 384 | return SelectItem(value) |
| 385 | |
| 386 | def create_func_tree(self, return_type, allow_subquery=False): |
| 387 | '''Returns an instance of a basic function that has all of it's arguments either set |
| 388 | to None or another instance of a function that has it's arguments set likewise. The |
| 389 | caller should replace the None values with column references or constants as |
| 390 | desired. The depth of the tree is determined by the query profile (self.profile). |
| 391 | ''' |
| 392 | signatures = self._funcs_to_allowed_signatures(FUNCS) |
| 393 | root_signatures = self._find_matching_signatures( |
| 394 | signatures, returns=return_type, allow_subquery=allow_subquery) |
| 395 | root_signature = self.profile.choose_func_signature(root_signatures) |
| 396 | func = root_signature.func(root_signature) # An instance of a function |
| 397 | max_children = self.profile.choose_nested_expr_count() |
| 398 | if max_children: |
| 399 | # Impala does not allow functions that contain subqueries to have arguments |
| 400 | # that contain subqueries. Ex: ... WHERE (int_col IN (SELECT 1)) IN (SELECT TRUE) |
| 401 | subquery_allowed_null_args = list() |
| 402 | subquery_not_allowed_null_args = list() |
| 403 | if func.contains_subquery: |
| 404 | null_args = subquery_not_allowed_null_args |
| 405 | else: |
| 406 | null_args = subquery_allowed_null_args |
| 407 | null_args.extend((func, idx) for idx, arg in enumerate(func.args) |
| 408 | if type(arg) != list and arg.val is None) |
| 409 | while max_children \ |
| 410 | and (subquery_allowed_null_args or subquery_not_allowed_null_args): |
| 411 | idx = randrange( |
| 412 | len(subquery_allowed_null_args) + len(subquery_not_allowed_null_args)) |
| 413 | if idx < len(subquery_allowed_null_args): |
| 414 | null_args = subquery_allowed_null_args |
| 415 | else: |
| 416 | null_args = subquery_not_allowed_null_args |
| 417 | shuffle(null_args) |
| 418 | parent_func, parent_arg_idx = null_args.pop() |
| 419 | child_signatures = self._find_matching_signatures( |
| 420 | signatures, |
| 421 | returns=parent_func.args[parent_arg_idx].type, |
| 422 | allow_subquery=(allow_subquery and null_args == subquery_allowed_null_args)) |
| 423 | child_signature = self.profile.choose_func_signature(child_signatures) |
| 424 | child_func = child_signature.func(child_signature) |
| 425 | parent_func.args[parent_arg_idx] = child_func |
| 426 | if child_func.contains_subquery: |
| 427 | null_args = subquery_not_allowed_null_args |
| 428 | else: |
| 429 | null_args = subquery_allowed_null_args |
| 430 | null_args.extend((child_func, idx) for idx, arg in enumerate(child_func.args) |
| 431 | if type(arg) != list and arg.val is None) |
| 432 | max_children -= 1 |
| 433 | return func |
| 434 | |
| 435 | def _funcs_to_allowed_signatures(self, funcs): |
| 436 | '''Return a list of the signatures contained in "funcs" that are eligible for use |
no test coverage detected