/** * Compiles Fragment_SQL fragments into an SQL string. * * @param \Glue\DB\Fragment_SQL $fragment * * @return string */ protected function compile_sql(\Glue\DB\Fragment_SQL $fragment) { // Get data from fragment : $template = $fragment->sql(); $replacements = $fragment->replacements(); // Split template according to inline string litterals and identifiers : $matches = preg_split("/('(?:''|[^'])*'|`(?:``|[^`])*`)/", $template, -1, PREG_SPLIT_DELIM_CAPTURE); // Loop over matches and generate SQL : $cn = $this; $sql = ''; for ($i = 0; $i < count($matches); $i++) { // Get string : $part = $matches[$i]; // Tell apart delimiters from pieces : if ($i % 2 === 0) { // In-between string, we must make replacements : $sql .= preg_replace_callback('/[?!]/', function ($matches) use($cn, &$replacements) { // Get next replacement : $replacement = array_shift($replacements); // Replacement is a fragment ? if ($replacement instanceof \Glue\DB\Fragment) { return $cn->compile($replacement); } else { // Tell appart value from identifier replacements : if ($matches[0] === '?') { // Value : return $cn->quote_value($replacement); } else { // Identifier : if (is_array($replacement)) { $replacement = array_map(array($cn, 'quote_identifier'), $replacement); return implode('.', $replacement); } else { return $cn->quote_identifier($replacement); } } } }, $part); } else { // Delimiter string, we must quote it according to current connection conventions : if ($part[0] === "'") { // String litteral : $sql .= $this->quote(\Glue\DB\DB::unquote($part)); } else { // Identifier : $sql .= $this->quote_identifier(\Glue\DB\DB::unquote_identifier($part)); } } } return $sql; }