class_docstr: Select Statement constructed after parsing the input query
  
  Attributes
  ----------
  _target_list : List[AbstractExpression]
      list of target attributes in the select query,
      each attribute is represented as a Abstract Expression
  _from_table : TableRef | Select Statement
      table reference in the select query, can be a select statement
      in nested queries
  _where_clause : AbstractExpression
      predicate of the select query, represented as a expression tree.
  **kwargs : to support other functionality, Orderby, Distinct, Groupby.
class_docstr_tok: ["Select","Statement","constructed","after","parsing","the","input","query","Attributes","--","--","--","--","--","_target_list",":","List","[","AbstractExpression","]","list","of","target","attributes","in","the","select","query",",","each","attribute","is","represented","as","a","Abstract","Expression","_from_table",":","TableRef","|","Select","Statement","table","reference","in","the","select","query",",","can","be","a","select","statement","in","nested","queries","_where_clause",":","AbstractExpression","predicate","of","the","select","query",",","represented","as","a","expression","tree",".","*","*","kwargs",":","to","support","other","functionality",",","Orderby",",","Distinct",",","Groupby","."]
code: def __str__(self) -> str:
      target_list_str = ""
      if self._target_list is not None:
          for expr in self._target_list:
              target_list_str += str(expr) + ", "
          target_list_str = target_list_str.rstrip(", ")
  
      orderby_list_str = ""
      if self._orderby_list is not None:
          for expr in self._orderby_list:
              sort_str = ""
              if expr[1] == ParserOrderBySortType.ASC:
                  sort_str = "ASC"
              elif expr[1] == ParserOrderBySortType.DESC:
                  sort_str = "DESC"
              orderby_list_str += str(expr[0]) + " " + sort_str + ", "
          orderby_list_str = orderby_list_str.rstrip(", ")
  
      select_str = f"SELECT {target_list_str}"
  
      if self._from_table is not None:
          select_str += " FROM " + str(self._from_table)
  
      if self._where_clause is not None:
          select_str += " WHERE " + str(self._where_clause)
  
      if self._union_link is not None:
          if not self._union_all:
              select_str += " UNION " + str(self._union_link)
          else:
              select_str += " UNION ALL " + str(self._union_link)
  
      if self._groupby_clause is not None:
          select_str += " GROUP BY " + str(self._groupby_clause)
  
      if self._orderby_list is not None:
          select_str += " ORDER BY " + orderby_list_str
  
      if self._limit_count is not None:
          select_str += " LIMIT " + str(self._limit_count)
  
      select_str = select_str.rstrip(" ")
  
      return select_str
  
imports: from __future__ import annotations
  import typing
  from typing import List, Union
  from evadb.expression.abstract_expression import AbstractExpression
  from evadb.parser.statement import AbstractStatement
  from evadb.parser.types import ParserOrderBySortType, StatementType
label_desc: Use image node_id 18 for calling the SelectStatement obj's underlying member method code with example usage: obj.__str__() and returns: select_str