SQLSelectItem en Apache Druid: Clase para Manejar Elementos de Selección SQL

SQLSelectItem es una clase final en el framework Apache Druid que representa un elemento en la lista de selección de una consulta SQL. Esta clase es esencial para el aálisis de consultas, ya que encapsula la expresión de selección y su alias opcional. En esta guía, exploramos su estructura, atributos, métodos y ejemplos prácticos para su uso en aplicaciones Java.

  1. Jerarquía de Clases

La clase SQLSelectItem pertenece a un árbol de herencia simple en Druid 1.2.x:

SQLObject (interfaz principal)
 ↑
SQLObjectImpl (clase abstracta base)
 ↑
SQLSelectItem (clase concreta, sin subclases)

SQLSelectItem es una clase concreta sin derivaciones; toda la variabilidad reside en el atributo SQLExpr expr que contiene.

  1. Estructura Principal

La definición de la clase incluye los siguientes atributos clave:

public class SQLSelectItem extends SQLObjectImpl {
    private SQLExpr expr;        // Expresión de selección (campo, función, constante, etc.)
    private String alias;        // Alias definido con AS
    private boolean connectBy;   // Marcador para consultas jerárquicas en Oracle
    // Otros métodos y atributos internos
}
  1. Atributos Detallados

  • expr: De tipo SQLExpr, representa la expresión principal (ejemplo: id, COUNT(*), a + b).
  • alias: Cadena que almacena el alias asignado (ejemplo: nombreUsuario).
  • connectBy: Booleano para soporte de consultas CONNECT BY en Oracle.
  • parent: Referencia al nodo padre en el árbol de sintaxis abstracta (AST).

El tipo de expr determina el comportamiento del elemento de selección. Las subclases comunes de SQLExpr incluyen:

  • SQLIdentifierExpr: Para campos simples (ejemplo: nombre).
  • SQLPropertyExpr: Para campos con alias de tabla (ejemplo: usuario.id).
  • SQLMethodInvokeExpr: Para funciones SQL (ejemplo: MAX(edad)).
  • SQLBinaryOpExpr: Para operaciones binarias (ejemplo: precio * cantidad).
  • SQLSubqueryExpr: Para subconsultas (ejemplo: SELECT id FROM otra_tabla).
  1. Métodos Principales

Los constructores y métodos más utilizados son:

// Constructores
new SQLSelectItem()                          // Vacío
new SQLSelectItem(SQLExpr expresion)         // Solo expresión
new SQLSelectItem(SQLExpr expresion, String apodo) // Expresión con alias

// Getters y Setters comunes
SQLExpr obtenerExpresion()
void establecerExpresion(SQLExpr expresion)
String obtenerAlias()
void establecerAlias(String apodo)
SQLIdentifierExpr obtenerAliasExpr()         // Para uso interno con SQLIdentifierExpr
void establecerAliasExpr(SQLIdentifierExpr aliasExpr)

// Métodos utilitarios
String toString()                            // Conversión a cadena SQL
void aceptar(SQLASTVisitor visitante)        // Para recorrido con visitor
SQLSelectItem clonar()                       // Clonación del objeto
  1. Ejemplo Práctico: Analizar Campos Simples

Consideremos una consulta SQL básica y cómo extraer información de los elementos de selección:

// Consulta SQL de ejemplo
String consultaSQL = "SELECT identificador, nombre_completo AS nombre_usuario FROM tabla_usuarios";

// Parsear la consulta usando Druid
SQLStatement declaracion = SQLUtils.parseSingleStatement(consultaSQL, JdbcConstants.MYSQL);
SQLSelectStatement declaracionSelect = (SQLSelectStatement) declaracion;
SQLSelectQueryBlock bloqueConsulta = declaracionSelect.getSelect().getQueryBlock();

// Iterar sobre los elementos de selección
for (SQLSelectItem elemento : bloqueConsulta.getSelectList()) {
    System.out.println("=== Elemento de Selección ===");
    System.out.println("Alias: " + elemento.getAlias());

    SQLExpr expresion = elemento.getExpr();
    if (expresion instanceof SQLIdentifierExpr) {
        SQLIdentifierExpr identificador = (SQLIdentifierExpr) expresion;
        System.out.println("Campo simple: " + identificador.getName());
    }
}

Este código imprimirá los campos y sus alias, mostrando cómo identificar expresiones simples.

  1. Ejemplo: Campos con Alias de Tabla

Para campos que incluyen un prefijo de tabla, como en consultas con joins:

String consultaSQL = "SELECT u.identificador, d.descripcion FROM usuarios u JOIN departamentos d";

// Usar el mismo bloque de consulta anterior
for (SQLSelectItem elemento : bloqueConsulta.getSelectList()) {
    SQLExpr expresion = elemento.getExpr();
    if (expresion instanceof SQLPropertyExpr) {
        SQLPropertyExpr propiedad = (SQLPropertyExpr) expresion;
        System.out.println("Tabla: " + propiedad.getOwnerName());
        System.out.println("Campo: " + propiedad.getName());
    }
}

Aquí se extrae el nombre de la tabla y el campo a partir de la expresión de propiedad.

  1. Ejemplo: Funciones de Agregación

Las funciones SQL como COUNT o SUM se representan con SQLMethodInvokeExpr:

String consultaSQL = "SELECT COUNT(*) AS total, SUM(monto) AS suma_montos FROM ventas";

for (SQLSelectItem elemento : bloqueConsulta.getSelectList()) {
    SQLExpr expresion = elemento.getExpr();
    if (expresion instanceof SQLMethodInvokeExpr) {
        SQLMethodInvokeExpr funcion = (SQLMethodInvokeExpr) expresion;
        System.out.println("Función: " + funcion.getMethodName());
        System.out.println("Número de parámetros: " + funcion.getArguments().size());
    }
}

Este ejemplo demuestra cómo identificar y extraer detalles de funciones en la selección.

  1. Recorrido con Visitor Pattern

Para un aálisis más flexible, se puede usar un adaptador de visitor para recorrer todos los SQLSelectItem en una consulta:

// Definir un visitor personalizado
public class AnalizadorElementosSeleccion extends SQLASTVisitorAdapter {
    @Override
    public boolean visit(SQLSelectItem item) {
        System.out.println("\n=== Elemento de Selección ===");
        System.out.println("Alias: " + item.getAlias());
        System.out.println("Expresión: " + item.getExpr());

        SQLExpr expr = item.getExpr();
        if (expr instanceof SQLIdentifierExpr) {
            System.out.println("Tipo: Campo simple → " + ((SQLIdentifierExpr) expr).getName());
        } else if (expr instanceof SQLPropertyExpr) {
            SQLPropertyExpr prop = (SQLPropertyExpr) expr;
            System.out.println("Tipo: Campo con tabla → " + prop.getOwnerName() + "." + prop.getName());
        } else if (expr instanceof SQLMethodInvokeExpr) {
            System.out.println("Tipo: Función → " + ((SQLMethodInvokeExpr) expr).getMethodName());
        }
        return true;
    }
}

// Aplicar el visitor a una declaración SQL
declaracion.accept(new AnalizadorElementosSeleccion());

Este patrón facilita el procesamiento modular de elementos de selección en consultas complejas.

Etiquetas: Druid sql-parser java AST sql-select

Publicado el 7-27 05:57