def fetch_stock_data(ticker, start_date):
    """
    Fetch historical stock data from database first, then yfinance if needed.
    Also checks for earliest available date.
    """
    try:
        start_date = pd.to_datetime(start_date)
        ticker = ticker.strip().upper()
        today = pd.Timestamp.now().normalize()
        
        # First check yfinance for earliest available date
        try:
            # Use a more recent date for the initial check (e.g., 1970)
            earliest_check = yf.download(
                ticker,
                start='1970-01-01',
                end=today,
                progress=False,
                auto_adjust=False,
                timeout=30
            )
            if earliest_check.empty:
                logger.error(f"No data available from yfinance for {ticker}")
                return None
                
            earliest_available = earliest_check.index[0]
            logger.info(f"Earliest available date for {ticker}: {earliest_available}")
            
            # If requested start date is before earliest available
            if start_date < earliest_available:
                logger.warning(f"Adjusting start date from {start_date} to {earliest_available} for {ticker}")
                start_date = earliest_available
                
        except Exception as e:
            logger.error(f"Error checking earliest date for {ticker}: {str(e)}")
            return None

        # Get sector info and proceed with normal data fetch
        db = SessionLocal()
        try:
            sector_query = text("""
                SELECT gics_sector, gics_sub_industry 
                FROM market_tickers 
                WHERE ticker = :ticker
            """)
            sector_info = db.execute(sector_query, {"ticker": ticker}).first()
            
            # Get data from database
            stock_query = text("""
                SELECT date, open, high, low, close, volume
                FROM stock_data 
                WHERE ticker = :ticker 
                AND date >= :start_date
                ORDER BY date
            """)
            
            result = db.execute(
                stock_query, 
                {"ticker": ticker, "start_date": start_date}
            )
            
            # Convert result to DataFrame
            db_data = pd.DataFrame(result.fetchall(), columns=['Date', 'Open', 'High', 'Low', 'Close', 'Volume'])
            if not db_data.empty:
                db_data.set_index('Date', inplace=True)
                db_data['Adj Close'] = db_data['Close']
                
                if sector_info:
                    db_data['gics_sector'] = sector_info[0]
                    db_data['gics_sub_industry'] = sector_info[1]
                
                latest_db_date = db_data.index.max()
                
                # If data is up to date and covers the entire requested period, return it
                if latest_db_date >= today - pd.Timedelta(days=1) and db_data.index[0] <= start_date:
                    logger.info(f"Using database data for {ticker}")
                    return db_data
                
                # If we need to fetch new data or backfill historical data
                if db_data.index[0] > start_date:
                    # Need to fetch historical data - use the adjusted start_date
                    historical_data = yf.download(
                        ticker,
                        start=start_date,  # Use adjusted start_date
                        end=db_data.index[0],
                        progress=False,
                        auto_adjust=False,
                        timeout=30
                    )
                    if not historical_data.empty:
                        if sector_info:
                            historical_data['gics_sector'] = sector_info[0]
                            historical_data['gics_sub_industry'] = sector_info[1]
                        save_stock_data_to_db(ticker, historical_data)
                        db_data = pd.concat([historical_data, db_data])
                
                if latest_db_date < today - pd.Timedelta(days=1):
                    # Need to fetch recent data
                    new_data = yf.download(
                        ticker,
                        start=latest_db_date + pd.Timedelta(days=1),
                        end=today,
                        progress=False,
                        auto_adjust=False,
                        timeout=30
                    )
                    if not new_data.empty:
                        if sector_info:
                            new_data['gics_sector'] = sector_info[0]
                            new_data['gics_sub_industry'] = sector_info[1]
                        save_stock_data_to_db(ticker, new_data)
                        db_data = pd.concat([db_data, new_data])
                
                return db_data
            
            # If no data in database, fetch all from yfinance
            logger.info(f"Fetching all data for {ticker} from yfinance")
            stock_data = yf.download(
                ticker,
                start=start_date,
                end=today,
                progress=False,
                auto_adjust=False,
                timeout=30
            )
            
            if not stock_data.empty:
                if sector_info:
                    stock_data['gics_sector'] = sector_info[0]
                    stock_data['gics_sub_industry'] = sector_info[1]
                
                save_stock_data_to_db(ticker, stock_data)
                return stock_data
            
            logger.warning(f"No data available for {ticker}")
            return None
            
        finally:
            db.close()

    except Exception as e:
        logger.error(f"Failed to fetch data for {ticker}: {str(e)}", exc_info=True)
        return None

enhance the above functions based on below and return me full updated code:
Key changes made:
Removed the initial yfinance check for earliest available date since we're using database data
Prioritized database data retrieval
Only fetch from yfinance if:
No data exists in database
We need newer data (data in database is not up to date)
Added better error handling and logging
This should significantly improve the performance since it:
Reduces unnecessary API calls to yfinance
Uses database data as the primary source
Only makes API calls when absolutely necessary
The function will now:
First check the database for data
Use that data if available
Only fetch from yfinance if needed for newer data
Fall back to yfinance only if no data exists in database
This should prevent the long delays you're experiencing while waiting for yfinance API calls.