Ejemplo n.º 1
0
void pgUser::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
    if (!expandedKids)
    {
        expandedKids = true;

        pgSet *set = GetServer()->ExecuteSet(wxT("SELECT groname, grolist FROM pg_group ORDER BY groname"));
        if (set)
        {
            while (!set->Eof())
            {
                wxString groupName = set->GetVal(wxT("groname"));
                wxString str = set->GetVal(wxT("grolist"));
                if (!str.IsNull())
                {
                    wxStringTokenizer ids(str.Mid(1, str.Length() - 2), wxT(","));
                    while (ids.HasMoreTokens())
                    {
                        if (StrToLong(ids.GetNextToken()) == GetUserId())
                        {
                            groupsIn.Add(groupName);
                            break;
                        }
                    }
                }
                set->MoveNext();
            }
            delete set;
        }
    }
    if (properties)
    {
        CreateListColumns(properties);

        properties->AppendItem(_("Name"), GetName());
        properties->AppendItem(_("User ID"), GetUserId());
        properties->AppendItem(_("Account expires"), DateToAnsiStr(GetAccountExpires()));
        properties->AppendItem(_("Superuser?"), BoolToYesNo(GetSuperuser()));
        properties->AppendItem(_("Create databases?"), BoolToYesNo(GetCreateDatabase()));
        properties->AppendItem(_("Update catalogs?"), BoolToYesNo(GetUpdateCatalog()));

        wxString groupList;

        size_t index;
        for (index = 0 ; index < groupsIn.GetCount() ; index++)
        {
            if (!groupList.IsEmpty())
                groupList += wxT(", ");
            groupList += groupsIn.Item(index);
        }
        properties->AppendItem(_("Member of"), groupList);

        for (index = 0; index < configList.GetCount() ; index++)
        {
            wxString item = configList.Item(index);
            properties->AppendItem(item.BeforeFirst('='), item.AfterFirst('='));
        }
    }
}
Ejemplo n.º 2
0
void ConfigDisplay(ConfigFileInfo *Info)
{
	int loop;
	for(loop = 0; loop != Info -> NumOfOptions; ++loop)
	{
		if( *(Info -> Options[loop].Caption) != '\0' )
		{
			switch( Info -> Options[loop].Type )
			{
				case TYPE_INT32:
					printf("%s:%d\n", Info -> Options[loop].Caption, Info -> Options[loop].Holder.INT32);
					break;
				case TYPE_BOOLEAN:
					printf("%s:%s\n", Info -> Options[loop].Caption, BoolToYesNo(Info -> Options[loop].Holder.boolean));
					break;
				case TYPE_STRING:
					if( Info -> Options[loop].Holder.str != NULL )
						printf("%s:%s\n", Info -> Options[loop].Caption, Info -> Options[loop].Holder.str);
					break;
				default:
					break;
			}
		}
	}
}
Ejemplo n.º 3
0
void pgCheck::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
	if (properties)
	{
		CreateListColumns(properties);

		properties->AppendItem(_("Name"), GetName());
		properties->AppendItem(_("OID"), GetOid());
		properties->AppendItem(_("Definition"), GetDefinition());
		if (GetDatabase()->BackendMinimumVersion(9, 2))
		{
			properties->AppendItem(_("No Inherit?"), BoolToYesNo(GetNoInherit()));
			properties->AppendItem(_("Valid?"), BoolToYesNo(GetValid()));
		}
		// Check constraints on a domain don't have comments
		if (objectKind.Upper() == wxT("TABLE"))
			properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
	}
}
Ejemplo n.º 4
0
void gpResQueue::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
	if (!expandedKids)
	{
		expandedKids = true;
		wxString queuesquery;

		queuesquery = wxT("SELECT rolname,\n")
		              wxT(" pg_catalog.shobj_description(r.oid, 'pg_authid') AS description\n");

		queuesquery += wxT("  FROM pg_roles r\n")
		               wxT("  JOIN pg_resqueue q ON  rolresqueue=q.oid\n")
		               wxT(" WHERE  rolresqueue=") + GetOidStr() + wxT("\n")
		               wxT(" ORDER BY rolname");

		pgSetIterator queues(GetConnection(), queuesquery);

		while (queues.RowsLeft())
		{
			wxString queue = queues.GetVal(wxT("rolname"));

			queuesIn.Add(queue);
		}
	}
	if (properties)
	{
		CreateListColumns(properties);

		properties->AppendItem(_("Name"), GetName());
		properties->AppendItem(_("OID"), GetOid());
		properties->AppendItem(_("Active threshold"), GetCountLimit());
		properties->AppendItem(_("Cost threshold"), GetCostLimit());
		properties->AppendItem(_("Ignore threshold"), GetIgnoreCostLimit());
		properties->AppendItem(_("Over commit?"), BoolToYesNo(GetOvercommit()));

		wxString roleList;

		size_t index;
		for (index = 0 ; index < queuesIn.GetCount() ; index++)
		{
			if (!roleList.IsEmpty())
				roleList += wxT(", ");
			roleList += queuesIn.Item(index);
		}
		properties->AppendItem(_("Roles using this"), roleList);
		properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));

	}
}
Ejemplo n.º 5
0
void pgRole::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
    if (!expandedKids)
    {
        expandedKids=true;
        wxString rolesquery;

        if (GetConnection()->BackendMinimumVersion(8, 2))
            rolesquery = wxT("SELECT rolname, admin_option,\n") 
                         wxT(" pg_catalog.shobj_description(r.oid, 'pg_authid') AS description\n");
        else
            rolesquery = wxT("SELECT rolname, admin_option\n"); 

        rolesquery += wxT("  FROM pg_roles r\n") 
                      wxT("  JOIN pg_auth_members ON r.oid=roleid\n") 
                      wxT(" WHERE member=") + GetOidStr() + wxT("\n") 
                      wxT(" ORDER BY rolname");

        pgSetIterator roles(GetConnection(), rolesquery);

        while (roles.RowsLeft())
        {
            wxString role=roles.GetVal(wxT("rolname"));
            if (roles.GetBool(wxT("admin_option")))
                role += PGROLE_ADMINOPTION;

            rolesIn.Add(role);
        }
    }
    if (properties)
    {
        CreateListColumns(properties);

        properties->AppendItem(_("Name"), GetName());
        properties->AppendItem(_("OID"), GetOid());
        properties->AppendItem(_("Account expires"), DateToAnsiStr(GetAccountExpires()));
        properties->AppendItem(_("Can login?"), BoolToYesNo(GetCanLogin()));
        properties->AppendItem(_("Superuser?"), BoolToYesNo(GetSuperuser()));
        properties->AppendItem(_("Create databases?"), BoolToYesNo(GetCreateDatabase()));
        properties->AppendItem(_("Create roles?"), BoolToYesNo(GetCreateRole()));
        properties->AppendItem(_("Update catalogs?"), BoolToYesNo(GetUpdateCatalog()));
        properties->AppendItem(_("Inherits?"), BoolToYesNo(GetInherits()));
        if (server->GetConnection()->BackendMinimumVersion(9, 1))
        {
            properties->AppendItem(_("Replication?"), BoolToYesNo(GetReplication()));
        }

        wxString strConnLimit;
        strConnLimit.Printf(wxT("%ld"), GetConnectionLimit()); 
        properties->AppendItem(_("Connection Limit"), strConnLimit);

        properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));

        wxString roleList;

        size_t index;
        for (index=0 ; index < rolesIn.GetCount() ; index++)
        {
            if (!roleList.IsEmpty())
                roleList += wxT(", ");
            roleList += rolesIn.Item(index);
        }
        properties->AppendItem(_("Member of"), roleList);

        for (index=0; index < configList.GetCount() ; index++)
        {
            wxString item=configList.Item(index);
            properties->AppendItem(item.BeforeFirst('='), item.AfterFirst('='));
        }
    }
}
Ejemplo n.º 6
0
void pgType::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
	wxString query;
	wxString collation;

	if (!expandedKids)
	{
		expandedKids = true;
		if (GetTypeClass() == TYPE_COMPOSITE)
		{
			query = wxT("SELECT attname, format_type(t.oid,NULL) AS typname, attndims, atttypmod, nsp.nspname,\n")
			        wxT("       (SELECT COUNT(1) from pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup");
			if (GetConnection()->BackendMinimumVersion(9, 1))
				query += wxT(",\n       collname, nspc.nspname as collnspname");
			query += wxT("\n  FROM pg_attribute att\n")
			         wxT("  JOIN pg_type t ON t.oid=atttypid\n")
			         wxT("  JOIN pg_namespace nsp ON t.typnamespace=nsp.oid\n")
			         wxT("  LEFT OUTER JOIN pg_type b ON t.typelem=b.oid\n");
			if (GetConnection()->BackendMinimumVersion(9, 1))
				query += wxT("  LEFT OUTER JOIN pg_collation c ON att.attcollation=c.oid\n")
				         wxT("  LEFT OUTER JOIN pg_namespace nspc ON c.collnamespace=nspc.oid\n");
			query += wxT(" WHERE att.attrelid=") + NumToStr(relOid) + wxT("\n")
			         wxT(" ORDER by attnum");
			pgSet *set = ExecuteSet(query);
			if (set)
			{
				int anzvar = 0;
				while (!set->Eof())
				{
					wxString element;
					if (anzvar++)
					{
						typesList += wxT(", ");
						quotedTypesList += wxT(",\n    ");
					}
					typesList += set->GetVal(wxT("attname")) + wxT(" ");
					typesArray.Add(set->GetVal(wxT("attname")));
					quotedTypesList += qtIdent(set->GetVal(wxT("attname"))) + wxT(" ");

					pgDatatype dt(set->GetVal(wxT("nspname")), set->GetVal(wxT("typname")),
					              set->GetBool(wxT("isdup")), set->GetLong(wxT("attndims")) > 0, set->GetLong(wxT("atttypmod")));

					wxString nspname = set->GetVal(wxT("nspname"));

					typesList += dt.GetSchemaPrefix(GetDatabase()) + dt.FullName();
					typesArray.Add(dt.GetSchemaPrefix(GetDatabase()) + dt.FullName());
					quotedTypesList += dt.GetQuotedSchemaPrefix(GetDatabase()) + dt.QuotedFullName();

					if (GetConnection()->BackendMinimumVersion(9, 1))
					{
						if (set->GetVal(wxT("collname")).IsEmpty() || (set->GetVal(wxT("collname")) == wxT("default") && set->GetVal(wxT("collnspname")) == wxT("pg_catalog")))
							collation = wxEmptyString;
						else
						{
							collation = qtIdent(set->GetVal(wxT("collnspname"))) + wxT(".") + qtIdent(set->GetVal(wxT("collname")));
							quotedTypesList += wxT(" COLLATE ") + collation;
						}
						collationsArray.Add(collation);
					}
					typesArray.Add(collation);

					set->MoveNext();
				}
				delete set;
			}
		}
		else if (GetTypeClass() == TYPE_ENUM)
		{
			query = wxT("SELECT enumlabel\n")
			        wxT("  FROM pg_enum\n")
			        wxT(" WHERE enumtypid=") + GetOidStr() + wxT("\n");
			if (GetConnection()->BackendMinimumVersion(9, 1))
				query += wxT(" ORDER by enumsortorder");
			else
				query += wxT(" ORDER by oid");
			pgSet *set = ExecuteSet(query);
			if (set)
			{
				int anzvar = 0;
				while (!set->Eof())
				{
					wxString element;
					if (anzvar++)
					{
						labelList += wxT(", ");
						quotedLabelList += wxT(",\n    ");
					}
					labelList += set->GetVal(wxT("enumlabel"));
					labelArray.Add(set->GetVal(wxT("enumlabel")));
					quotedLabelList += GetDatabase()->connection()->qtDbString(set->GetVal(wxT("enumlabel")));

					set->MoveNext();
				}
				delete set;
			}
		}
	}

	if (properties)
	{
		CreateListColumns(properties);

		properties->AppendItem(_("Name"), GetName());
		properties->AppendItem(_("OID"), GetOid());
		properties->AppendItem(_("Owner"), GetOwner());
		properties->AppendItem(_("Alias"), GetAlias());
		if (GetTypeClass() == TYPE_COMPOSITE)
		{
			properties->AppendItem(_("Members"), GetTypesList());
		}
		if (GetTypeClass() == TYPE_ENUM)
		{
			properties->AppendItem(_("Labels"), GetLabelList());
		}
		else
		{
			properties->AppendItem(_("Alignment"), GetAlignment());
			properties->AppendItem(_("Internal length"), GetInternalLength());
			properties->AppendItem(_("Default"), GetDefault());
			properties->AppendItem(_("Passed by Value?"), BoolToYesNo(GetPassedByValue()));
			if (!GetElement().IsEmpty())
			{
				properties->AppendItem(_("Element"), GetElement());
				properties->AppendItem(_("Delimiter"), GetDelimiter());
			}
			properties->AppendItem(_("Input function"), GetInputFunction());
			properties->AppendItem(_("Output function"), GetOutputFunction());
			if (GetConnection()->BackendMinimumVersion(7, 4))
			{
				properties->AppendItem(_("Receive function"), GetReceiveFunction());
				properties->AppendItem(_("Send function"), GetSendFunction());
			}
			if (GetConnection()->BackendMinimumVersion(8, 3))
			{
				if (GetTypmodinFunction().Length() > 0)
					properties->AppendItem(_("Typmod in function"), GetTypmodinFunction());
				if (GetTypmodoutFunction().Length() > 0)
					properties->AppendItem(_("Typmod out function"), GetTypmodoutFunction());
			}
			properties->AppendItem(_("Storage"), GetStorage());
			if (GetConnection()->BackendMinimumVersion(9, 1))
				properties->AppendItem(_("Collatable?"), BoolToYesNo(GetCollatable()));
		}
		properties->AppendYesNoItem(_("System type?"), GetSystemObject());
		properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));

		if (!GetLabels().IsEmpty())
		{
			wxArrayString seclabels = GetProviderLabelArray();
			if (seclabels.GetCount() > 0)
			{
				for (unsigned int index = 0 ; index < seclabels.GetCount() - 1 ; index += 2)
				{
					properties->AppendItem(seclabels.Item(index), seclabels.Item(index + 1));
				}
			}
		}
	}
}
Ejemplo n.º 7
0
void reportObjectDataDictionaryFactory::GenerateReport(frmReport *report, pgObject *object)
{

	pgTable *table = (pgTable *)object;

	report->SetReportTitle(object->GetTranslatedMessage(DATADICTIONNARYREPORT));

	// Columns
	int section = report->XmlCreateSection(_("Columns"));

	report->XmlSetSectionTableHeader(section, 6, (const wxChar *) _("Name"), (const wxChar *) _("Data type"), (const wxChar *) _("Not Null?"), (const wxChar *) _("Primary key?"), (const wxChar *) _("Default"), (const wxChar *) _("Comment"));

	ctlTree *browser = GetFrmMain()->GetBrowser();
	pgCollection *columns = table->GetColumnCollection(browser);

	treeObjectIterator colIt(browser, columns);

	pgColumn *column;
	bool haveInherit = false;
	wxString colName;
	while ((column = (pgColumn *)colIt.GetNextObject()) != 0)
	{
		column->ShowTreeDetail(browser);
		if (column->GetColNumber() > 0)
		{
			colName = column->GetName();
			if (column->GetInheritedCount() > 0)
			{
				colName += _("*");
				haveInherit = true;
			}

			report->XmlAddSectionTableRow(section,
			                              column->GetColNumber(),
			                              6,
			                              (const wxChar *) colName,
			                              (const wxChar *) column->GetVarTypename(),
			                              (const wxChar *) BoolToYesNo(column->GetNotNull()),
			                              (const wxChar *) BoolToYesNo(column->GetIsPK()),
			                              (const wxChar *) column->GetDefault(),
			                              (const wxChar *) column->GetComment());
		}
	}
	if (haveInherit)
	{
		wxString info;
		info.Printf(_("* Inherited columns from %s."), table->GetInheritedTables().c_str());
		report->XmlSetSectionTableInfo(section, info);
	}

	// Constraints
	pgCollection *constraints = table->GetConstraintCollection(browser);

	treeObjectIterator conIt(browser, constraints);

	pgObject *constraint;
	long x = 1;
	wxString definition, type;
	while ((constraint = (pgObject *)conIt.GetNextObject()) != 0)
	{
		if (x == 1)
		{
			section = report->XmlCreateSection(_("Constraints"));
			report->XmlSetSectionTableHeader(section, 4, (const wxChar *) _("Name"), (const wxChar *) _("Type"), (const wxChar *) _("Definition"), (const wxChar *) _("Comment"));
		}

		constraint->ShowTreeDetail(browser);

		switch (constraint->GetMetaType())
		{
			case PGM_PRIMARYKEY:
				type = _("Primary key");
				definition = ((pgIndexConstraint *)constraint)->GetDefinition();
				break;
			case PGM_UNIQUE:
				type = _("Unique");
				definition = ((pgIndexConstraint *)constraint)->GetDefinition();
				break;
			case PGM_FOREIGNKEY:
				type = _("Foreign key");
				definition = ((pgForeignKey *)constraint)->GetDefinition();
				break;
			case PGM_EXCLUDE:
				type = _("Exclude");
				definition = ((pgIndexConstraint *)constraint)->GetDefinition();
				break;
			case PGM_CHECK:
				type = _("Check");
				definition = wxT("(") + ((pgCheck *)constraint)->GetDefinition() + wxT(")");
				break;
		}

		report->XmlAddSectionTableRow(section,
		                              x,
		                              4,
		                              (const wxChar *) constraint->GetName(),
		                              (const wxChar *) type,
		                              (const wxChar *) definition,
		                              (const wxChar *) constraint->GetComment());
		x++;
	}
}
Ejemplo n.º 8
0
void pgRole::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
	if (!expandedKids)
	{
		expandedKids = true;
		wxString rolesquery;

		if (GetConnection()->BackendMinimumVersion(8, 2))
			rolesquery = wxT("SELECT rolname, admin_option,\n")
			             wxT(" pg_catalog.shobj_description(r.oid, 'pg_authid') AS description\n");
		else
			rolesquery = wxT("SELECT rolname, admin_option\n");

		rolesquery += wxT("  FROM pg_roles r\n")
		              wxT("  JOIN pg_auth_members ON r.oid=roleid\n")
		              wxT(" WHERE member=") + GetOidStr() + wxT("\n")
		              wxT(" ORDER BY rolname");

		pgSetIterator roles(GetConnection(), rolesquery);

		while (roles.RowsLeft())
		{
			wxString role = roles.GetVal(wxT("rolname"));
			if (roles.GetBool(wxT("admin_option")))
				role += PGROLE_ADMINOPTION;

			rolesIn.Add(role);
		}

		// Get configuration
		wxString query;
		if (GetConnection()->BackendMinimumVersion(9, 0))
		{
			query = wxT("WITH configs AS ")
			        wxT("(SELECT datname, unnest(setconfig) AS config")
			        wxT(" FROM pg_db_role_setting s")
			        wxT(" LEFT JOIN pg_database d ON d.oid=s.setdatabase")
			        wxT(" WHERE s.setrole=") + NumToStr(GetOid()) + wxT(")\n")
			        wxT("SELECT datname, split_part(config, '=', 1) AS variable, replace(config, split_part(config, '=', 1) || '=', '') AS value\n")
			        wxT("FROM configs");
		}
		else
		{
			wxString query_myrole = wxT("SELECT rolconfig FROM pg_roles WHERE oid=") + NumToStr(GetOid());
			query = wxT("SELECT '' AS datname, split_part(config, '=', 1) AS variable,\n")
			        wxT("       replace(config,split_part(config, '=', 1) || '=', '') AS value\n")
			        wxT("FROM (\n")
			        wxT("    SELECT\n")
			        wxT("      (\n")
			        wxT("      SELECT rolconfig[i]\n")
			        wxT("      FROM pg_roles\n")
			        wxT("      WHERE oid=") + NumToStr(GetOid()) + wxT("\n")
			        wxT("      ) AS config\n")
			        wxT("    FROM generate_series(array_lower((") + query_myrole + wxT("),1), array_upper((") + query_myrole + wxT("),1)) AS i\n")
			        wxT("     ) configs");
		}
		pgSet *configs = GetConnection()->ExecuteSet(query);
		if (configs)
		{
			while (!configs->Eof())
			{
				variables.Add(configs->GetVal(wxT("datname")));
				variables.Add(configs->GetVal(wxT("variable")));
				variables.Add(configs->GetVal(wxT("value")));
				configs->MoveNext();
			}
			delete configs;
		}
	}
	if (properties)
	{
		CreateListColumns(properties);

		properties->AppendItem(_("Name"), GetName());
		properties->AppendItem(_("OID"), GetOid());
		properties->AppendItem(_("Account expires"), DateToAnsiStr(GetAccountExpires()));
		properties->AppendItem(_("Can login?"), BoolToYesNo(GetCanLogin()));
		properties->AppendItem(_("Superuser?"), BoolToYesNo(GetSuperuser()));
		properties->AppendItem(_("Create databases?"), BoolToYesNo(GetCreateDatabase()));
		properties->AppendItem(_("Create roles?"), BoolToYesNo(GetCreateRole()));

		if (!server->GetConnection()->BackendMinimumVersion(9, 5))
			properties->AppendItem(_("Update catalogs?"), BoolToYesNo(GetUpdateCatalog()));
		properties->AppendItem(_("Inherits?"), BoolToYesNo(GetInherits()));
		if (server->GetConnection()->BackendMinimumVersion(9, 1))
		{
			properties->AppendItem(_("Replication?"), BoolToYesNo(GetReplication()));
		}

		wxString strConnLimit;
		strConnLimit.Printf(wxT("%ld"), GetConnectionLimit());
		properties->AppendItem(_("Connection Limit"), strConnLimit);

		properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));

		wxString roleList;

		size_t index;
		for (index = 0 ; index < rolesIn.GetCount() ; index++)
		{
			if (!roleList.IsEmpty())
				roleList += wxT(", ");
			roleList += rolesIn.Item(index);
		}
		properties->AppendItem(_("Member of"), roleList);

		wxString dbname;
		wxString parameter;
		wxString value;
		for (index = 0; index < variables.GetCount() ; index += 3)
		{
			dbname = variables.Item(index);
			parameter = variables.Item(index + 1);
			value = variables.Item(index + 2);

			if (dbname.Length() == 0)
			{
				properties->AppendItem(parameter, value);
			}
			else
			{
				properties->AppendItem(parameter + wxT(" (database ") + dbname + wxT(")"), value);
			}
		}

		if (!GetLabels().IsEmpty())
		{
			wxArrayString seclabels = GetProviderLabelArray();
			if (seclabels.GetCount() > 0)
			{
				for (unsigned int index = 0 ; index < seclabels.GetCount() - 1 ; index += 2)
				{
					properties->AppendItem(seclabels.Item(index), seclabels.Item(index + 1));
				}
			}
		}
	}
}
Ejemplo n.º 9
0
void pgForeignKey::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
	if (!expandedKids)
	{
		expandedKids = true;

		wxStringTokenizer c1l(GetConkey(), wxT(","));
		wxStringTokenizer c2l(GetConfkey(), wxT(","));
		wxString c1, c2;

		// resolve column names
		while (c1l.HasMoreTokens())
		{
			c1 = c1l.GetNextToken();
			c2 = c2l.GetNextToken();
			pgSet *set = ExecuteSet(
			                 wxT("SELECT a1.attname as conattname, a2.attname as confattname\n")
			                 wxT("  FROM pg_attribute a1, pg_attribute a2\n")
			                 wxT(" WHERE a1.attrelid=") + GetTableOidStr() + wxT(" AND a1.attnum=") + c1 + wxT("\n")
			                 wxT("   AND a2.attrelid=") + GetRelTableOidStr() + wxT(" AND a2.attnum=") + c2);
			if (set)
			{
				if (!fkColumns.IsNull())
				{
					fkColumns += wxT(", ");
					refColumns += wxT(", ");
					quotedFkColumns += wxT(", ");
					quotedRefColumns += wxT(", ");
				}
				fkColumns += set->GetVal(0);
				refColumns += set->GetVal(1);
				quotedFkColumns += qtIdent(set->GetVal(0));
				quotedRefColumns += qtIdent(set->GetVal(1));
				delete set;
			}
		}
		wxTreeItemId item = browser->GetItemParent(GetId());
		while (item)
		{
			pgTable *table = (pgTable *)browser->GetObject(item);
			if (table->IsCreatedBy(tableFactory))
			{
				coveringIndex = table->GetCoveringIndex(browser, fkColumns);
				break;
			}
			item = browser->GetItemParent(item);
		}
	}

	if (properties)
	{
		CreateListColumns(properties);

		properties->AppendItem(_("Name"), GetName());
		properties->AppendItem(_("OID"), NumToStr(GetOid()));
		properties->AppendItem(_("Child columns"), GetFkColumns());
		properties->AppendItem(_("References"), GetReferences()
		                       + wxT("(") + GetRefColumns() + wxT(")"));

		properties->AppendItem(_("Covering index"), GetCoveringIndex());
		properties->AppendItem(_("Match type"), GetMatch());
		properties->AppendItem(_("On update"), GetOnUpdate());
		properties->AppendItem(_("On delete"), GetOnDelete());
		properties->AppendItem(_("Deferrable?"), BoolToYesNo(GetDeferrable()));
		if (GetDeferrable())
			properties->AppendItem(_("Initially?"),
			                       GetDeferred() ? wxT("DEFERRED") : wxT("IMMEDIATE"));
		if (GetDatabase()->BackendMinimumVersion(9, 1))
			properties->AppendItem(_("Valid?"), BoolToYesNo(GetValid()));
		properties->AppendItem(_("System foreign key?"), BoolToYesNo(GetSystemObject()));
		properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
	}
}