]> granicus.if.org Git - postgresql/commitdiff
Jason Davies patch to getImported/getExported keys
authorDave Cramer <davec@fastcrypt.com>
Fri, 9 Nov 2001 02:57:50 +0000 (02:57 +0000)
committerDave Cramer <davec@fastcrypt.com>
Fri, 9 Nov 2001 02:57:50 +0000 (02:57 +0000)
src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java

index 7a22cfd75478ac5be0b76fed842da137638b4668..d4eceb3dbc75597c4518addd69b11264faf66333 100644 (file)
@@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException;
 /**
  * This class provides information about the database as a whole.
  *
- * $Id: DatabaseMetaData.java,v 1.37 2001/11/02 23:50:08 davec Exp $
+ * $Id: DatabaseMetaData.java,v 1.38 2001/11/09 02:57:25 davec Exp $
  *
  * <p>Many of the methods here return lists of information in ResultSets.  You
  * can use the normal ResultSet methods such as getString and getInt to
@@ -2272,72 +2272,117 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
                                                                                                                );
        }
 
-       private void parseConstraint(java.sql.ResultSet keyRelation, Vector tuples) throws SQLException
+        private java.sql.ResultSet getImportedExportedKeys(String catalog, String schema, String primaryTable, String foreignTable) throws SQLException
         {
-           byte tuple[][]=new byte[14][0];
-           for (int k = 0;k < 14;k++)
-               tuple[k] = null;
-           String s=keyRelation.getString(1);
-           int pos=s.indexOf("\\000");
-           if(pos>-1)
-           {
-               tuple[11]=s.substring(0,pos).getBytes();; // FK_NAME
-               int pos2=s.indexOf("\\000", pos+1);
-               if(pos2>-1)
-               {
-                   tuple[2]=s.substring(pos+4, pos2).getBytes();; // PKTABLE_NAME
-                   pos=s.indexOf("\\000", pos2+1);
-                   if(pos>-1)
-                   {
-                       tuple[6]=s.substring(pos2+4, pos).getBytes();; // FKTABLE_NAME
-                       pos=s.indexOf("\\000", pos+1); // Ignore MATCH type 
-                       if(pos>-1)
-                       {
-                           pos2=s.indexOf("\\000",pos+1);
-                           if(pos2>-1)
-                           {
-                               tuple[3]=s.substring(pos+4, pos2).getBytes();; // PKCOLUMN_NAME
-                               pos=s.indexOf("\\000", pos2+1);
-                               if(pos>-1)
-                               {
-                                   tuple[7]=s.substring(pos2+4, pos).getBytes(); //FKCOLUMN_NAME
+           Field f[]=new Field[14];
+
+           f[0]=new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
+           f[1]=new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
+           f[2]=new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
+           f[3]=new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
+           f[4]=new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
+           f[5]=new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
+           f[6]=new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
+           f[7]=new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
+           f[8]=new Field(connection, "KEY_SEQ", iInt2Oid, 2);
+           f[9]=new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
+           f[10]=new Field(connection, "DELETE_RULE", iInt2Oid, 2);
+           f[11]=new Field(connection, "FK_NAME", iVarcharOid, 32);
+           f[12]=new Field(connection, "PK_NAME", iVarcharOid, 32);
+           f[13]=new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
+
+           java.sql.ResultSet rs = connection.ExecSQL("SELECT c.relname,c2.relname,"
+                                                      + "t.tgconstrname,ic.relname,"
+                                                      + "t.tgdeferrable,t.tginitdeferred,"
+                                                      + "t.tgnargs,t.tgargs,p.proname "
+                                                      + "FROM pg_trigger t,pg_class c,pg_class c2,"
+                                                      + "pg_class ic,pg_proc p, pg_index i "
+                                                      + "WHERE t.tgrelid=c.oid AND t.tgconstrrelid=c2.oid "
+                                                      + "AND t.tgfoid=p.oid AND tgisconstraint "
+                                                      + ((primaryTable!=null) ? "AND c2.relname='"+primaryTable+"' " : "")
+                                                      + ((foreignTable!=null) ? "AND c.relname='"+foreignTable+"' " : "")
+                                                      + "AND i.indrelid=c.oid "
+                                                      + "AND i.indexrelid=ic.oid AND i.indisprimary "
+                                                      + "ORDER BY c.relname,c2.relname"
+                                                      );
+           Vector tuples = new Vector();
+           short seq=0;
+           if(rs.next()) {
+               boolean hasMore;
+               do {
+                   byte tuple[][]=new byte[14][0];
+                   for (int k = 0;k < 14;k++)
+                       tuple[k] = null;
+
+                   String fKeyName=rs.getString(3);
+                   boolean foundRule=false;
+                   do {
+                       String proname=rs.getString(9);
+                       if(proname!=null && proname.startsWith("RI_FKey_")) {
+                           int col=-1;
+                           if(proname.endsWith("_upd")) col=9; // UPDATE_RULE
+                           else if(proname.endsWith("_del")) col=10; // DELETE_RULE
+                           if(col>-1) {
+                               String rule=proname.substring(8, proname.length()-4);
+                               int action=importedKeyNoAction;
+                               if("cascade".equals(rule)) action=importedKeyCascade;
+                               else if("setnull".equals(rule)) action=importedKeySetNull;
+                               else if("setdefault".equals(rule)) action=importedKeySetDefault;
+                               tuple[col]=Integer.toString(action).getBytes();
+                               foundRule=true;
+                           }
+                       }
+                   } while((hasMore=rs.next()) && fKeyName.equals(rs.getString(3)));
+
+                   if(foundRule) {
+                       tuple[2]=rs.getBytes(2); //PKTABLE_NAME
+                       tuple[6]=rs.getBytes(1); //FKTABLE_NAME
+
+                       // Parse the tgargs data
+                       StringBuffer fkeyColumns=new StringBuffer();
+                       StringBuffer pkeyColumns=new StringBuffer();
+                       int numColumns=(rs.getInt(7) >> 1) - 2;
+                       String s=rs.getString(8);
+                       int pos=s.lastIndexOf("\\000");
+                       for(int c=0;c<numColumns;c++) {
+                           if(pos>-1) {
+                               int pos2=s.lastIndexOf("\\000", pos-1);
+                               if(pos2>-1) {
+                                   if(fkeyColumns.length()>0) fkeyColumns.insert(0, ',');
+                                   fkeyColumns.insert(0, s.substring(pos2+4, pos)); //FKCOLUMN_NAME
+                                   pos=s.lastIndexOf("\\000", pos2-1);
+                                   if(pos>-1) {
+                                       if(pkeyColumns.length()>0) pkeyColumns.insert(0, ',');
+                                       pkeyColumns.insert(0, s.substring(pos+4, pos2)); //PKCOLUMN_NAME
+                                   }
                                }
                            }
                        }
+                       tuple[7]=fkeyColumns.toString().getBytes(); //FKCOLUMN_NAME
+                       tuple[3]=pkeyColumns.toString().getBytes(); //PKCOLUMN_NAME
+
+                       tuple[8]=Integer.toString(seq++).getBytes(); //KEY_SEQ
+                       tuple[11]=fKeyName.getBytes(); //FK_NAME
+                       tuple[12]=rs.getBytes(4); //PK_NAME
+
+                       // DEFERRABILITY
+                       int deferrability=importedKeyNotDeferrable;
+                       boolean deferrable=rs.getBoolean(5);
+                       boolean initiallyDeferred=rs.getBoolean(6);
+                       if(deferrable) {
+                           if(initiallyDeferred)
+                               deferrability=importedKeyInitiallyDeferred;
+                           else
+                               deferrability=importedKeyInitiallyImmediate;
+                       }
+                       tuple[13]=Integer.toString(deferrability).getBytes();
+
+                       tuples.addElement(tuple);
                    }
-               }
+               } while(hasMore);
            }
 
-           // UPDATE_RULE
-           String rule=keyRelation.getString(2);
-           int action=importedKeyNoAction;
-           if("cascade".equals(rule)) action=importedKeyCascade;
-           else if("setnull".equals(rule)) action=importedKeySetNull;
-           else if("setdefault".equals(rule)) action=importedKeySetDefault;
-           tuple[9]=Integer.toString(action).getBytes();
-
-           // DELETE_RULE
-           rule=keyRelation.getString(3);
-           action=importedKeyNoAction;
-           if("cascade".equals(rule)) action=importedKeyCascade;
-           else if("setnull".equals(rule)) action=importedKeySetNull;
-           else if("setdefault".equals(rule)) action=importedKeySetDefault;
-           tuple[10]=Integer.toString(action).getBytes();
-
-           // DEFERRABILITY
-           int deferrability=importedKeyNotDeferrable;
-           boolean deferrable=keyRelation.getBoolean(4);
-           if(deferrable)
-           {
-               if(keyRelation.getBoolean(5))
-                   deferrability=importedKeyInitiallyDeferred;
-               else
-                   deferrability=importedKeyInitiallyImmediate;
-           }
-           tuple[13]=Integer.toString(deferrability).getBytes();
-           for (int i=0; i< 14; i++){
-               tuples.addElement(tuple[i]);
-           }
+           return new ResultSet(connection, f, tuples, "OK", 1);
        }
 
        /**
@@ -2393,51 +2438,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
         */
         public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException
         {
-                Field f[]=new Field[14];
-
-                f[0]=new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
-                f[1]=new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
-                f[2]=new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
-                f[3]=new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
-                f[4]=new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
-                f[5]=new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
-                f[6]=new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
-                f[7]=new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
-                f[8]=new Field(connection, "KEY_SEQ", iInt2Oid, 2);
-                f[9]=new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
-                f[10]=new Field(connection, "DELETE_RULE", iInt2Oid, 2);
-                f[11]=new Field(connection, "FK_NAME", iVarcharOid, 32);
-                f[12]=new Field(connection, "PK_NAME", iVarcharOid, 32);
-                f[13]=new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
-
-                java.sql.ResultSet rs = connection.ExecSQL("SELECT a.tgargs,"
-                                                           + "substring(a.proname from 9 for (char_length(a.proname)-12)),"
-                                                           + "substring(b.proname from 9 for (char_length(b.proname)-12)),"
-                                                           + "a.tgdeferrable,"
-                                                           + "a.tginitdeferred "
-                                                           + "FROM "
-                                                           + "(SELECT t.tgargs, t.tgconstrname, p.proname, t.tgdeferrable,"
-                                                           + "t.tginitdeferred "
-                                                           + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                           + "WHERE c.relfilenode=t.tgrelid AND t.tgfoid = p.oid "
-                                                           + "AND p.proname LIKE 'RI_FKey_%_upd') as a,"
-                                                           + "(SELECT t.tgconstrname, p.proname "
-                                                           + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                           + "WHERE c.relfilenode=t.tgrelid AND t.tgfoid = p.oid "
-                                                           + "AND p.proname LIKE 'RI_FKey_%_del') as b,"
-                                                           + "(SELECT t.tgconstrname FROM pg_class as c, pg_trigger as t "
-                                                           + "WHERE c.relname like '"+table+"' AND c.relfilenode=t.tgrelid) as c "
-                                                           + "WHERE a.tgconstrname=b.tgconstrname AND a.tgconstrname=c.tgconstrname"
-                                                           );
-                Vector tuples = new Vector();
-
-                while (rs.next())
-                {
-                 
-                  parseConstraint(rs,tuples);
-                }
-
-                return new ResultSet(connection, f, tuples, "OK", 1);
+           return getImportedExportedKeys(catalog, schema, null, table);
         }
 
        /**
@@ -2495,47 +2496,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
         */
        public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException
        {
-               Field f[] = new Field[14];
-
-               f[0] = new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
-               f[1] = new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
-               f[2] = new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
-               f[3] = new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
-               f[4] = new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
-               f[5] = new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
-               f[6] = new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
-               f[7] = new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
-               f[8] = new Field(connection, "KEY_SEQ", iInt2Oid, 2);
-               f[9] = new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
-               f[10] = new Field(connection, "DELETE_RULE", iInt2Oid, 2);
-               f[11] = new Field(connection, "FK_NAME", iVarcharOid, 32);
-               f[12] = new Field(connection, "PK_NAME", iVarcharOid, 32);
-               f[13] = new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
-
-               java.sql.ResultSet rs = connection.ExecSQL("SELECT a.tgargs,"
-                                                          + "substring(a.proname from 9 for (char_length(a.proname)-12)),"
-                                                          + "substring(b.proname from 9 for (char_length(b.proname)-12)),"
-                                                          + "a.tgdeferrable,"
-                                                          + "a.tginitdeferred "
-                                                          + "FROM "
-                                                          + "(SELECT t.tgargs, t.tgconstrname, p.proname,"
-                                                          + "t.tgdeferrable, t.tginitdeferred "
-                                                          + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                          + "WHERE c.relname like '"+table+"' AND c.relfilenode=t.tgrelid "
-                                                          + "AND t.tgfoid = p.oid AND p.proname LIKE 'RI_FKey_%_upd') as a, "
-                                                          + "(SELECT t.tgconstrname, p.proname "
-                                                          + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                          + "WHERE c.relname like '"+table+"' AND c.relfilenode=t.tgrelid "
-                                                          + "AND t.tgfoid = p.oid AND p.proname LIKE 'RI_FKey_%_del') as b "
-                                                          + "WHERE a.tgconstrname=b.tgconstrname");
-               Vector tuples = new Vector();
-
-               while (rs.next())
-               {
-                       parseConstraint(rs,tuples);
-               }
-
-               return new ResultSet(connection, f, tuples, "OK", 1);
+           return getImportedExportedKeys(catalog, schema, table, null);
        }
 
        /**
@@ -2596,7 +2557,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
         */
        public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException
        {
-               throw org.postgresql.Driver.notImplemented();
+           return getImportedExportedKeys(primaryCatalog, primarySchema, primaryTable, foreignTable);
        }
 
        /**
index f546342c0254cfb2a16ea51b71ebb85b7fdcac2e..431823631f2f6d0db09e7a067c2a43902054ad40 100644 (file)
@@ -15,7 +15,7 @@ import org.postgresql.util.PSQLException;
 /**
  * This class provides information about the database as a whole.
  *
- * $Id: DatabaseMetaData.java,v 1.43 2001/11/02 23:51:18 davec Exp $
+ * $Id: DatabaseMetaData.java,v 1.44 2001/11/09 02:57:50 davec Exp $
  *
  * <p>Many of the methods here return lists of information in ResultSets.  You
  * can use the normal ResultSet methods such as getString and getInt to
@@ -2400,71 +2400,118 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
                                                                                                                );
        }
 
-        private byte[][] parseConstraint(java.sql.ResultSet keyRelation) throws SQLException
+        private java.sql.ResultSet getImportedExportedKeys(String catalog, String schema, String primaryTable, String foreignTable) throws SQLException
         {
-          byte tuple[][]=new byte[14][0];
-          for (int k = 0;k < 14;k++)
-            tuple[k] = null;
-          String s=keyRelation.getString(1);
-          int pos=s.indexOf("\\000");
-          if(pos>-1)
-          {
-            tuple[11]=s.substring(0,pos).getBytes();; // FK_NAME
-            int pos2=s.indexOf("\\000", pos+1);
-            if(pos2>-1)
-            {
-              tuple[2]=s.substring(pos+4, pos2).getBytes();; // PKTABLE_NAME
-              pos=s.indexOf("\\000", pos2+1);
-              if(pos>-1)
-              {
-                tuple[6]=s.substring(pos2+4, pos).getBytes();; // FKTABLE_NAME
-                pos=s.indexOf("\\000", pos+1); // Ignore MATCH type
-                if(pos>-1)
-                {
-                  pos2=s.indexOf("\\000",pos+1);
-                  if(pos2>-1)
-                  {
-                    tuple[3]=s.substring(pos+4, pos2).getBytes();; // PKCOLUMN_NAME
-                    pos=s.indexOf("\\000", pos2+1);
-                    if(pos>-1)
-                    {
-                      tuple[7]=s.substring(pos2+4, pos).getBytes(); //FKCOLUMN_NAME
-                    }
-                  }
-                }
-              }
-            }
-          }
-
-          // UPDATE_RULE
-          String rule=keyRelation.getString(2);
-          int action=importedKeyNoAction;
-          if("cascade".equals(rule)) action=importedKeyCascade;
-          else if("setnull".equals(rule)) action=importedKeySetNull;
-          else if("setdefault".equals(rule)) action=importedKeySetDefault;
-          tuple[9]=Integer.toString(action).getBytes();
-
-          // DELETE_RULE
-          rule=keyRelation.getString(3);
-          action=importedKeyNoAction;
-          if("cascade".equals(rule)) action=importedKeyCascade;
-          else if("setnull".equals(rule)) action=importedKeySetNull;
-          else if("setdefault".equals(rule)) action=importedKeySetDefault;
-          tuple[10]=Integer.toString(action).getBytes();
-          // DEFERRABILITY
-          int deferrability=importedKeyNotDeferrable;
-          boolean deferrable=keyRelation.getBoolean(4);
-          if(deferrable)
-          {
-            if(keyRelation.getBoolean(5))
-              deferrability=importedKeyInitiallyDeferred;
-            else
-              deferrability=importedKeyInitiallyImmediate;
-          }
-          tuple[13]=Integer.toString(deferrability).getBytes();
-
-          return tuple;
-        }
+           Field f[]=new Field[14];
+
+           f[0]=new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
+           f[1]=new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
+           f[2]=new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
+           f[3]=new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
+           f[4]=new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
+           f[5]=new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
+           f[6]=new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
+           f[7]=new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
+           f[8]=new Field(connection, "KEY_SEQ", iInt2Oid, 2);
+           f[9]=new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
+           f[10]=new Field(connection, "DELETE_RULE", iInt2Oid, 2);
+           f[11]=new Field(connection, "FK_NAME", iVarcharOid, 32);
+           f[12]=new Field(connection, "PK_NAME", iVarcharOid, 32);
+           f[13]=new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
+
+           java.sql.ResultSet rs = connection.ExecSQL("SELECT c.relname,c2.relname,"
+                                                      + "t.tgconstrname,ic.relname,"
+                                                      + "t.tgdeferrable,t.tginitdeferred,"
+                                                      + "t.tgnargs,t.tgargs,p.proname "
+                                                      + "FROM pg_trigger t,pg_class c,pg_class c2,"
+                                                      + "pg_class ic,pg_proc p, pg_index i "
+                                                      + "WHERE t.tgrelid=c.oid AND t.tgconstrrelid=c2.oid "
+                                                      + "AND t.tgfoid=p.oid AND tgisconstraint "
+                                                      + ((primaryTable!=null) ? "AND c2.relname='"+primaryTable+"' " : "")
+                                                      + ((foreignTable!=null) ? "AND c.relname='"+foreignTable+"' " : "")
+                                                      + "AND i.indrelid=c.oid "
+                                                      + "AND i.indexrelid=ic.oid AND i.indisprimary "
+                                                      + "ORDER BY c.relname,c2.relname"
+                                                      );
+           Vector tuples = new Vector();
+           short seq=0;
+           if(rs.next()) {
+               boolean hasMore;
+               do {
+                   byte tuple[][]=new byte[14][0];
+                   for (int k = 0;k < 14;k++)
+                       tuple[k] = null;
+
+                   String fKeyName=rs.getString(3);
+                   boolean foundRule=false;
+                   do {
+                       String proname=rs.getString(9);
+                       if(proname!=null && proname.startsWith("RI_FKey_")) {
+                           int col=-1;
+                           if(proname.endsWith("_upd")) col=9; // UPDATE_RULE
+                           else if(proname.endsWith("_del")) col=10; // DELETE_RULE
+                           if(col>-1) {
+                               String rule=proname.substring(8, proname.length()-4);
+                               int action=importedKeyNoAction;
+                               if("cascade".equals(rule)) action=importedKeyCascade;
+                               else if("setnull".equals(rule)) action=importedKeySetNull;
+                               else if("setdefault".equals(rule)) action=importedKeySetDefault;
+                               tuple[col]=Integer.toString(action).getBytes();
+                               foundRule=true;
+                           }
+                       }
+                   } while((hasMore=rs.next()) && fKeyName.equals(rs.getString(3)));
+
+                   if(foundRule) {
+                       tuple[2]=rs.getBytes(2); //PKTABLE_NAME
+                       tuple[6]=rs.getBytes(1); //FKTABLE_NAME
+
+                       // Parse the tgargs data
+                       StringBuffer fkeyColumns=new StringBuffer();
+                       StringBuffer pkeyColumns=new StringBuffer();
+                       int numColumns=(rs.getInt(7) >> 1) - 2;
+                       String s=rs.getString(8);
+                       int pos=s.lastIndexOf("\\000");
+                       for(int c=0;c<numColumns;c++) {
+                           if(pos>-1) {
+                               int pos2=s.lastIndexOf("\\000", pos-1);
+                               if(pos2>-1) {
+                                   if(fkeyColumns.length()>0) fkeyColumns.insert(0, ',');
+                                   fkeyColumns.insert(0, s.substring(pos2+4, pos)); //FKCOLUMN_NAME
+                                   pos=s.lastIndexOf("\\000", pos2-1);
+                                   if(pos>-1) {
+                                       if(pkeyColumns.length()>0) pkeyColumns.insert(0, ',');
+                                       pkeyColumns.insert(0, s.substring(pos+4, pos2)); //PKCOLUMN_NAME
+                                   }
+                               }
+                           }
+                       }
+                       tuple[7]=fkeyColumns.toString().getBytes(); //FKCOLUMN_NAME
+                       tuple[3]=pkeyColumns.toString().getBytes(); //PKCOLUMN_NAME
+
+                       tuple[8]=Integer.toString(seq++).getBytes(); //KEY_SEQ
+                       tuple[11]=fKeyName.getBytes(); //FK_NAME
+                       tuple[12]=rs.getBytes(4); //PK_NAME
+
+                       // DEFERRABILITY
+                       int deferrability=importedKeyNotDeferrable;
+                       boolean deferrable=rs.getBoolean(5);
+                       boolean initiallyDeferred=rs.getBoolean(6);
+                       if(deferrable) {
+                           if(initiallyDeferred)
+                               deferrability=importedKeyInitiallyDeferred;
+                           else
+                               deferrability=importedKeyInitiallyImmediate;
+                       }
+                       tuple[13]=Integer.toString(deferrability).getBytes();
+
+                       tuples.addElement(tuple);
+                   }
+               } while(hasMore);
+           }
+
+           return new ResultSet(connection, f, tuples, "OK", 1);
+       }
 
        /**
         * Get a description of the primary key columns that are
@@ -2519,50 +2566,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
         */
        public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException
        {
-                Field f[]=new Field[14];
-
-                f[0]=new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
-                f[1]=new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
-                f[2]=new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
-                f[3]=new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
-                f[4]=new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
-                f[5]=new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
-                f[6]=new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
-                f[7]=new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
-                f[8]=new Field(connection, "KEY_SEQ", iInt2Oid, 2);
-                f[9]=new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
-                f[10]=new Field(connection, "DELETE_RULE", iInt2Oid, 2);
-                f[11]=new Field(connection, "FK_NAME", iVarcharOid, 32);
-                f[12]=new Field(connection, "PK_NAME", iVarcharOid, 32);
-                f[13]=new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
-
-                java.sql.ResultSet rs = connection.ExecSQL("SELECT a.tgargs,"
-                                                           + "substring(a.proname from 9 for (char_length(a.proname)-12)),"
-                                                           + "substring(b.proname from 9 for (char_length(b.proname)-12)),"
-                                                           + "a.tgdeferrable,"
-                                                           + "a.tginitdeferred "
-                                                           + "FROM "
-                                                           + "(SELECT t.tgargs, t.tgconstrname, p.proname, t.tgdeferrable,"
-                                                           + "t.tginitdeferred "
-                                                           + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                           + "WHERE c.relfilenode=t.tgrelid AND t.tgfoid = p.oid "
-                                                           + "AND p.proname LIKE 'RI_FKey_%_upd') as a,"
-                                                           + "(SELECT t.tgconstrname, p.proname "
-                                                           + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                           + "WHERE c.relfilenode=t.tgrelid AND t.tgfoid = p.oid "
-                                                           + "AND p.proname LIKE 'RI_FKey_%_del') as b,"
-                                                           + "(SELECT t.tgconstrname FROM pg_class as c, pg_trigger as t "
-                                                           + "WHERE c.relname like '"+table+"' AND c.relfilenode=t.tgrelid) as c "
-                                                           + "WHERE a.tgconstrname=b.tgconstrname AND a.tgconstrname=c.tgconstrname"
-                                                           );
-                Vector tuples = new Vector();
-
-                while (rs.next())
-                {
-                  tuples.add(parseConstraint(rs));
-                }
-
-                return new ResultSet(connection, f, tuples, "OK", 1);
+           return getImportedExportedKeys(catalog, schema, null, table);
         }
 
        /**
@@ -2620,48 +2624,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
         */
        public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException
        {
-                Field f[] = new Field[14];
-
-                f[0] = new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
-                f[1] = new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
-                f[2] = new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
-                f[3] = new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
-                f[4] = new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
-                f[5] = new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
-                f[6] = new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
-                f[7] = new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
-                f[8] = new Field(connection, "KEY_SEQ", iInt2Oid, 2);
-                f[9] = new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
-                f[10] = new Field(connection, "DELETE_RULE", iInt2Oid, 2);
-                f[11] = new Field(connection, "FK_NAME", iVarcharOid, 32);
-                f[12] = new Field(connection, "PK_NAME", iVarcharOid, 32);
-                f[13] = new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
-
-                java.sql.ResultSet rs = connection.ExecSQL("SELECT a.tgargs,"
-                                                           + "substring(a.proname from 9 for (char_length(a.proname)-12)),"
-                                                           + "substring(b.proname from 9 for (char_length(b.proname)-12)),"
-                                                           + "a.tgdeferrable,"
-                                                           + "a.tginitdeferred "
-                                                           + "FROM "
-                                                           + "(SELECT t.tgargs, t.tgconstrname, p.proname,"
-                                                           + "t.tgdeferrable, t.tginitdeferred "
-                                                           + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                           + "WHERE c.relname like '"+table+"' AND c.relfilenode=t.tgrelid "
-                                                           + "AND t.tgfoid = p.oid AND p.proname LIKE 'RI_FKey_%_upd') as a, "
-                                                           + "(SELECT t.tgconstrname, p.proname "
-                                                           + "FROM pg_class as c, pg_proc as p, pg_trigger as t "
-                                                           + "WHERE c.relname like '"+table+"' AND c.relfilenode=t.tgrelid "
-                                                           + "AND t.tgfoid = p.oid AND p.proname LIKE 'RI_FKey_%_del') as b "
-                                                           + "WHERE a.tgconstrname=b.tgconstrname"
-                                                          );
-                Vector tuples = new Vector();
-
-                while (rs.next())
-                {
-                  tuples.add(parseConstraint(rs));
-                }
-
-                return new ResultSet(connection, f, tuples, "OK", 1);
+           return getImportedExportedKeys(catalog, schema, table, null);
        }
 
        /**
@@ -2722,7 +2685,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
         */
        public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException
        {
-               throw org.postgresql.Driver.notImplemented();
+           return getImportedExportedKeys(primaryCatalog, primarySchema, primaryTable, foreignTable);
        }
 
        /**