JavaScriptSQL (JSSQL)
Documentación

En esta sección la documentación de uso del motor JSSQL, del conversor JSBD_Conversor y del indexador JSBD_Indexador


Manual de Uso JavaScriptSQL (versión 2.1)

Otros manuales disponibles:

Índice

  1. Diseño Inicial
  2. Funcionalidades
  3. Posibles Aplicaciones
  4. Requisitos e instalación
  5. Ejemplo Básico de Uso
  6. Referencias de la clase JSSQL
    1. useDebug
    2. useIndex
    3. docsMaxLen
    4. docsMinLen
    5. Open(JSBD)
    6. Query(sql)
    7. GetError()
    8. GetDebug()
    9. GetDef()
    10. SetBaseDir(BaseDir)
  7. Tipos de Datos
  8. Sintaxis SQL
    1. SELECT
    2. FROM
    3. WHERE
    4. GROUP BY
    5. HAVING
    6. ORDER BY
    7. DISTINCT
    8. LIMIT
  9. Uso de Índices
  10. Indexado de documentos
  11. Particionado de Tablas

I. Diseño Inicial

A continuación se muestra el diagrama de diseño inicial que describe la relación entre los distintos módulos utilizados para el funcionamiento de la base de datos en JavaScript.

Diagrama de Diseño inicial

El funcionamiento básico de la base de datos para JavaScript consiste en generar mediante un conversor de bases de datos y un indexador de documentos los archivos de definiciones, tablas, índices y demás componentes de la base de datos JSBD. Luego el motor JSSQL permite acceder de manera eficiente a la base de datos JSBD mediante consultas SQL.

Cada uno de estos componentes o subsistemas están conformados por una o más clases a ser usadas por los desarrolladores. El conversor y el indexador están desarrollados en PHP mientras que el motor JSSQL esta desarrollado íntegramente en JavaScript.

Una vez generada una base de datos JSBD, se pueden realizar consultas SQL mediante el motor JSSQL sin necesidad de acceder a ningún otro motor de bases de datos y sin necesidad de utilizar ningún lenguaje de scripting que funcione del lado del servidor (PHP, ASP, etc.).

Índice

II. Funcionalidades

El motor de base de datos JSSQL es una clase enteramente desarrollada en JavaScript que permite realizar consultas SQL sobre la base de datos JSBD generada a tal efecto.

JSSQL es un motor de base de datos solamente de consulta, una vez generada la base de datos no es posible agregar más registros ni tablas.

Las consultas que procesa SQL deben son de la forma:


    SELECT
    [DISTINCT]
    * | expresión_de_select [ AS alias_campo ] [, ...]
    FROM nombre_tabla [alias_tabla] [, ...]
    [ WHERE condición_where ]
    [ GROUP BY numero_campo [, ... ] [HAVING condición_having ] ]
    [ ORDER BY numero_campo [ ASC | DESC ] [, ...] ]
    [ LIMIT cantidad ]

Donde:

expresión_de_select:
Es una expresión o conjunto de funciones aplicadas sobre los campos de las tablas listadas en la cláusula FROM. En estas expresiones pueden utilizarse funciones y operadores propios de JavaScript, funciones previamente definidas por el usuario o funciones de agregación (COUNT, SUM, AVG) en caso de agrupar registros mediante la cláusula GROUP BY. Por ejemplo "campo1" o "COUNT(pedidos)" o "nombre.ToUpperCase()".

condición_where:
Es una expresión que devuelve únicamente los valores true o false, puede estar compuesta por campos de las tablas listadas en la cláusula FROM. Pueden utilizarse funciones y operadores propios de JavaScript y funciones previamente definidas por el usuario.

condición_having:
Es una expresión que devuelve únicamente los valores true o false, puede estar compuesta por campos o expresiones enumeradas en la cláusula SELECT y marcadas como campos de agrupación en la cláusula GROUP BY. Pueden utilizarse funciones y operadores propios de JavaScript y funciones previamente definidas por el usuario.

