<commit_before><?php

/**
 * SowerPHP
 * Copyright (C) SowerPHP (http://sowerphp.org)
 *
 * Este programa es software libre: usted puede redistribuirlo y/o
 * modificarlo bajo los términos de la Licencia Pública General Affero de GNU
 * publicada por la Fundación para el Software Libre, ya sea la versión
 * 3 de la Licencia, o (a su elección) cualquier versión posterior de la
 * misma.
 *
 * Este programa se distribuye con la esperanza de que sea útil, pero
 * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita
 * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO.
 * Consulte los detalles de la Licencia Pública General Affero de GNU para
 * obtener una información más detallada.
 *
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
 * junto a este programa.
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
 */

namespace sowerphp\core;

/**
 * Clase para trabajar con una base de datos PostgreSQL
 * @author <NAME>, DeLaF (esteban[at]delaf.cl)
 * @version 2014-09-24
 */
class Model_Datasource_Database_PostgreSQL extends Model_Datasource_Database_Manager
{

    /**
     * Constructor de la clase
     *
     * Realiza conexión a la base de datos, recibe parámetros para la
     * conexión
     * @param config Arreglo con los parámetros de la conexión
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2016-05-06
     */
    public function __construct($config)
    {
        // definir configuración para el acceso a la base de datos
        $this->config = array_merge(array(
            'host' => 'localhost',
            'port' => '5432',
            'char' => 'utf8',
            'sche' => 'public',
        ), $config);
        // abrir conexión a la base de datos
        parent::__construct(
            'pgsql:host='.$this->config['host'].
            ';port='.$this->config['port'].
            ';dbname='.$this->config['name'],
            $this->config['user'],
            $this->config['pass']
        );
        // definir encoding a utilizar con la base de datos
        $this->query('SET CLIENT_ENCODING TO \''.$this->config['char'].'\'');
        // definir esquema que se utilizará (solo si es diferente a public)
        if ($this->config['sche'] != 'public') {
            $this->query(
                'SET SEARCH_PATH TO '.$this->config['sche']
            );
        }
    }

    /**
     * Asigna un límite para la obtención de filas en la consulta SQL
     * @param sql Consulta SQL a la que se le agrega el límite
     * @return String Consulta con el límite agregado
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2012-09-09
     */
    public function setLimit($sql, $records, $offset = 0)
    {
        return $sql.' LIMIT '.(int)$records.' OFFSET '.(int)$offset;
    }

    /**
     * Concatena los parámetros pasados al método
     *
     * El método acepta n parámetros, pero dos como mínimo deben ser
     * pasados.
     * @param par1 Parámetro 1 que se quiere concatenar
     * @param par2 Parámetro 2 que se quiere concatenar
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2015-01-07
     */
    public function concat($par1, $par2)
    {
        $separators = array(' ', ',', ', ', '-', ' - ', '|', ':', ': ');
        $concat = array();
        $parameters = func_get_args();
        foreach($parameters as &$parameter) {
            if(in_array($parameter, $separators))
                $parameter = "'".$parameter."'";
            array_push($concat, $parameter);
        }
        return implode(' || ', $concat);
    }

    /**
     * Extrae un valor desde un nodo de un XML almacenado en una columna de la
     * base de datos
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2016-09-24
     */
    public function xml($column, $path, $namespace = null, $data_format = null)
    {
        if (!is_array($path))
            $path = [$path];
        $select = [];
        $column = 'CONVERT_FROM(decode('.$column.', \'base64\'), \'ISO8859-1\')::XML';
        foreach ($path as $k => $p) {
            if ($namespace) {
                $select[$k] = 'BTRIM(XPATH(\''.str_replace('/', '/n:', $p).'/text()\', '.$column.', \'{{n,'.$namespace.'}}\')::TEXT, \'{"}\')';
            } else {
                $select[$k] = 'BTRIM(XPATH(\''.$p.'/text()\', '.$column.')::TEXT, \'{}\')';
            }
        }
        return count($select)>1 ? $select : array_shift($select);
    }

