docs: def get_symbol_id(symbol, dbconn, dbcurr, ibConn=None):
      """
      Retrives symbol's ID from the Database or create it if it doesn't exist
  
      :Parameters:
          symbol : str
              Instrument symbol
          dbconn : object
              Database connection to be used
          dbcurr : object
              Database cursor to be used
  
      :Optional:
          ibConn : object
              ezIBpy object (used for determining futures/options expiration)
  
      :Returns:
          symbol_id : int
              Symbol ID
      """
      def _get_contract_expiry(symbol, ibConn=None):
          # parse w/p ibConn
          if ibConn is None or isinstance(symbol, str):
              return tools.contract_expiry_from_symbol(symbol)
  
          # parse with ibConn
          contract_details = ibConn.contractDetails(symbol)["m_summary"]
          if contract_details["m_expiry"] == "":
              ibConn.createContract(symbol)
              return _get_contract_expiry(symbol, ibConn)
  
          if contract_details["m_expiry"]:
              return datetime.strptime(str(contract_details["m_expiry"]), '%Y%m%d'
                                       ).strftime("%Y-%m-%d")
  
          return contract_details["m_expiry"]
  
      # start
      asset_class = tools.gen_asset_class(symbol)
      symbol_group = tools.gen_symbol_group(symbol)
      clean_symbol = symbol.replace("_" + asset_class, "")
      expiry = None
  
      if asset_class in ("FUT", "OPT", "FOP"):
          expiry = _get_contract_expiry(symbol, ibConn)
  
          # look for symbol w/ expiry
          sql = """SELECT id FROM `symbols` WHERE
              `symbol`=%s AND `symbol_group`=%s AND `asset_class`=%s  AND `expiry`=%s LIMIT 1"""
          dbcurr.execute(sql, (clean_symbol, symbol_group, asset_class, expiry))
  
      else:
          # look for symbol w/o expiry
          sql = """SELECT id FROM `symbols` WHERE
              `symbol`=%s AND `symbol_group`=%s AND `asset_class`=%s LIMIT 1"""
          dbcurr.execute(sql, (clean_symbol, symbol_group, asset_class))
  
      row = dbcurr.fetchone()
  
      # symbol already in db
      if row is not None:
          return row[0]
  
      # symbol/expiry not in db... insert new/update expiry
      else:
          # need to update the expiry?
          if expiry is not None:
              sql = """SELECT id FROM `symbols` WHERE
                  `symbol`=%s AND `symbol_group`=%s AND `asset_class`=%s LIMIT 1"""
              dbcurr.execute(sql, (clean_symbol, symbol_group, asset_class))
  
              row = dbcurr.fetchone()
              if row is not None:
                  sql = "UPDATE `symbols` SET `expiry`='" + \
                      str(expiry) + "' WHERE id=" + str(row[0])
                  dbcurr.execute(sql)
                  try:
                      dbconn.commit()
                  except Exception as e:
                      return False
                  return int(row[0])
  
          # insert new symbol
          sql = """INSERT IGNORE INTO `symbols`
              (`symbol`, `symbol_group`, `asset_class`, `expiry`) VALUES (%s, %s, %s, %s)
              ON DUPLICATE KEY UPDATE `symbol`=`symbol`, `expiry`=%s
          """
  
          dbcurr.execute(sql, (clean_symbol, symbol_group,
                               asset_class, expiry, expiry))
          try:
              dbconn.commit()
          except Exception as e:
              return False
  
          return dbcurr.lastrowid