numero_campo:
Es el número de campo dentro del listado de campos del SELECT, estos números no pueden repetirse dentro del listado definido en las cláusulas ORDER BY y GROUP BY.

cantidad:
Es la cantidad máxima de registros que se desea que devuelva la consulta.

La versión actual posee las siguientes características:

  • Permite la consulta de datos offline sin intervención de servidores WEB o servidores de bases de datos.
  • Permite flexibilidad en la sintaxis SQL, aceptando el uso de alias de campos y tablas, es case-insensitive en las cláusulas y campos y permite el uso de espacios múltiples, de manera de que la escritura de las sentencias SQL es sencilla e intuitiva.
  • Permite el uso de todas las funciones y operadores de JavaScript de manera que su uso para desarrolladores JavaScript es totalmente intuitivo. Además permite el uso de funciones definidas externamente por los usuarios.
  • Permite la definición y uso de índices para acelerar las consultas.
  • Permite la paginación de tablas de manera que puedan utilizarse tablas de gran cantidad de registros sin sobrecargar la memoria utilizada por el navegador.
  • Incluye funcionalidades para la búsqueda de texto dentro de documentos indexados mediante el indexador JSBD_Indexador y asociados mediante campos del tipo link en las tablas de la base de datos.
  • Informa claramente los errores de sintaxis, de ejecución y de carga de la base de datos y de las consultas SQL.
  • Prover mecanismos de debug para ayudar en el desarrollo, mantenimiento y testeo del motor.
  • Utiliza una estructura clara para la definición de las bases de datos y las estructuras de almacenamiento de los datos e índices. Utilizando estructuras compatibles con JSON.
  • Su uso e instalación es sencilla, de bajos requerimientos y compatible con los navegadores más utilizados.

Índice

III. Posibles Aplicaciones:

Cualquier tipo de aplicación que requiera la consulta y búsqueda de documentos desconectada de una base de datos, por ejemplo:

  • Un diccionario o enciclopedia.
  • Un catálogo.
  • Una recopilación de documentos.
  • Cualquier aplicación WEB con manejo de datos donde se necesite mayor dinamismo sin intervención del servidor. Por ejemplo una tabla dinámica de datos (o planilla de cálculos) que permita filtrar los valores presentados, realizar ordenamientos por los distintas columnas y realizar cálculos auxiliares (sumas, subtotales, promedios, etc.)
  • Un sistema de Business Intelligence (BI) donde los datos son agrupados por distintos campos mostrando de manera dinámica las distintas estadísticas. Por ejemplo en una aplicación de BI donde se analiza las ventas de una compañía, poder ver de manera dinámica las ventas por país, vendedor, tipo de cliente, producto, etc. Sin la necesidad de realizar reiteradas consultas al servidor.

Índice

IV. Requisitos e instalación

El motor JSSQL funciona en la mayoría de los navegadores modernos con JavaScrit habilitado, y fue probado formalmente en los siguientes navegadores:

  • Firefox 4.0
  • Internet Explorer 6.0
  • Google Crome 5.0

Para utilizar JSSQL simplemente deberá copiar el archivo JSSQL.js al directorio donde desea instalarlo y copiar la base de datos JSBD en el directorio 'bases' dentro del directorio de instalación.

Por ejemplo si el directorio de instalación es 'basedir' y la base de datos JSBD se llama 'neptuno' se tiene la siguiente estructura de archivos

    basedir\JSSQL.js
    basedir\bases\neptuno\

Por defecto el directorio de almacenamiento de los archivos de la JSBD es 'bases', pero puede modificarse mediante el método SetBaseDir(BaseDir).

Dentro del directorio 'basedir\bases\neptuno\' se encuentran todos los archivos de definición de la base de datos.

Es recomendable crear la base de datos JSBD mediante el conversor desarrollado a tal efecto ( JSBD_Conversor) e indexar los campos del tipo link mediante el indexador desarrollado a tal efecto (JSBD_Indexador).

Índice

V. Ejemplo Básico de Uso

