Index: tol/stdlib/data/db/engine/_constants.tol
===================================================================
--- tol/stdlib/data/db/engine/_constants.tol	(revision 3d69c4da7468b912cd55b6e525c188d168f6f805)
+++ tol/stdlib/data/db/engine/_constants.tol	(revision 3d69c4da7468b912cd55b6e525c188d168f6f805)
@@ -0,0 +1,53 @@
+//////////////////////////////////////////////////////////////////////////////
+// FILE    : _constants.tol
+// PURPOSE : Diversas constantes a organizar para el desglose de sadd en
+//            modulos
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// CONSTANTES DE SQL
+//////////////////////////////////////////////////////////////////////////////
+
+Real GesMic = 0;
+Real GesOra = 1;
+Real GesMys = 2;
+Real GesAcc = 3;
+Real GesPos = 4;
+Real GesTer = 5;
+Real GesRed = 6;
+
+Real GesAct = If(ObjectExist("Text", "DBA"),
+Case
+(
+  DBA == "SqlServer", GesMic,
+  DBA == "Oracle",    GesOra,
+  DBA == "MySql",     GesMys,
+  DBA == "Teradata",  GesTer, 
+  DBA == "PostgreSQL",  GesPos, 
+  TRUE,
+  {
+    WriteLn("common/functions/sql/_constants.tol\n"+
+            " No existe gestor conocido!", "E");
+    -1
+  }
+), 
+{
+  WriteLn("common/functions/sql/_constants.tol\n"+
+          " No hay definido gestor!", "W");
+  -1
+});
+Real NumLotIns = 500;
+
+//Text WriteLn("La variable SqlTra, debe estar en definition.tol");
+Real If(ObjectExist("Real", "SqlTra"), SqlTra, SqlTra = Copy(FALSE));
+PutDescription("Controla la traza de las queries de las funciones
+SqlDB*",
+SqlTra);
+
+Real SqlExec = Copy(TRUE);
+PutDescription("Controla la ejecucion de las queries de la funcion
+SqlDBExecQuery",
+SqlExec);
+
+
+
Index: tol/stdlib/data/db/engine/_ini_engine.tol
===================================================================
--- tol/stdlib/data/db/engine/_ini_engine.tol	(revision 374ca56c5b238e9fcd132e22c929166bfafda68d)
+++ tol/stdlib/data/db/engine/_ini_engine.tol	(revision 3d69c4da7468b912cd55b6e525c188d168f6f805)
@@ -10,4 +10,5 @@
   Set _SqlEngine =
   [[
+    Set Include("_constants.tol");
     Set Include("_sqltools.tol");
     Set Include("_sqlpos.tol");
@@ -15,4 +16,5 @@
     Set Include("_sqlmic.tol");
     Set Include("_sqlmys.tol");
+    Set Include("_sqlred.tol");
     Set Include("_sqlter.tol");
     //Set Include("_sqlacc.tol");
Index: tol/stdlib/data/db/engine/_sql.tol
===================================================================
--- tol/stdlib/data/db/engine/_sql.tol	(revision 374ca56c5b238e9fcd132e22c929166bfafda68d)
+++ tol/stdlib/data/db/engine/_sql.tol	(revision 3d69c4da7468b912cd55b6e525c188d168f6f805)
@@ -85,13 +85,4 @@
 };
 
-//////////////////////////////////////////////////////////////////////////////
-// CONSTANTS
-//////////////////////////////////////////////////////////////////////////////
-Real GesMic = 0;
-Real GesOra = 1;
-Real GesMys = 2;
-Real GesAcc = 3;
-Real GesPos = 4;
-Real GesTer = 5;
 
 //////////////////////////////////////////////////////////////////////////////
@@ -181,4 +172,5 @@
     EQ(gestor, GesOra), [[ "", "||" ]],
     EQ(gestor, GesMys), [[ "concat", "," ]],
+    EQ(gestor, GesRed), [[ "concat", "," ]],
     EQ(gestor, GesPos), [[ "", "||" ]], 
     EQ(gestor, GesAcc), [[ "", "&" ]]
@@ -200,4 +192,5 @@
     EQ(gestor, GesOra), "nvl",
     EQ(gestor, GesMys), "IfNull", 
+    EQ(gestor, GesRed), "IfNull", 
     EQ(gestor, GesPos), "coalesce",
     EQ(gestor, GesTer), "coalesce",
@@ -443,4 +436,5 @@
     EQ(gestor, GesPos), "cast("+ txt +" as char varying)",
     EQ(gestor, GesTer), "rtrim(cast("+ txt +" as char(255)))",    
+    EQ(gestor, GesRed), "trim(string("+ txt +"))",    
     EQ(gestor, GesAcc), "SqlConvertText. Access. Opción por implementar."
   );
