code: def extract_equi_join_keys(
      join_predicate: AbstractExpression,
      left_table_aliases: List[Alias],
      right_table_aliases: List[Alias],
  ) -> Tuple[List[AbstractExpression], List[AbstractExpression]]:
      pred_list = to_conjunction_list(join_predicate)
      left_join_keys = []
      right_join_keys = []
      left_table_alias_strs = [
          left_table_alias.alias_name
          for left_table_alias in left_table_aliases
      ]
      right_table_alias_strs = [
          right_table_alias.alias_name
          for right_table_alias in right_table_aliases
      ]
  
      for pred in pred_list:
          if pred.etype == ExpressionType.COMPARE_EQUAL:
              left_child = pred.children[0]
              right_child = pred.children[1]
              # only extract if both are TupleValueExpression
              if (
                  left_child.etype == ExpressionType.TUPLE_VALUE
                  and right_child.etype == ExpressionType.TUPLE_VALUE
              ):
                  if (
                      left_child.table_alias in left_table_alias_strs
                      and right_child.table_alias
                      in right_table_alias_strs
                  ):
                      left_join_keys.append(left_child)
                      right_join_keys.append(right_child)
                  elif (
                      left_child.table_alias in right_table_alias_strs
                      and right_child.table_alias
                      in left_table_alias_strs
                  ):
                      left_join_keys.append(right_child)
                      right_join_keys.append(left_child)
  
      return (left_join_keys, right_join_keys)
  
imports: import typing
  from typing import List, Tuple
  from evadb.catalog.catalog_utils import get_table_primary_columns
  from evadb.catalog.models.column_catalog import ColumnCatalogEntry
  from evadb.catalog.models.function_io_catalog import FunctionIOCatalogEntry
  from evadb.catalog.models.function_metadata_catalog import FunctionMetadataCatalogEntry
  from evadb.constants import CACHEABLE_FUNCTIONS, DEFAULT_FUNCTION_EXPRESSION_COST
  from evadb.expression.abstract_expression import AbstractExpression, ExpressionType
  from evadb.expression.constant_value_expression import ConstantValueExpression
  from evadb.expression.expression_utils import conjunction_list_to_expression_tree, contains_single_column, get_columns_in_predicate, is_simple_predicate, to_conjunction_list
  from evadb.expression.function_expression import FunctionExpression, FunctionExpressionCache
  from evadb.expression.tuple_value_expression import TupleValueExpression
  from evadb.parser.alias import Alias
  from evadb.parser.create_statement import ColumnDefinition
  from evadb.utils.kv_cache import DiskKVCache
label_desc: Use image node_id 3 for calling a global function with example usage: extract_equi_join_keys(join_predicate, left_table_aliases, right_table_aliases) and returns: left_join_keys,  right_join_keys