A continuación se muestra un ejemplo de cómo utilizar la clase para realizar una consulta a la base de datos JSBD.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>Ejemplo de uso JSSQL</title>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

       <!-- AGREGADO DE LA CLASE JSSQL ------------------------------------------  --->
       <script LANGUAGE="JavaScript1.2" type="text/javascript" SRC="JSSQL.js"></script>
        <!-- ---------------------------------------------------------------------- --->

    </head>
    <body>
        <script LANGUAGE="JavaScript1.2" type="text/javascript">
                    
            //Creacion del motor JSSQL
            myJSSQL= new JSSQL();

            //Apertura de la base de datos neptuno
            if (!myJSSQL.Open('neptuno'))
            {
                alert(myJSSQL.GetError()); //si falla se muestra un mensaje de error
            }

            //Consulta SQL
            sql="select nombrecompania as comp, nombrecontacto as cont, cargocontacto as cargo
                 from clientes order by 3, 2 desc" ;

            //Ejecución de la consulta
            res=myJSSQL.Query(sql)

            if(res===false)
            {
                //si falla se muestra un mensaje de error
                alert( myJSSQL.GetError() );
            }
            else
            {
                //Impresión de resultados

                for (i=0;i < res.length;i++){
                    document.write(res[i]["comp"]);
                    document.write(" | ");
                    document.write(res[i]["cont"]);
                    document.write(" | ");
                    document.write(res[i]["cargo"]);
                    document.write(" | <br>");
                }

            }
        </script>
    </body>
</html>
                    

Índice

VI. Referencias de la clase JSSQL

A continuación se describen los métodos y atributos de la clase JSSQL

VI.i useDebug

Establece si se utiliza o no la generación de información de debug. Como ser tiempos de respuesta, cantidad de registros devueltos, cantidad de registros recorridos, estructuras utilizadas, etc. Por defecto se encuentra activada. Al desactivar esta opción el motor será un poco más rápido.

Índice

VI.ii useIndex

Establece si se analiza las condiciones del WHERE para utilizar los índices (de estar definidos), en caso de estar activado se supone que dichas condiciones están expresadas de una manera simple que impiden resultados inexactos (vea la sección "Uso de Índices" para mas información). Por defecto se encuentra deshabilitada.

Índice

VI.iii docsMaxLen

Establece la cantidad máxima de caracteres que puede tener una palabra en los índices de contenido. Si se realiza una búsqueda de una palabra con mayor cantidad de caracteres se la omite en la búsqueda.

Índice

VI.iv docsMinLen

Establece la cantidad mínima de caracteres que puede tener una palabra en los índices de contenido. Si se realiza una búsqueda de una palabra con cantidad menor de caracteres se la omite en la búsqueda.

Índice

VI.v Open(JSBD)

Abre la base de datos JSBD, cargando en memoria las tablas de datos, índices y definiciones correspondientes.

Parámetros:
JSBD: Nombre de la base de datos JSBD a abrir.

Devuelve:
true/false en caso de poder o no abrir las estructuras correspondientes. Utilizar GetError() para obtener una descripción del error.

Índice

VI.vi Query(sql)

Ejecuta una consulta a la base de datos.

Parámetros:
Sql: Consulta SQL a ejecutar.

Devuelve:
Un array con el conjunto de registros resultantes, el array tiene la forma:

    [
    {"campo1":valor, "campo2":valor, (...) } , // Registro 1
    (..)
    {"campo1":valor, "campo2":valor, (...) }  // Registro n
    ]

Devuelve false en caso de error. Utilizar GetError() para obtener una descripción del error.

Índice

VI.vii GetError()

Devuelve la descripción del último error generado.

Índice

VI.viii GetDebug()

Devuelve un array con los datos de debug generados en la última consulta, el array tiene la siguiente estructura:

    [
    {"nombre_propiedad_1":["descripción", valor] } , // propiedad 1
    (..)
    {"nombre_propiedad_n":["descripción", valor] } // propiedad n
    ]

