protected function buildClause(array $cond)
    {
        // handle SQL fragments
        if (count($cond) == 1 && (is_string($cond[0]) || !is_callable($cond[0]))) {
            return $cond[0];
        }

        // handle EXISTS conditions
        if ($cond[0] === 'EXISTS') {
            return $this->buildExists($cond[1], $cond[2]);
        }

        // handle BETWEEN conditions
        if ($cond[0] === 'BETWEEN') {
            return $this->buildBetween($cond[1], $cond[2], $cond[3], $cond[4]);
        }

        // escape an identifier
        if (is_string($cond[0]) || !is_callable($cond[0])) {
            $cond[0] = $this->escapeIdentifier($cond[0]);

        // handle a subquery
        // NOTE string callables are not supported
        // as subquery functions
        } elseif (is_callable($cond[0])) {
            $cond[0] = $this->buildSubquery($cond[0]);
        }

        if (count($cond) === 1 || empty($cond[0])) {
            return $cond[0];
        }

        // handle NULL values
        if ($cond[2] === null && in_array($cond[1], ['=', '<>'])) {
            return $this->buildNull($cond[0], $cond[1] == '=');
        }

        // handle IN values
        if (is_array($cond[2]) && in_array($cond[1], ['=', '<>'])) {
            return $this->buildIn($cond[0], $cond[2], $cond[1] == '=');
        }

        // otherwise parameterize the value
        $cond[2] = $this->parameterize($cond[2]);

        return implode(' ', $cond);
    }