@@ -578,4 +572,5 @@
     EQ(gestor, GesPos), "Pos",
     EQ(gestor, GesTer), "Ter",
+    EQ(gestor, GesRed), "Red",
     True, ""
   );
Index: tol/stdlib/data/db/engine/_sqlred.tol
===================================================================
--- tol/stdlib/data/db/engine/_sqlred.tol	(revision 3d69c4da7468b912cd55b6e525c188d168f6f805)
+++ tol/stdlib/data/db/engine/_sqlred.tol	(revision 3d69c4da7468b912cd55b6e525c188d168f6f805)
@@ -0,0 +1,584 @@
+//////////////////////////////////////////////////////////////////////////////
+// FILE    : _sqlRed.tol
+// PURPOSE : Funciones propias del gestor Teradata
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
+//////////////////////////////////////////////////////////////////////////////
+
+Text SqlRedFormatRealTol2Sql = "%.5lf";
+Date SqlRedDefaultTheBegin   = y1990m01d01h00i00s00;
+Date SqlRedDefaultTheEnd     = Succ(Now, Daily, 365*3+366);
+
+//////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedFormatDate(Date dte)
+//////////////////////////////////////////////////////////////////////////////
+{
+  Date dteAux = 
+   If(dte == TheBegin, SqlRedDefaultTheBegin,
+   If(dte == TheEnd,   SqlRedDefaultTheEnd, dte));
+
+  Text formatDate = FormatDate(dteAux, "%c%Y-%m-%d%u %h:%i:%s");
+  Real longfd     = TextLength(formatDate);
+  Text sqlFormat  = Case
+  (
+    EQ(longfd, 10), "%c%Y-%m-%d",
+    True          , "%c%Y-%m-%d %h:%i:%s"
+  );
+  Text expr = Case(
+    EQ(longfd, 10), "date('"+ FormatDate(dteAux, sqlFormat)+ "')",
+    1,              "timestamp('"+ FormatDate(dteAux, sqlFormat)+ "')"
+  )
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Formateador de fecha con formato dependiente del de TOL al formato 
+equivalente Teradata.",
+SqlRedFormatDate);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedFormatReal(Real rea)
+//////////////////////////////////////////////////////////////////////////////
+{
+  Real isUnk = IsUnknown(rea);
+  Real isInf = IsInfinite(rea);
+  If(Or(isUnk, isInf), "null", 
+   FormatReal(rea,SqlRedFormatRealTol2Sql))
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Formateador de reales TOL a formato real de Teradata.",
+SqlRedFormatReal);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedFormatInteger(Real rea)
+//////////////////////////////////////////////////////////////////////////////
+{
+  Real isUnk = IsUnknown(rea);
+  Real isInf = IsInfinite(rea);
+  If(Or(isUnk, isInf), "null", IntText(rea))
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Formateador de reales TOL a formato entero de Teradata. Si el numero no es 
+entero lo redondea.",
+SqlRedFormatInteger);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedFormatText(Text txt)
+//////////////////////////////////////////////////////////////////////////////
+{ If(txt == "", "null","'"+Replace(txt, "'", "''")+"'") };
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Formateador de text a char de Teradata",
+SqlRedFormatText);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedFormatPolyn(Polyn pol)
+//////////////////////////////////////////////////////////////////////////////
+{ 
+  If(IsUnknownPolyn(pol), "null", "'"+FormatPolyn(pol)+"'") 
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Formateador de polyn a char de Teradata",
+SqlRedFormatPolyn);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Set SqlRedInfoColumns(Text tabla)
+//////////////////////////////////////////////////////////////////////////////
+{ 
+  // query
+
+  Text strSql =
+"
+    SELECT UPPER(pg_class.relname) AS Table_, 
+           UPPER(pg_attribute.attname) AS Column_, 
+           UPPER(pg_type.typname) AS Type_,
+           CASE WHEN 
+             pg_type.typname = 'varchar' 
+           THEN
+             (pg_attribute.atttypmod - 
+               (pg_attribute.atttypmod / 65536) * 65536 - 
+              4)
+           ELSE
+             CASE WHEN 
+               pg_type.typname = 'date' 
+             THEN
+               4
+             ELSE
+               CASE WHEN 
+                 pg_type.typname = 'time' OR pg_type.typname = 'timestamp' 
+               THEN
+                 8
+               ELSE
+                 (pg_attribute.atttypmod / 65536) 
+               END
+             END
+           END AS Length_,
+           CASE WHEN 
+             pg_type.typname = 'numeric' 
+           THEN
+             (pg_attribute.atttypmod / 65536) 
+           ELSE
+             null
+           END AS Precision_,
+           CASE WHEN 
+             pg_type.typname = 'numeric'
+           THEN
+             (pg_attribute.atttypmod - 
+               (pg_attribute.atttypmod / 65536) * 65536 - 
+              4) 
+           ELSE 
+             null
+           END AS Scale_,
+           CASE WHEN 
+             pg_attribute.attnotnull = 't'
+           THEN 
+             0 
+           ELSE
+             1
+           END AS IsNull_,
+           CASE WHEN
+             (SELECT COUNT(*) > 0
+                FROM pg_class Cla, pg_constraint Con, pg_attribute Att
+               WHERE Cla.oid          = Con.conrelid 
+                 AND Con.contype      = 'p'
+                 AND Cla.relname      = pg_class.relname
+                 AND Att.attname      = pg_attribute.attname
+                 AND Cla.oid          = Att.attrelid
+                 AND Att.attnum       = ANY(Con.conkey)
+                 AND Att.attisdropped = 'f'
+                 AND Att.attnum       > 0) = 't'
+           THEN
+             1
+           ELSE
+             0
+           END AS IsKey_
+      FROM pg_class, pg_attribute, pg_type
+     WHERE pg_class.oid              = pg_attribute.attrelid 
+       AND pg_attribute.attisdropped = 'f' 
+       AND pg_attribute.attnum       > 0
+       AND UPPER(pg_class.relname)   = UPPER('"+tabla+"') 
+       AND pg_attribute.atttypid     = pg_type.oid 
+  ORDER BY pg_attribute.attnum
+";
+  Set info = SqlDBTable(strSql, "StSqlInfoColums");
+  info
+
+//  Empty
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Información de los campos de una tabla de Poscle",
+SqlRedInfoColumns);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Set SqlRedInfoKeys(Text tabla)
+//////////////////////////////////////////////////////////////////////////////
+{ 
+  // query
+  Text strSql =
+"
+select Cl.RelName     as Table_,
+       ic.conname     as Index_,
+       Atr.attname    as Column_
+from  pg_constraint ic, pg_attribute Atr,pg_class     Cl
+where ic.conrelid = Cl.oid
+and   Atr.attnum = Any(ic.conkey)
+and   ic.contype='p'
+
+and upper(Cl.RelName) = upper('"+tabla+"')*/
+order by Atr.attnum
+";
+  Set info = SqlDBTable(strSql, "StSqlInfoKeys");
+  info;
+  Empty
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Información de los campos clave de una tabla de Poscle",
+SqlRedInfoKeys);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Set SqlRedInfoForeign(Text tabla)
+//////////////////////////////////////////////////////////////////////////////
+{ 
+  // query
+  Text strSql =
+"
+
+select Cl.RelName          as Table_,
+       ic.conname          as Index_,
+       Atr.attname         as Column_,
+       Cl2.RelName         as ForeignTable_,
+       ic2.conname         as ForeignIndex_,
+       Atr2.attname        as ForeignColumn_
+from  pg_constraint ic, pg_constraint ic2,
+      pg_attribute Atr, pg_attribute Atr2,
+      pg_class     Cl,  pg_class     Cl2
+where ic.oid   <>             ic2.oid
+  and ic.conrelid          = Cl.oid
+  and ic2.conrelid         = Cl2.oid
+  and cl.relowner          = cl2.relowner
+  and ic.contype          = 'p'
+   and ic2.contype          = 'f'
+  and   Atr.attnum        = Any(ic.conkey)
+  and   Atr2.attnum       = Any(ic2.conkey)
+  and   Cl.Oid             = Atr.attrelid
+  and    Atr.attrelid      <> atr2.attrelid
+and   UPPER(Cl.RelName) = UPPER('"+tabla+"')
+order by  ic.conname , Atr.attnum
+";
+  Set info = SqlDBTable(strSql, "StSqlInfoForeing");
+  info;
+  Empty
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Información de las relacciones externas de una tabla de Poscle",
+SqlRedInfoForeign);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Set SqlRedInfoDependent(Anything tabla)
+//////////////////////////////////////////////////////////////////////////////
+{ 
+  Text gramTabla = Grammar(tabla);
+  // informacion de los campos claves
+  Text txtWhe = Case(
+    gramTabla == "Text", " upper(Cl2.RelName) = upper('"+tabla+"') ",
+    gramTabla == "Set",
+    {
+      Set lstWhe = EvalSet(tabla, Text (Set set)
+      {
+         Text " ( upper(Cl2.RelName) = upper('"+set->Table+"') 
+                  and upper(ic2.conname) = upper('"+set->Column+"'))"
+      });
+      Text TxtListItem (lstWhe, " or "+NL)
+    }, 
+    "",
+    {
+      WriteLn("ERROR: SqlRedInfoDependent\n"+
+              "Gramatica '"+ gramTabla +"' desconocida!");
+      " = '"<< tabla +"'"
+    }
+  );
+  // query
+  Set info = If(txtWhe == "", Empty,
+  {
+    Text strSql =
+"
+select Cl.RelName          as Table_,
+       ic.conname          as Index_,
+       Atr.attname         as Column_,
+       Cl2.RelName         as ForeignTable_,
+       ic2.conname         as ForeignIndex_,
+       Atr2.attname        as ForeignColumn_
+from  pg_constraint ic, pg_constraint ic2,
+      pg_attribute Atr, pg_attribute Atr2,
+      pg_class     Cl,  pg_class     Cl2
+where ic.oid   <>             ic2.oid
+  and ic.conrelid          = Cl.oid
+  and ic2.conrelid         = Cl2.oid
+  and cl.relowner          = cl2.relowner
+  and ic.contype          = 'p'
+   and ic2.contype          = 'f'
+  and   Atr.attnum        = Any(ic.conkey)
+  and   Atr2.attnum       = Any(ic2.conkey)
+  and   Cl.Oid             = Atr.attrelid
+  and    Atr.attrelid      <> atr2.attrelid
+and  ("+ txtWhe +")
+order by  ic.conname , Atr.attnum
+";
+    Set info = SqlDBTable(strSql, "StSqlInfoForeing");
+    info
+  })
+
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Información de las tablas que dependen de una tabla dada en Poscle.
+La función puede recibir un Text o un Set.
+Parámetros:
+  tabla -> Text: Nombre de una tabla la Base de Datos
+           Set : Conjunto con la estructura 'StSqlInfoForeing'",
+SqlRedInfoDependent);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Set SqlRedGetDependantTables(Text tabla, Set columns)
+//////////////////////////////////////////////////////////////////////////////
+{
+// informacion de los campos claves
+  Text txtWhe = " upper(Cl2.RelName = upper('"+tabla+"')" + 
+    If(IsEmpty(columns), "",
+    {
+      Set lstWhe = EvalSet(columns, Text (Text col)
+      {
+        Text " ( and upper(ic2.conname) = upper('"+col+"'))"
+      });
+      Text " and (" + TxtListItem (lstWhe, " or "+NL) + ")"
+     });
+  // query
+  Set info = If(txtWhe == "", Empty,
+  {
+    Text strSql =
+"
+select Cl.RelName          as Table_,
+       ic.conname          as Index_,
+       Atr.attname         as Column_,
+       Cl2.RelName         as ForeignTable_,
+       ic2.conname         as ForeignIndex_,
+       Atr2.attname        as ForeignColumn_
+from  pg_constraint ic, pg_constraint ic2,
+      pg_attribute Atr, pg_attribute Atr2,
+      pg_class     Cl,  pg_class     Cl2
+where ic.oid   <>             ic2.oid
+  and ic.conrelid          = Cl.oid
+  and ic2.conrelid         = Cl2.oid
+  and cl.relowner          = cl2.relowner
+  and ic.contype          = 'p'
+   and ic2.contype          = 'f'
+  and   Atr.attnum        = Any(ic.conkey)
+  and   Atr2.attnum       = Any(ic2.conkey)
+  and   Cl.Oid             = Atr.attrelid
+  and    Atr.attrelid      <> atr2.attrelid
+and  ("+ txtWhe +")
+order by  ic.conname , Atr.attnum
+";
+    Set info = SqlDBTable(strSql, "StSqlInfoForeing");
+    info
+  })
+
+
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Información de las tablas que dependen de una tabla dada. La función
+recibe un Text y un Set.
+Parámetros:
+  tabla    -> Text: Nombre de una tabla la Base de Datos
+  columns  -> Set : Conjunto de columnas de las cuales se quiere saber
+              qué claves externas están relacionadas a ella
+  gestor   -> SGBD activo 
+Devuelve un Set de estructuras StSqlInfoForeing 
+  (Text Table, Text Index, Text Column, Text ForeignTable,
+   Text ForeignIndex, Text ForeignColumn)
+",
+SqlRedGetDependantTables);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Set SqlRedInfoDependentAll(Anything tabla)
+//////////////////////////////////////////////////////////////////////////////
+{
+  // query
+  Set sGetTabDep = SqlRedInfoDependent(tabla);
+
+  Set info = If(IsEmpty(sGetTabDep), Empty,
+  {
+    Text gramTabla = Grammar(tabla);
+    Set cnj  = Case(
+      gramTabla == "Text", SetOfText(tabla),
+      gramTabla == "Set", tabla,
+      Empty,
+      {
+        WriteLn("ERROR: SqlRedInfoDependentAll\n"+
+                "Gramatica '"+ gramTabla +"' desconocida!");
+        Empty
+    });
+    sGetTabDep << SqlRedInfoDependentAll(sGetTabDep)
+  })
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription("
+Información de todas las tablas que dependen de una tabla dada en Poscle.
+La función puede recibir un Text o un Set.
+Parámetros:
+  tabla -> Text: Nombre de una tabla la Base de Datos
+           Set : Conjunto con la estructura 'StSqlInfoForeing'
+",
+SqlRedInfoDependentAll);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedForeignEnable(Text tabla, Text restriccion)
+//////////////////////////////////////////////////////////////////////////////
+{
+  WriteLn("<W>SqlRedForeignEnable. Postgres. Work in Progress.</W>");
+  ""
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Sentencia para habilitar una clave ajena dada para Poscle.
+Valida los cambios realizados.
+Parámetros:
+  tabla       -> Nombre de la tabla
+  restriccion -> Nombre de la resticcion
+Devuelve: El texto a ejecutar",
+SqlRedForeignEnable);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedForeignDisable(Text tabla, Text restriccion)
+//////////////////////////////////////////////////////////////////////////////
+{
+  WriteLn("<W>SqlRedForeignDisable. Postgres. Work in Progress.</W>");
+  ""
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"Sentencia para deshabilitar una clave ajena dada para Poscle.
+Valida los cambios realizados.
+Parámetros:
+  tabla       -> Nombre de la tabla
+  restriccion -> Nombre de la resticcion
+Devuelve: El texto a ejecutar",
+SqlRedForeignDisable);
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+Text SqlRedShowTreeTable(Text nombreTabla, Real showSonTables){
+//////////////////////////////////////////////////////////////////////////////
+
+  Set ctoTablasAcum = Copy(Empty);
+
+  Text func_espacios(Real nEspacios, Text txt){
+    Set cto = For(1, nEspacios, Text(Real i){ txt });
+    If(Card(cto),
+      SetSum(cto),
+      "")
+  };
+
+  Text funcion(Text nombreTabla_2, Real numEspacios){
+
+    Text espacios = func_espacios(numEspacios, "|  ");
+
+    Text qry_cols =
+    "
+        SELECT UPPER(pg_attribute.attname)
+          FROM pg_class, pg_attribute
+         WHERE pg_class.oid              = pg_attribute.attrelid 
+           AND UPPER(pg_class.relname)   = UPPER('"+ nombreTabla_2 +"') 
+           AND pg_attribute.attisdropped = 'f' 
+           AND pg_attribute.attnum       > 0
+    ";
+    Set cto_cols = DBTable(qry_cols);
+  
+    Text cols = {
+      Text qry_pk =
+      "
+        SELECT UPPER(pg_attribute.attname)
+          FROM pg_class, pg_constraint, pg_attribute
+         WHERE pg_class.oid              = pg_constraint.conrelid 
+           AND pg_constraint.contype     = 'p'
+           AND UPPER(pg_class.relname)   = UPPER('"+ nombreTabla_2 +"') 
+           AND pg_class.oid              = pg_attribute.attrelid
+           AND pg_attribute.attnum       = ANY(pg_constraint.conkey)
+           AND pg_attribute.attisdropped = 'f'
+           AND pg_attribute.attnum       > 0
+      ";
+      Set cto_pk_temp = DBTable(qry_pk);
+      Set cto_pk = If(Card(cto_pk_temp), 
+        Traspose(cto_pk_temp)[1],
+        Empty
+      );
+
+      Real card = Card(cto_cols);
+      If(card,
+      { Set cto = For(1, card-1, Text(Real i){
+          Text col = cto_cols[i][1];
+          If(col<:cto_pk, FirstToUpper(col, TRUE)+", ",  ToLower(col) +", ")
+        });
+        Text ultimo = {
+          Text col = cto_cols[card][1];
+          If(col<:cto_pk, FirstToUpper(col, TRUE), ToLower(col))
+        };
+
+        "("+ SetSum(cto) + ultimo +")"
+      }," --> ¡¡¡NO EXISTEN restricciones para esta tabla!!!")
+    };
+  
+    Text qry_tablas =
+    If(showSonTables,
+      "
+      SELECT UPPER(ownTable.relname)
+        FROM pg_class ownTable,
+             pg_constraint,
+             pg_class refTable
+       WHERE pg_constraint.contype = 'f'
+         AND ownTable.oid = pg_constraint.conrelid
+         AND pg_constraint.confrelid = refTable.oid
+         AND UPPER(refTable.relname) = UPPER('"+ nombreTabla_2 +"')
+      ",
+      "
+      SELECT UPPER(refTable.relname)
+        FROM pg_class ownTable,
+             pg_constraint,
+             pg_class refTable
+       WHERE pg_constraint.contype = 'f'
+         AND ownTable.oid = pg_constraint.conrelid
+         AND pg_constraint.confrelid = refTable.oid
+         AND UPPER(ownTable.relname) = UPPER('"+ nombreTabla_2 +"')
+      "
+    );
+
+    Set cto_tablas_temp = DBTable(qry_tablas);
+  
+    Set cto_tablas = If(Card(cto_tablas_temp),
+      Traspose(cto_tablas_temp)[1],
+      Empty
+    );
+  
+
+   Real condParada = { 
+     Set cto = EvalSet(cto_tablas, Real(Text tabla){
+         nombreTabla_2 <: ctoTablasAcum
+     });
+     Real r = SetSum(cto);
+     If(IsUnknown(r), 0, r)
+     };
+    
+    Set {ctoTablasAcum := ctoTablasAcum + SetOfText(nombreTabla_2)};
+
+    Text ptosSusp = If(Card(cto_tablas),
+    {
+      Text espaciosVacios = func_espacios(numEspacios + 1, "|  ");
+      "\n"+ espaciosVacios +"· [...]"
+    }, "");
+
+    If(condParada, 
+      ToUpper(nombreTabla_2) + cols + ptosSusp,
+     { 
+       Set cto = EvalSet(cto_tablas, Text(Text tab){
+         "\n"+ espacios + "|  · "+ funcion(tab, numEspacios + 1)
+       });
+       ToUpper(nombreTabla_2) + cols + SetSum(cto)
+     }
+    )
+  };
+
+  funcion(nombreTabla, 0)
+};
+//////////////////////////////////////////////////////////////////////////////
+PutDescription(
+"  Dada una tabla, dibuja un árbol con las tablas que hacen referencia a ella 
+de forma recursiva si 'showSonTables' es TRUE, si no mostrará las
+tablas a las que ésta hace referencia recursivamente.
+  Se muestran también los campos, los que son Primary Key en capital.
+  La expresión '[...]' indica que dicha tabla ya ha sido representada.",
+SqlRedShowTreeTable);
+//////////////////////////////////////////////////////////////////////////////