Índice

VI.ix GetDef()

Devuelve un array con la definición de las tablas de la base de datos abierta, la estructura es la definida para la JSBD.

Índice

VI.x SetBaseDir(BaseDir)

Setea el directorio donde se almacenan las bases de datos JSBD

Parámetros:
Basedir: Directorio de almacenamiento de las bases JSBD.

Devuelve:
true/false en caso de poder o no abrir las estructuras correspondientes. Utilizar GetError() para obtener una descripción del error.

Índice

VII. Tipos de Datos

Los tipos posibles de los campos de la base JSBD son los siguientes:

  • numeric: números enteros, o flotantes.
  • string: cadenas de caracteres.
  • boolean: variables lógicas (true/false).
  • date: tiempo expresado en cantidad de milisegundos desde el 01/01/1970.
  • link: hace referencia a un documento cuyo contenido ha sido indexado.

Índice

VIII. Sintaxis SQL

Las consultas que procesa SQL deben son de la forma:

    SELECT
    [DISTINCT]
    * | expresión_de_select [ AS alias_campo ] [, ...]
    FROM nombre_tabla [alias_tabla] [, ...]
    [ WHERE condición_where ]
    [ GROUP BY numero_campo [, ... ] [HAVING condición_having ] ]
    [ ORDER BY numero_campo [ ASC | DESC ] [, ...] ]
    [ LIMIT cantidad ]

En todos los casos las cláusulas, nombres de tablas, nombres de campos y alias son case-insensitive, es decir que la cláusulas 'SELECT' y 'select' y 'SeLeCt' son válidas y son interpretadas de la misma manera.

Las funciones SUM, AVG, COUNT, CONTENT, ALL y ANY, son funciones definidas por el motor JSSQL y deben ser escritas en mayúscula.

Índice

VIII.i. SELECT

A continuación del SELECT debe incluirse un listado de expresiones que conforman los campos del resultado.

Haciendo referencia a los campos de una tabla:

    select nombre, apellidos from empleados

Utilizando alias para las expresiones:

    select nombre as N, apellidos as A from empleados

Cabe aclarar que no es correcto que se repitan los alias de las expresiones, si esto ocurre solo se devolverá el alias de la última expresión.

INCORRECTO:

     select nombre as N, apellidos as N from empleados 

Utilizando el '*'

    select * from empleados

    select *, idempleado as ID2  from empleados

En las expresiones pueden utilizarse cualquier operador o función definida fuera de la clase JSSQL

Utilizando operadores

    select idempleado *2 as IDx2 , nombre + '  ' + apellidos as NombreCompleto
    from empleados

Utilizando funciones y atributos de JavaScript

    Select nombre.length , nombre.match(/nancy/i), "CONSTANTE"  as C, escape(pais) as P
    from empleados

Convirtiendo una fecha dentro de la consulta

    Select nombre, (new Date(fechanacimiento)).getFullYear() as AnioNacimiento from empleados

Utilizando funciones externas. Suponiendo definidas las funciones pad() y DateFormat()

    select pad(idempleado,4) as id, DateFormat(E.Fechanacimiento) as FechaNacimiento
    from empleados E

Índice

VIII.ii. FROM

A continuación del FROM se listan las tablas a ser incluidas en la consulta.

En caso de ser más de una tabla el motor recorre las tablas como un producto cartesiano.

Cada tabla puede asociarse a un alias de tabla

    Select e.* from empleados e

El alias por defecto es el nombre completo de la tabla

    Select empleados.idempleado from empleados

Juntando tablas

    Select j.Apellidos, 'Es jefe de' as Relacion, e.apellidos
    from empleados e, empleados j
    where j.idempleado == e.jefe
(relaciona cada empleado con su jefe)

En caso de que no sean ambiguos los nombres de campos referidos en las expresiones del SELECT puede obviarse el uso de alias

    Select nombreproducto, nombrecategoria
    from categorias, productos

Índice

VIII.iii.WHERE

