protected static function buildQueryStatement(
        &$objQueryBuilder,
        iCondition $objConditions,
        $objOptionalClauses,
        $mixParameterArray,
        $blnCountOnly
    ) {
        // Get the Database Object for this Class
        $objDatabase = static::getDatabase();
        $strTableName = static::getTableName();

        // Create/Build out the QueryBuilder object with class-specific SELECT and FROM fields
        $objQueryBuilder = new Builder($objDatabase, $strTableName);

        $blnAddAllFieldsToSelect = true;
        if ($objDatabase->OnlyFullGroupBy) {
            // see if we have any group by or aggregation clauses, if yes, don't add all the fields to select clause by default
            // because these databases post an error instead of just choosing a value to return when a select item could
            // have multiple values
            if ($objOptionalClauses instanceof iClause) {
                if ($objOptionalClauses instanceof Clause\AggregationBase || $objOptionalClauses instanceof Clause\GroupBy) {
                    $blnAddAllFieldsToSelect = false;
                }
            } else {
                if (is_array($objOptionalClauses)) {
                    foreach ($objOptionalClauses as $objClause) {
                        if ($objClause instanceof Clause\AggregationBase || $objClause instanceof Clause\GroupBy) {
                            $blnAddAllFieldsToSelect = false;
                            break;
                        }
                    }
                }
            }
        }


        $objQueryBuilder->addFromItem($strTableName);

        // Set "CountOnly" option (if applicable)
        if ($blnCountOnly) {
            $objQueryBuilder->setCountOnlyFlag();
        }

        // Apply Any Conditions
        if ($objConditions) {
            try {
                $objConditions->updateQueryBuilder($objQueryBuilder);
            } catch (Caller $objExc) {
                $objExc->incrementOffset();
                $objExc->incrementOffset();
                throw $objExc;
            }
        }

        // Iterate through all the Optional Clauses (if any) and perform accordingly
        if ($objOptionalClauses) {
            if ($objOptionalClauses instanceof iClause) {
                try {
                    $objOptionalClauses->updateQueryBuilder($objQueryBuilder);
                } catch (Caller $objExc) {
                    $objExc->incrementOffset();
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            } else {
                if (is_array($objOptionalClauses)) {
                    foreach ($objOptionalClauses as $objClause) {
                        try {
                            $objClause->updateQueryBuilder($objQueryBuilder);
                        } catch (Caller $objExc) {
                            $objExc->incrementOffset();
                            $objExc->incrementOffset();
                            throw $objExc;
                        }

                    }
                } else {
                    throw new Caller('Optional Clauses must be a iClause object or an array of iClause objects');
                }
            }
        }

        // Do this here because it needs to know if distinct clause is included, and that is determined above
        $objSelectClauses = QQ::extractSelectClause($objOptionalClauses);
        if ($objSelectClauses || $blnAddAllFieldsToSelect) {
            static::baseNode()->putSelectFields($objQueryBuilder, null, $objSelectClauses);
        }

        // Get the SQL Statement
        $strQuery = $objQueryBuilder->getStatement();

        // Substitute the correct sql variable names for the placeholders specified in the query, if any.
        if ($mixParameterArray) {
            if (is_array($mixParameterArray)) {
                if (count($mixParameterArray)) {
                    $strQuery = $objDatabase->prepareStatement($strQuery, $mixParameterArray);
                }

                // Ensure that there are no other Unresolved Named Parameters
                if (strpos($strQuery, chr(Node\NamedValue::DELIMITER_CODE) . '{') !== false) {
                    throw new Caller('Unresolved named parameters in the query');
                }
            } else {
                throw new Caller('Parameter Array must be an array of name-value parameter pairs');
            }
        }

        // Return the Objects
        return $strQuery;
    }