code: def exec(self, *args, **kwargs) -> Iterator[Batch]:
      # SELECT expr;
      if len(self.children) == 0:
          # Create a dummy batch with size 1
          dummy_batch = Batch(pd.DataFrame([0]))
          batch = apply_project(dummy_batch, self.target_list)
          if not batch.empty():
              yield batch
      # SELECT expr FROM table;
      elif len(self.children) == 1:
          child_executor = self.children[0]
          for batch in child_executor.exec(**kwargs):
              batch = apply_project(batch, self.target_list)
              if not batch.empty():
                  yield batch
      else:
          raise ExecutorError(
              "ProjectExecutor has more than 1 children."
          )
  
      # instrument required stats
      instrument_function_expression_cost(
          self.target_list, self.catalog()
      )
  
file_path: evadb/evadb/executor/project_executor.py
imports: from typing import Iterator
  import pandas
  from evadb.database import EvaDBDatabase
  from evadb.executor.abstract_executor import AbstractExecutor
  from evadb.executor.executor_utils import ExecutorError, apply_project, instrument_function_expression_cost
  from evadb.models.storage.batch import Batch
  from evadb.plan_nodes.project_plan import ProjectPlan
label_desc: Use image node_id 2 for calling the ProjectExecutor obj's underlying member method code with example usage: obj.exec() without return types