A continuación del WHERE debe escribirse una expresión lógica que devuelva true o false.

En esta expresión los operadores, funciones, métodos y propiedades son los disponibles en JavaScript y los definidos externamente por los usuarios.

    select nombre, apellidos from empleados
    where apellidos.length>5 && (nombre=='Nancy' || nombre=='Andrew')

    select nombre, apellidos from empleados
    where nombre.match(/an/i) != null

    Select nombre from empleados
    where(new Date(fechanacimiento)).getFullYear() > 1960

En esta condición también puede hacerse referencia a los alias de tablas

    Select nombreproducto, nombrecategoria from categorias c , productos p
    where c.idcategoria == p.idcategoria &&
    p.idcategoria != 5 && nombrecategoria != 'Bebidas'

En el caso de estar habilitado el uso de índices mediante la propiedad useIndex del motor JSSQL, hay que ser cuidadosos con las condiciones a utilizar, en algunos casos los resultados pueden ser inexactos. Vea mas adelante la sección "Uso de Índices" para mas información.

Índice

VIII.iv. GROUP BY

A continuación del GROUP BY debe listarse las expresiones que deben agruparse. Este listado debe contener únicamente números no repetidos donde cada uno haga referencia a una expresión del SELECT que no sea una función de agregación, es decir aquellas expresiones donde no se haga referencia a las funciones COUNT, AVG o SUM.

Al utilizar GROUP BY todas las expresiones del SELECT deben estar listadas en el GROUP BY o bien ser funciones de agrupación.

Un GROUP BY sin funciones de agrupación:

    Select pais, ciudad from empleados group by 1,2

A continuación las definiciones de las funciones de agrupación

SUM(NombreCampo)

Descripcion:
Devuelve la suma de los valores agrupados del campo NombreCampo.

Parámetros:
NombreCampo: el nombre del campo a sumar (debe ser de tipo numeric)

Ejemplos:

    select idpedido, SUM(cantidad) from detalledepedido group by 1

    select SUM(cargo) from pedidos

COUNT(NombreCampo)

Descripcion:
Devuelve la cuenta de los valores agrupados del campo NombreCampo. En caso de que el nombre del campo sea '*' se cuentan todos los valores, caso contrario se cuentan todos los valores no nulos

Parámetros:
NombreCampo: el nombre del campo a contar (debe ser de tipo numeric), para contar todos los registros se puede utilizar la cadena '*'

Ejemplos:

    select idpedido, COUNT('*') from detalledepedido group by 1 

    select COUNT(jefe) from empleados
(devuelve la cantidad de empleados con jefe no nulo)
    select COUNT('*') from empleados
(devuelve la cantidad total de empleados)

AVG(NombreCampo)

Descripcion:
Devuelve el promedio de los valores agrupados del campo.

Parámetros:
NombreCampo: el nombre del campo a promediar (debe ser de tipo numeric)

Ejemplos:

    select idpedido, AVG(cantidad) from detalledepedido group by 1

    select AVG(cargo) from pedidos

Índice

VIII.v. HAVING

A continuación del HAVING se escribe una condición lógica donde se hace referencia a las expresiones del SELECT.

Esta condición es evaluada luego de realizarse el agrupamiento de los datos

    select idproveedor, AVG(idproducto) from productos where idproveedor>=5
    group by 1
    having AVG(idproducto)>58

La única restricción es que la expresión debe citarse tal cual se encuentra en el SELECT

INCORRECTO:

    select idproveedor, AVG(idproducto) from productos p group by 1 having AVG(p.idproducto) >58

No es correcto ya que 'AVG(idproducto)' no es igual a 'AVG(p.idproducto)'

Índice

VIII.vi. ORDER BY

A continuación del ORDER BY se lista los números de expresiones por las que se realizan el ordenamiento.

Todos los números listados deben corresponde a un número de expresión del SELECT, los números no deben repetirse.

Ordenamiento simple

    Select pais, ciudad from empleados order by 1

