From c126c15eadc4c7482ff5cfcd8703e14765e7fa4c Mon Sep 17 00:00:00 2001
From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com>
Date: Wed, 20 May 2026 20:30:20 -0500
Subject: [PATCH] fix(query-runner): dialecto SQL correcto por tipo de BD en
helpers DBA
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Detecta isPostgres desde tipo_db.nombre al cambiar conexión
- sqlHelpers: getter dinámico — chips distintos para PostgreSQL vs MySQL
PostgreSQL: pg_database, information_schema, pg_stat_activity, pg_indexes
MySQL: SHOW DATABASES/TABLES/USERS/PROCESSLIST/CREATE TABLE
- generateDbHelper: genera SQL correcto por dialecto
PostgreSQL: sin backticks, sin charset, sin @host, DO$$ para CREATE USER IF NOT EXISTS,
GRANT ALL ON DATABASE + SCHEMA + DEFAULT PRIVILEGES
MySQL: backticks, utf8mb4, 'user'@'host', FLUSH PRIVILEGES
- Badge PostgreSQL/MySQL en header del generador DBA
- Campo Host oculto en conexiones PostgreSQL
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
resources/views/query_runner.html | 100 +++++++++++++++++++++---------
1 file changed, 70 insertions(+), 30 deletions(-)
diff --git a/resources/views/query_runner.html b/resources/views/query_runner.html
index 5ed0631..42f7184 100644
--- a/resources/views/query_runner.html
+++ b/resources/views/query_runner.html
@@ -192,6 +192,8 @@
Generador DBA
+ PostgreSQL
+ MySQL
CREATE · GRANT · DROP · Setup
@@ -224,7 +226,7 @@
class="w-full border rounded px-2 py-1 font-mono focus:outline-none focus:ring-1 focus:ring-[#8eb02f]"
placeholder="usuario_app">
-
+
{
testOk: true,
toast: { show: false, msg: '', type: 'ok' },
isMongo: false,
+ isPostgres: false,
selectedCollection: '',
collectionFields: [],
loadingFields: false,
@@ -450,16 +453,29 @@ document.addEventListener('alpine:init', () => {
// SQL DBA helpers
showDbHelper: false,
dbHelper: { db: '', user: '', pass: '', host: '%', op: 'full_setup' },
- sqlHelpers: [
- { label: 'SHOW DATABASES', cmd: 'SHOW DATABASES;' },
- { label: 'SHOW TABLES', cmd: 'SHOW TABLES;' },
- { label: 'SHOW USERS', cmd: "SELECT User, Host, plugin FROM mysql.user ORDER BY User;" },
- { label: 'SHOW GRANTS (actual)',cmd: 'SHOW GRANTS FOR CURRENT_USER;' },
- { label: 'SHOW PROCESSLIST', cmd: 'SHOW FULL PROCESSLIST;' },
- { label: 'SHOW CREATE TABLE', cmd: 'SHOW CREATE TABLE nombre_tabla;' },
- { label: 'DESC tabla', cmd: 'DESCRIBE nombre_tabla;' },
- { label: 'ENGINE/CHARSET', cmd: "SELECT table_name, engine, table_collation FROM information_schema.tables WHERE table_schema = DATABASE();" },
- ],
+ get sqlHelpers() {
+ if (this.isPostgres) return [
+ { label: 'SHOW DATABASES', cmd: 'SELECT datname FROM pg_database ORDER BY datname;' },
+ { label: 'SHOW TABLES', cmd: "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name;" },
+ { label: 'SHOW USERS', cmd: "SELECT usename, usesuper, usecreatedb, usecreaterole FROM pg_catalog.pg_user ORDER BY usename;" },
+ { label: 'SHOW GRANTS', cmd: "SELECT grantee, table_name, privilege_type FROM information_schema.role_table_grants WHERE table_schema = 'public' ORDER BY grantee, table_name;" },
+ { label: 'SHOW CONNECTIONS', cmd: "SELECT pid, usename, application_name, state, query_start, LEFT(query,80) AS query FROM pg_stat_activity WHERE state IS NOT NULL;" },
+ { label: 'DESC tabla', cmd: "SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name = 'nombre_tabla' ORDER BY ordinal_position;" },
+ { label: 'SHOW INDEXES', cmd: "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'nombre_tabla';" },
+ { label: 'SIZE db', cmd: "SELECT pg_size_pretty(pg_database_size(current_database())) AS size;" },
+ ];
+ // MySQL / MariaDB
+ return [
+ { label: 'SHOW DATABASES', cmd: 'SHOW DATABASES;' },
+ { label: 'SHOW TABLES', cmd: 'SHOW TABLES;' },
+ { label: 'SHOW USERS', cmd: "SELECT User, Host, plugin FROM mysql.user ORDER BY User;" },
+ { label: 'SHOW GRANTS', cmd: 'SHOW GRANTS FOR CURRENT_USER;' },
+ { label: 'SHOW PROCESSLIST', cmd: 'SHOW FULL PROCESSLIST;' },
+ { label: 'SHOW CREATE TABLE', cmd: 'SHOW CREATE TABLE nombre_tabla;' },
+ { label: 'DESC tabla', cmd: 'DESCRIBE nombre_tabla;' },
+ { label: 'ENGINE/CHARSET', cmd: "SELECT table_name, engine, table_collation FROM information_schema.tables WHERE table_schema = DATABASE();" },
+ ];
+ },
mongoExamples: [
{ label: 'find()', cmd: 'db.coleccion.find({})' },
{ label: 'findOne()', cmd: 'db.coleccion.findOne({})' },
@@ -502,7 +518,9 @@ document.addEventListener('alpine:init', () => {
this.collectionFields = [];
if (!this.selectedConxId) return;
const conx = this.conexiones.find(c => c.ID == this.selectedConxId);
- this.isMongo = conx?.tipo_db?.nombre?.toLowerCase().includes('mongo') ?? false;
+ const dbType = conx?.tipo_db?.nombre?.toLowerCase() || '';
+ this.isMongo = dbType.includes('mongo');
+ this.isPostgres = dbType.includes('postgres');
try {
const res = await axios.get('/app/query-runner/databases?conx_db_id=' + this.selectedConxId);
this.databases = res.data.data || [];
@@ -699,25 +717,47 @@ document.addEventListener('alpine:init', () => {
const user = this.dbHelper.user || 'usuario_app';
const host = this.dbHelper.host || '%';
const pass = this.dbHelper.pass || 'Contraseña123!';
+ let map;
- const createDb = `CREATE DATABASE IF NOT EXISTS \`${db}\`\n CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`;
- const createUser = `CREATE USER IF NOT EXISTS '${user}'@'${host}' IDENTIFIED BY '${pass}';`;
- const grant = `GRANT ALL PRIVILEGES ON \`${db}\`.* TO '${user}'@'${host}';\nFLUSH PRIVILEGES;`;
- const revoke = `REVOKE ALL PRIVILEGES ON \`${db}\`.* FROM '${user}'@'${host}';\nFLUSH PRIVILEGES;`;
- const showGrants = `SHOW GRANTS FOR '${user}'@'${host}';`;
- const dropUser = `DROP USER IF EXISTS '${user}'@'${host}';\nFLUSH PRIVILEGES;`;
- const dropDb = `DROP DATABASE IF EXISTS \`${db}\`;`;
-
- const map = {
- full_setup: `-- 1. Crear base de datos\n${createDb}\n\n-- 2. Crear usuario\n${createUser}\n\n-- 3. Dar permisos totales\n${grant}`,
- create_db: createDb,
- create_user: createUser,
- grant: grant,
- revoke: revoke,
- show_grants: showGrants,
- drop_user: dropUser,
- drop_db: dropDb,
- };
+ if (this.isPostgres) {
+ // ── PostgreSQL ──────────────────────────────────────────────
+ const createDb = `CREATE DATABASE "${db}"\n WITH ENCODING 'UTF8'\n LC_COLLATE = 'en_US.UTF-8'\n LC_CTYPE = 'en_US.UTF-8'\n TEMPLATE = template0;`;
+ const createUser = `DO $$\nBEGIN\n IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${user}') THEN\n CREATE USER "${user}" WITH PASSWORD '${pass}';\n END IF;\nEND\n$$;`;
+ const grant = `GRANT ALL PRIVILEGES ON DATABASE "${db}" TO "${user}";\nGRANT ALL ON SCHEMA public TO "${user}";\nALTER DEFAULT PRIVILEGES IN SCHEMA public\n GRANT ALL ON TABLES TO "${user}";\nALTER DEFAULT PRIVILEGES IN SCHEMA public\n GRANT ALL ON SEQUENCES TO "${user}";`;
+ const revoke = `REVOKE ALL PRIVILEGES ON DATABASE "${db}" FROM "${user}";\nREVOKE ALL ON SCHEMA public FROM "${user}";`;
+ const showGrants = `SELECT grantee, privilege_type, table_name\nFROM information_schema.role_table_grants\nWHERE grantee = '${user}'\nORDER BY table_name;`;
+ const dropUser = `DROP USER IF EXISTS "${user}";`;
+ const dropDb = `DROP DATABASE IF EXISTS "${db}";`;
+ map = {
+ full_setup: `-- 1. Crear base de datos\n${createDb}\n\n-- 2. Crear usuario (si no existe)\n${createUser}\n\n-- 3. Dar permisos totales\n${grant}`,
+ create_db: createDb,
+ create_user: createUser,
+ grant: grant,
+ revoke: revoke,
+ show_grants: showGrants,
+ drop_user: dropUser,
+ drop_db: dropDb,
+ };
+ } else {
+ // ── MySQL / MariaDB ─────────────────────────────────────────
+ const createDb = `CREATE DATABASE IF NOT EXISTS \`${db}\`\n CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`;
+ const createUser = `CREATE USER IF NOT EXISTS '${user}'@'${host}' IDENTIFIED BY '${pass}';`;
+ const grant = `GRANT ALL PRIVILEGES ON \`${db}\`.* TO '${user}'@'${host}';\nFLUSH PRIVILEGES;`;
+ const revoke = `REVOKE ALL PRIVILEGES ON \`${db}\`.* FROM '${user}'@'${host}';\nFLUSH PRIVILEGES;`;
+ const showGrants = `SHOW GRANTS FOR '${user}'@'${host}';`;
+ const dropUser = `DROP USER IF EXISTS '${user}'@'${host}';\nFLUSH PRIVILEGES;`;
+ const dropDb = `DROP DATABASE IF EXISTS \`${db}\`;`;
+ map = {
+ full_setup: `-- 1. Crear base de datos\n${createDb}\n\n-- 2. Crear usuario\n${createUser}\n\n-- 3. Dar permisos totales\n${grant}`,
+ create_db: createDb,
+ create_user: createUser,
+ grant: grant,
+ revoke: revoke,
+ show_grants: showGrants,
+ drop_user: dropUser,
+ drop_db: dropDb,
+ };
+ }
this.sqlText = map[this.dbHelper.op] || '';
document.getElementById('sql-editor')?.focus();