    /**
     * Listado de tablas de la base de datos
     * @return Array Arreglo con las tablas (nombre y comentario)
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2014-04-26
     */
    public function getTables()
    {
        // obtener solo tablas del esquema indicado de la base de datos
        $tables = $this->getTable("
            SELECT t.table_name AS name
            FROM information_schema.tables AS t
            WHERE
                t.table_catalog = :database
                AND t.table_schema = :schema
                AND t.table_type = 'BASE TABLE'
            ORDER BY t.table_name
        ", [':database'=>$this->config['name'], ':schema'=>$this->config['sche']]);
        // buscar comentarios de las tablas
        foreach($tables as &$table) {
            $table['comment'] = $this->getCommentFromTable($table['name']);
        }
        // retornar tablas
        return $tables;
    }<commit_msg>Fix al seleccionar múltiples nodos de un XML<commit_after><?php

/**
 * SowerPHP
 * Copyright (C) SowerPHP (http://sowerphp.org)
 *
 * Este programa es software libre: usted puede redistribuirlo y/o
 * modificarlo bajo los términos de la Licencia Pública General Affero de GNU
 * publicada por la Fundación para el Software Libre, ya sea la versión
 * 3 de la Licencia, o (a su elección) cualquier versión posterior de la
 * misma.
 *
 * Este programa se distribuye con la esperanza de que sea útil, pero
 * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita
 * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO.
 * Consulte los detalles de la Licencia Pública General Affero de GNU para
 * obtener una información más detallada.
 *
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
 * junto a este programa.
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
 */

namespace sowerphp\core;

/**
 * Clase para trabajar con una base de datos PostgreSQL
 * @author <NAME>, DeLaF (esteban[at]delaf.cl)
 * @version 2014-09-24
 */
class Model_Datasource_Database_PostgreSQL extends Model_Datasource_Database_Manager
{

    /**
     * Constructor de la clase
     *
     * Realiza conexión a la base de datos, recibe parámetros para la
     * conexión
     * @param config Arreglo con los parámetros de la conexión
     * @author <NAME>io, DeLaF (esteban[at]delaf.cl)
     * @version 2016-05-06
     */
    public function __construct($config)
    {
        // definir configuración para el acceso a la base de datos
        $this->config = array_merge(array(
            'host' => 'localhost',
            'port' => '5432',
            'char' => 'utf8',
            'sche' => 'public',
        ), $config);
        // abrir conexión a la base de datos
        parent::__construct(
            'pgsql:host='.$this->config['host'].
            ';port='.$this->config['port'].
            ';dbname='.$this->config['name'],
            $this->config['user'],
            $this->config['pass']
        );
        // definir encoding a utilizar con la base de datos
        $this->query('SET CLIENT_ENCODING TO \''.$this->config['char'].'\'');
        // definir esquema que se utilizará (solo si es diferente a public)
        if ($this->config['sche'] != 'public') {
            $this->query(
                'SET SEARCH_PATH TO '.$this->config['sche']
            );
        }
    }

    /**
     * Asigna un límite para la obtención de filas en la consulta SQL
     * @param sql Consulta SQL a la que se le agrega el límite
     * @return String Consulta con el límite agregado
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2012-09-09
     */
    public function setLimit($sql, $records, $offset = 0)
    {
        return $sql.' LIMIT '.(int)$records.' OFFSET '.(int)$offset;
    }

    /**
     * Concatena los parámetros pasados al método
     *
     * El método acepta n parámetros, pero dos como mínimo deben ser
     * pasados.
     * @param par1 Parámetro 1 que se quiere concatenar
     * @param par2 Parámetro 2 que se quiere concatenar
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2015-01-07
     */
    public function concat($par1, $par2)
    {
        $separators = array(' ', ',', ', ', '-', ' - ', '|', ':', ': ');
        $concat = array();
        $parameters = func_get_args();
        foreach($parameters as &$parameter) {
            if(in_array($parameter, $separators))
                $parameter = "'".$parameter."'";
            array_push($concat, $parameter);
        }
        return implode(' || ', $concat);
    }

    /**
     * Extrae un valor desde un nodo de un XML almacenado en una columna de la
     * base de datos
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2016-10-12
     */
    public function xml($column, $path, $namespace = null, $data_format = null)
    {
        if (!is_array($path))
            $path = [$path];
        $select = [];
        $column = 'CONVERT_FROM(decode('.$column.', \'base64\'), \'ISO8859-1\')::XML';
        foreach ($path as $k => $p) {
            if ($namespace) {
                $p = str_replace('|', '/text()|', str_replace('/', '/n:', $p)).'/text()';
                $select[$k] = 'BTRIM(XPATH(\''.$p.'\', '.$column.', \'{{n,'.$namespace.'}}\')::TEXT, \'{"}\')';
            } else {
                $p = str_replace('|', '/text()|', $p).'/text()';
                $select[$k] = 'BTRIM(XPATH(\''.$p.'\', '.$column.')::TEXT, \'{}\')';
            }
        }
        return count($select)>1 ? $select : array_shift($select);
    }

    /**
     * Listado de tablas de la base de datos
     * @return Array Arreglo con las tablas (nombre y comentario)
     * @author <NAME>, DeLaF (esteban[at]delaf.cl)
     * @version 2014-04-26
     */
    public function getTables()
    {
        // obtener solo tablas del esquema indicado de la base de datos
        $tables = $this->getTable("
            SELECT t.table_name AS name
            FROM information_schema.tables AS t
            WHERE
                t.table_catalog = :database
                AND t.table_schema = :schema
                AND t.table_type = 'BASE TABLE'
            ORDER BY t.table_name
        ", [':database'=>$this->config['name'], ':schema'=>$this->config['sche']]);
        // buscar comentarios de las tablas
        foreach($tables as &$table) {
            $table['comment'] = $this->getCommentFromTable($table['name']);
        }
        // retornar tablas
        return $tables;
    }
{'fraction_non_alphanumeric': 0.14385996900355547, 'fraction_numerical': 0.012580909836812836, 'mean_word_length': 2.230270906949352, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1561482', 'n_tokens_mistral': 3658, 'n_tokens_neox': 3530, 'n_words': 995}