Ordenamiento multiple

    Select pais, ciudad from empleados order by 1,2

Adicionalmente se puede agregar a cada número de expresión ASD o DESC para indicar el orden ascendente o descendente respectivamente, el ordenamiento por defecto es ascendente.

    Select pais, ciudad from empleados
    order by 1 desc, 2 asc

Índice

VIII.vii. DISTINCT

Opcionalmente luego del SELECT puede indicarse la cláusula DISTINCT, esto indica que deben devolverse los registros sin repetir los grupos de valores.

    Select distinct pais from empleados

Devuelve los valores del campo país

    Select distinct pais, ciudad from empleados

Devuelve todos los valores posibles de la dupla (país, ciudad) encontrado en la tabla empleados.

Índice

VIII.viii. LIMIT

Opcionalmente al final de la sentencia SQL puede usarse la cláusula LIMIT para limitar la cantidad de registros resultantes, evitando una consulta muy extensa.

A continuación de LIMIT se escribe el número de registros máximos a devolver.

    Select nombre from empleados limit 5

La cláusula LIMIT termina la consulta una vez llegado a la cantidad de registros encontrados, por lo que puede entrar en conflicto con la cláusula GROUP BY devolviendo resultados inexactos en las funciones de agrupación.

Por ejemplo:
Suponiendo las siguientes ciudades de los empleados:
IdEmpleadoCiudad
0 Seattle
1 Tacoma
2 Kirkland
3 Redmond
4 Londres
5 Londres
6 Seattle
7 Londres
8 Londres

    Select ciudad, COUNT('*') from empleados
    group by 1 limit 5

Devolverá:
Reg. ciudad COUNT
0 Seattle 1
1 Tacoma 1
2 Kirkland 1
3 Redmond 1
4 Londres 1
Ya que al encontrar la quinta ciudad distinta termina la consulta, cuando el resultado correcto sería:
    Select ciudad, COUNT('*') from empleados
    group by 1

Reg. ciudad COUNT
0 Seattle 2
1 Tacoma 1
2 Kirkland 1
3 Redmond 1
4 Londres 4
No es aconsejable el uso de LIMIT en consultas donde se utiliza GROUP BY

Índice

IX. Uso de Índices

Para el uso de índices se busca en la condición del WHERE expresiones del tipo campo=='valor', luego si el campo mencionado posee un índice se obtiene la lista de registros de la tabla asociados a dicho valor.

En caso de que todos los operadores utilizados sean && (AND) para todas las expresiones indexadas de la misma tabla se realiza una intersección en la lista de registros filtrados.

En caso de que exista al menos un operador || (OR) el listado de registros a filtrar es la unión de los listados de los valores buscados.

Como se vio anteriormente, la condición del WHERE se evalúa en un único paso, lo que permite gran flexibilidad en la escritura de la sentencia SQL ya que permite el uso de funciones propias de JavaScript o bien definidas externamente por el usuario.

Al no limitar el uso de funciones no se puede realizar un parseo exhaustivo de la condición del WHERE. Esto hace imposible afirmar la exactitud de un resultado, al utilizar un índice, en todo el universo posible de consultas.

Por ejemplo suponiendo que se quiere evaluar la siguiente condición del WHERE

    (nombre=='juan') || true

En este caso la evaluación siempre seria verdadera, pero serian equívoco utilizar un índice y restringir la búsqueda a aquellos registros donde el campo nombre sea igual a 'juan'.

Las condiciones pueden ser tan complejas como se deseen haciendo imposible determinar con exactitud en que momento debe utilizarse los índices.

Por este motivo el motor JSSQL permite el uso de índices para reducir el número de iteraciones y de evaluaciones, pero esta funcionalidad debe ser habilitada mediante la propiedad useIndex.

Al habilitar el uso de índices se asume que la condición del WHERE sigue las premisas que se detallan a continuación.

Definamos los siguientes términos:

Subconsultas: una expresión lógica elemental, que tiene como resultado un valor true o false
Ejemplos:

    nombre=='juan'
    costo ==12
    costo>= 12
    EsHombre()

(suponiendo que EsHombre() es una función que devuelve true o false)

Subconsulta indexada: Es una subconsultas que asocia un campo de una tabla a un valor y dicho campo esta indexado.
Ejemplos:
Actualmente las únicas subconsultas indexadas son las que tienen la forma campo=='valor', donde campo es un campo indexado.

    nombre=='juan'
    costo ==12

Llamemos Ai a las subconsultas indexadas asociadas a la tabla A, Es decir

A1 es equivalente a

TablaA.Campo1==Valor1
(Donde campo1 esta indexado)

Y F() a cualquier subconsulta no indexada, ya sea una función o comparación sobre la cual no se utiliza índice alguno

Subconsultas Excluyentes: son aquellas expresiones lógicas elementales que de ser falsas hacen falsa toda la consulta sin importar los valores que toman las demás subconsultas. Ejemplos:
(Vale aclarar que el operador && corresponde al operador AND y el operador || corresponde al operador OR)
Dada la consulta
A1 && A2 && B2 && F() && (C2 || C3 )
A1, A2 , B2 y F() son excluyentes, C2 y C3 no lo son

Subconsultas Determinantes: Son aquellas expresiones lógicas elementales que, de ser verdaderas, hacen verdaderas toda la consulta sin importar los valores que toman las demás subconsultas.
Ejemplos:
Dada la consulta
A1 || B2 || F() || ( C2 && C3 ) A1, B2 y F() son determinantes , C2 y C3 no lo son

Podemos afirmar que el resultado de la consulta será exacto si cumple con alguna de las siguientes pautas:

  • No utiliza ninguna subconsultas indexada.
    En este caso no se utiliza los índices.
  • Todas las subconsultas son excluyentes
    Por ejemplo:
    A1 && A2 && B1 && F()
  • Por cada subconsulta indexada no excluyente hay una subconsulta indexada excluyente asociada a la misma tabla.
    Por ejemplo:
    A1 && ( A2 || F() )
    A2 es no excluyente pero esta asociada a la misma tabla que A1

    A1 && B1 && ( A2 || B2 || F() )
    A2 es no excluyente pero esta asociada a la misma tabla que A1
    B2 es no excluyente pero esta asociada a la misma tabla que B1

  • Hay al menos una subconsulta indexada determinante y todas las demás subconsultas indexadas están asociadas a la misma tabla. Y además no hay subconsultas no indexadas determinantes (F() determinantes).
    Por ejemplo:
    A1 || A2 || A3
    Son todas determinantes asociadas a la misma tabla

    A1 || ( A2 && A3 && F() )
    A2 y A3 son no determinantes asociadas a la misma tabla que A1,F() es no determinante.

Otros casos donde son validas:

F() && ( A1 || A2 ) && ( B1 || B2 ) && ( A3 || B3 )

Esto es válido porque: (A1 || A2 ) pueden verse como una subconsulta indexada asociada a la tabla A que es excluyente (B1 || B2 ) pueden verse como una subconsulta indexada asociada a la tabla B que es excluyente A3 y B3 son subconsultas no excluyentes pero asociadas a la misma tabla que una subconsultas excluyente.

Para concluir se muestra algunos ejemplos de casos válidos e inválidos en una base de prueba.

Tabla: Productos
Campo Tipo Indexado
Improducto numeric NO
NombreProducto string NO
Idcategoria numeric SI
IdProveedor numeric SI

Tabla: Proveedores
Campo Tipo Indexado
ImProveedor numeric NO
NombreCompania string NO
Pais string SI

Sea la consulta:

    select A.idproducto, A.nombreproducto, B.idproveedor, B.nombrecompania
    from productos A , proveedores B
    where CONDICION

Condiciones válidas: (se resaltan las subcondiciones indexadas )

    A.IdProveedor == B.IdProveedor

    A.IdProveedor == B.IdProveedor && A.IdProveedor==4

    A.IdCategoria==2 && ( A.IdProveedor==1 || B.pais> "S")

    A.IdCategoria==2 || A.IdProveedor==4

    A.IdProveedor == B.IdProveedor && (A.IdCategoria==2  || A.IdProveedor==4)

Condiciones inválidas

    A.IdCategoria==2 ||  B.IdProveedor==4

    A.IdCategoria==2 || B.pais> "S"

    (A.IdCategoria==2 && A.IdProveedor==1 )  || B.pais> "S"

    A.IdProveedor == B.IdProveedor && (A.IdCategoria==2  ||  B.Pais=='Francia')

Índice

X.Indexado de documentos

En JSSQL se puede utilizar campos del tipo link, esto implica que se asocia un registro a un documento (ya sea de texto, pdf, etc.). Todos los enlaces mencionados deben ser indexados mediante el JSBD_Indexador. Esto permite realizar búsquedas de texto dentro del contenido de los documentos indexados.

Para acceder al contenido de dichos documentos se implementaron las siguientes funciones que pueden utilizarse dentro de una consulta SQL

CONTENT( NombreCampo )

Descripcion:
Devuelve el contenido del documento mencionado en el valor del campo del tipo link.

Parámetros:
NombreCampo: el nombre del campo del tipo link

Ejemplo:

    select CONTENT(notas) from empleados

ALL(NombreCampo, ArrayPalabras)

Descripcion:
Devuelve verdadero si encuentra todas las palabras incluidas en ArrayPalabras dentro del documento asociado al registro recorrido del campo NombreCampo

Parámetros:
NombreCampo: el nombre del campo del tipo link
ArrayPalabras: Vector con las palabras a buscar

Ejemplos:

    select CONTENT(notas) from empleados where ALL(notas,['formación','boston'])

ANY(NombreCampo, ArrayPalabras)

Descripcion:
Devuelve verdadero si encuentra alguna de las palabras incluidas en ArrayPalabras dentro del documento asociado al registro recorrido del campo NombreCampo

Parámetros:
NombreCampo: el nombre del campo del tipo link
ArrayPalabras: Vector con las palabras a buscar devuelve verdadero si el numero de registro se encuentra en el listado asociado.

Ejemplos:

    select CONTENT(notas) from empleados where ANY(notas,['licenciatura','formacion'])

EXACT(NombreCampo, Frase [, Estricto ] )

Descripcion:
Devuelve verdadero si encuentra la frase buscada dentro del documento asociado al registro recorrido del campo NombreCampo

Parámetros:
NombreCampo: el nombre del campo del tipo link
Frase: Cadena de texto a buscar dentro del contenido de los documentos
Estricto: Valor booleano que determina si la frase se busca teniendo en cuenta mayusculas y minúsculas y acentos. Es optativo y por defecto es verdadero

Ejemplos:

    select CONTENT(notas) from empleados where EXACT(notas,' ingresó en la empresa')

    select CONTENT(notas) from empleados where EXACT(notas,'Ingreso en la empresa',false)

Las funciones ALL, ANY y EXACT hace uso de los índices invertidos por palabra asociados a los campos del tipo link, por lo que optimizan los tiempos de búsqueda sin leer el contenido de todos los documentos.

En estos índices las palabras se encuentran en mayúsculas y sin acentos, para reducir la cantidad de palabras a indexar.

No se encuentran en el índice palabras que se encuentren en el listado de palabras frecuentes asociadas al campo o aquellas que estén fuera del límite establecido por los parámetros docsMaxLen y docsMinLen.

Índice

XI. Particionado de Tablas

Las tablas de la base JSBD pueden particionarse en porciones pequeñas de datos para evitar el uso excesivo de memoria al utilizar tablas con gran cantidad de registros.

La definición del tamaño de las particiones de las tablas se realiza en el momento de la creación de la JSBD (generalmente mediante el conversor JSBD_Conversor).

El uso de tablas particionadas es totalmente transparente al usuario en el momento de realizar las consultas al motor JSSQL.

Índice