mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
369 lines
11 KiB
C++
369 lines
11 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin III - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// pgSequence.cpp - Sequence class
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// wxWindows headers
|
|
#include <wx/wx.h>
|
|
|
|
// App headers
|
|
#include "pgAdmin3.h"
|
|
#include "utils/misc.h"
|
|
#include "schema/pgSequence.h"
|
|
|
|
|
|
pgSequence::pgSequence(pgSchema *newSchema, const wxString &newName)
|
|
: pgSchemaObject(newSchema, sequenceFactory, newName)
|
|
{
|
|
isReplicated = false;
|
|
}
|
|
|
|
pgSequence::~pgSequence()
|
|
{
|
|
}
|
|
|
|
wxString pgSequence::GetTranslatedMessage(int kindOfMessage) const
|
|
{
|
|
wxString message = wxEmptyString;
|
|
|
|
switch (kindOfMessage)
|
|
{
|
|
case RETRIEVINGDETAILS:
|
|
message = _("Retrieving details on sequence");
|
|
message += wxT(" ") + GetName();
|
|
break;
|
|
case REFRESHINGDETAILS:
|
|
message = _("Refreshing sequence");
|
|
message += wxT(" ") + GetName();
|
|
break;
|
|
case DROPINCLUDINGDEPS:
|
|
message = wxString::Format(_("Are you sure you wish to drop sequence \"%s\" including all objects that depend on it?"),
|
|
GetFullIdentifier().c_str());
|
|
break;
|
|
case DROPEXCLUDINGDEPS:
|
|
message = wxString::Format(_("Are you sure you wish to drop sequence \"%s\"?"),
|
|
GetFullIdentifier().c_str());
|
|
break;
|
|
case DROPCASCADETITLE:
|
|
message = _("Drop sequence cascaded?");
|
|
break;
|
|
case DROPTITLE:
|
|
message = _("Drop sequence?");
|
|
break;
|
|
case PROPERTIESREPORT:
|
|
message = _("Sequence properties report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case PROPERTIES:
|
|
message = _("Sequence properties");
|
|
break;
|
|
case DDLREPORT:
|
|
message = _("Sequence DDL report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case DDL:
|
|
message = _("Sequence DDL");
|
|
break;
|
|
case STATISTICSREPORT:
|
|
message = _("Sequence statistics report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case OBJSTATISTICS:
|
|
message = _("Sequence statistics");
|
|
break;
|
|
case DEPENDENCIESREPORT:
|
|
message = _("Sequence dependencies report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case DEPENDENCIES:
|
|
message = _("Sequence dependencies");
|
|
break;
|
|
case DEPENDENTSREPORT:
|
|
message = _("Sequence dependents report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case DEPENDENTS:
|
|
message = _("Sequence dependents");
|
|
break;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
int pgSequence::GetIconId()
|
|
{
|
|
if (isReplicated)
|
|
return sequenceFactory.GetReplicatedIconId();
|
|
else
|
|
return sequenceFactory.GetIconId();
|
|
}
|
|
|
|
bool pgSequence::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
|
|
{
|
|
wxString sql = wxT("DROP SEQUENCE ") + this->GetSchema()->GetQuotedIdentifier() + wxT(".") + this->GetQuotedIdentifier();
|
|
if (cascaded)
|
|
sql += wxT(" CASCADE");
|
|
return GetDatabase()->ExecuteVoid(sql);
|
|
}
|
|
|
|
|
|
void pgSequence::UpdateValues()
|
|
{
|
|
wxString lsql;
|
|
wxString tabname = schema->GetQuotedPrefix() + qtIdent(GetName());
|
|
if (GetConnection()->BackendMinimumVersion(10, 0))
|
|
{
|
|
|
|
lsql=wxT("SELECT pg_catalog.format_type(seqtypid, NULL) AS \"Type\",\n")
|
|
wxT(" seqstart AS \"start\",\n")
|
|
wxT(" seqmin AS \"min_value\",\n")
|
|
wxT(" seqmax AS \"max_value\",\n")
|
|
wxT(" seqincrement AS \"increment_by\",\n")
|
|
wxT(" CASE WHEN seqcycle THEN 't' ELSE 'f' END AS \"is_cycled\",\n")
|
|
wxT(" seqcache AS \"cache_value\",\n")
|
|
wxT(" last_value, is_called")
|
|
wxT(" FROM pg_catalog.pg_sequence,")+GetQuotedFullIdentifier()+wxT(" s")
|
|
wxT(" WHERE seqrelid = ")+GetOidStr()+wxT("");
|
|
|
|
} else
|
|
{
|
|
lsql=wxT("SELECT last_value, min_value, max_value, cache_value, is_cycled, increment_by, is_called\n")
|
|
wxT(" FROM ") + GetQuotedFullIdentifier();
|
|
|
|
}
|
|
pgSet *sequence = ExecuteSet(lsql);
|
|
|
|
if (sequence)
|
|
{
|
|
lastValue = sequence->GetLongLong(wxT("last_value"));
|
|
minValue = sequence->GetLongLong(wxT("min_value"));
|
|
maxValue = sequence->GetLongLong(wxT("max_value"));
|
|
cacheValue = sequence->GetLongLong(wxT("cache_value"));
|
|
increment = sequence->GetLongLong(wxT("increment_by"));
|
|
cycled = sequence->GetBool(wxT("is_cycled"));
|
|
called = sequence->GetBool(wxT("is_called"));
|
|
if (called)
|
|
nextValue = lastValue + increment;
|
|
else
|
|
nextValue = lastValue;
|
|
|
|
delete sequence;
|
|
}
|
|
}
|
|
|
|
|
|
wxString pgSequence::GetSql(ctlTree *browser)
|
|
{
|
|
if (sql.IsNull())
|
|
{
|
|
UpdateValues();
|
|
sql = wxT("-- Sequence: ") + GetQuotedFullIdentifier() + wxT("\n\n")
|
|
+ wxT("-- DROP SEQUENCE ") + GetQuotedFullIdentifier() + wxT(";")
|
|
+ wxT("\n\nCREATE SEQUENCE ") + GetQuotedFullIdentifier()
|
|
+ wxT("\n INCREMENT ") + GetIncrement().ToString()
|
|
+ wxT("\n MINVALUE ") + GetMinValue().ToString()
|
|
+ wxT("\n MAXVALUE ") + GetMaxValue().ToString()
|
|
+ wxT("\n START ") + GetLastValue().ToString()
|
|
+ wxT("\n CACHE ") + GetCacheValue().ToString();
|
|
if (GetCycled())
|
|
sql += wxT("\n CYCLE");
|
|
sql += wxT(";\n")
|
|
+ GetOwnerSql(7, 3, wxT("TABLE ") + GetQuotedFullIdentifier());
|
|
|
|
if (!GetConnection()->BackendMinimumVersion(8, 2))
|
|
sql += GetGrant(wxT("arwdRxt"), wxT("TABLE ") + GetQuotedFullIdentifier());
|
|
else
|
|
sql += GetGrant(wxT("rwU"), wxT("SEQUENCE ") + GetQuotedFullIdentifier());
|
|
|
|
sql += GetCommentSql();
|
|
|
|
if (GetConnection()->BackendMinimumVersion(9, 1))
|
|
sql += GetSeqLabelsSql();
|
|
}
|
|
|
|
return sql;
|
|
}
|
|
|
|
void pgSequence::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
|
|
{
|
|
UpdateValues();
|
|
if (properties)
|
|
{
|
|
CreateListColumns(properties);
|
|
|
|
properties->AppendItem(_("Name"), GetName());
|
|
properties->AppendItem(_("OID"), GetOid());
|
|
properties->AppendItem(_("Owner"), GetOwner());
|
|
properties->AppendItem(_("ACL"), GetAcl());
|
|
properties->AppendItem(_("Current value"), GetLastValue());
|
|
properties->AppendItem(_("Next value"), GetNextValue());
|
|
properties->AppendItem(_("Minimum"), GetMinValue());
|
|
properties->AppendItem(_("Maximum"), GetMaxValue());
|
|
properties->AppendItem(_("Increment"), GetIncrement());
|
|
properties->AppendItem(_("Cache"), GetCacheValue());
|
|
properties->AppendYesNoItem(_("Cycled?"), GetCycled());
|
|
properties->AppendYesNoItem(_("Called?"), GetCalled());
|
|
properties->AppendYesNoItem(_("System sequence?"), 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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void pgSequence::ShowStatistics(frmMain *form, ctlListView *statistics)
|
|
{
|
|
wxLogInfo(wxT("Displaying statistics for sequence on ") + GetSchema()->GetIdentifier());
|
|
|
|
// Add the statistics view columns
|
|
CreateListColumns(statistics, _("Statistic"), _("Value"));
|
|
|
|
pgSet *stats = GetSchema()->GetDatabase()->ExecuteSet(wxT(
|
|
"SELECT blks_read, blks_hit FROM pg_statio_all_sequences WHERE relid = ") + GetOidStr());
|
|
|
|
if (stats)
|
|
{
|
|
statistics->InsertItem(0, _("Blocks Read"), PGICON_STATISTICS);
|
|
statistics->SetItem(0l, 1, stats->GetVal(wxT("blks_read")));
|
|
statistics->InsertItem(1, _("Blocks Hit"), PGICON_STATISTICS);
|
|
statistics->SetItem(1, 1, stats->GetVal(wxT("blks_hit")));
|
|
|
|
delete stats;
|
|
}
|
|
}
|
|
|
|
|
|
pgObject *pgSequence::Refresh(ctlTree *browser, const wxTreeItemId item)
|
|
{
|
|
pgObject *sequence = 0;
|
|
pgCollection *coll = browser->GetParentCollection(item);
|
|
if (coll)
|
|
sequence = sequenceFactory.CreateObjects(coll, 0, wxT("\n AND cl.oid=") + GetOidStr());
|
|
|
|
return sequence;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
|
|
pgSequenceCollection::pgSequenceCollection(pgaFactory *factory, pgSchema *sch)
|
|
: pgSchemaObjCollection(factory, sch)
|
|
{
|
|
}
|
|
|
|
|
|
wxString pgSequenceCollection::GetTranslatedMessage(int kindOfMessage) const
|
|
{
|
|
wxString message = wxEmptyString;
|
|
|
|
switch (kindOfMessage)
|
|
{
|
|
case RETRIEVINGDETAILS:
|
|
message = _("Retrieving details on sequences");
|
|
break;
|
|
case REFRESHINGDETAILS:
|
|
message = _("Refreshing sequences");
|
|
break;
|
|
case GRANTWIZARDTITLE:
|
|
message = _("Privileges for sequences");
|
|
break;
|
|
case OBJECTSLISTREPORT:
|
|
message = _("Sequences list report");
|
|
break;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
pgObject *pgSequenceFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
|
|
{
|
|
pgSet *sequences;
|
|
pgSequence *sequence = 0;
|
|
wxString sql;
|
|
|
|
sql = wxT("SELECT cl.oid, relname, pg_get_userbyid(relowner) AS seqowner, relacl, description");
|
|
if (collection->GetDatabase()->BackendMinimumVersion(9, 1))
|
|
{
|
|
sql += wxT(",\n(SELECT array_agg(label) FROM pg_seclabels sl1 WHERE sl1.objoid=cl.oid) AS labels");
|
|
sql += wxT(",\n(SELECT array_agg(provider) FROM pg_seclabels sl2 WHERE sl2.objoid=cl.oid) AS providers");
|
|
}
|
|
sql += wxT("\n FROM pg_class cl\n")
|
|
wxT(" LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass)\n")
|
|
wxT(" WHERE relkind = 'S' AND relnamespace = ") + collection->GetSchema()->GetOidStr()
|
|
+ restriction + wxT("\n")
|
|
wxT(" ORDER BY relname");
|
|
|
|
sequences = collection->GetDatabase()->ExecuteSet(sql);
|
|
|
|
if (sequences)
|
|
{
|
|
while (!sequences->Eof())
|
|
{
|
|
sequence = new pgSequence(collection->GetSchema(),
|
|
sequences->GetVal(wxT("relname")));
|
|
|
|
sequence->iSetOid(sequences->GetOid(wxT("oid")));
|
|
sequence->iSetComment(sequences->GetVal(wxT("description")));
|
|
sequence->iSetOwner(sequences->GetVal(wxT("seqowner")));
|
|
sequence->iSetAcl(sequences->GetVal(wxT("relacl")));
|
|
|
|
if (collection->GetDatabase()->BackendMinimumVersion(9, 1))
|
|
{
|
|
sequence->iSetProviders(sequences->GetVal(wxT("providers")));
|
|
sequence->iSetLabels(sequences->GetVal(wxT("labels")));
|
|
}
|
|
|
|
if (browser)
|
|
{
|
|
browser->AppendObject(collection, sequence);
|
|
sequences->MoveNext();
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
delete sequences;
|
|
}
|
|
return sequence;
|
|
}
|
|
|
|
|
|
#include "images/sequence.pngc"
|
|
#include "images/sequences.pngc"
|
|
|
|
pgSequenceFactory::pgSequenceFactory()
|
|
: pgSchemaObjFactory(__("Sequence"), __("New Sequence..."), __("Create a new Sequence."), sequence_png_img)
|
|
{
|
|
metaType = PGM_SEQUENCE;
|
|
}
|
|
|
|
|
|
pgCollection *pgSequenceFactory::CreateCollection(pgObject *obj)
|
|
{
|
|
return new pgSequenceCollection(GetCollectionFactory(), (pgSchema *)obj);
|
|
}
|
|
|
|
pgSequenceFactory sequenceFactory;
|
|
static pgaCollectionFactory cf(&sequenceFactory, __("Sequences"), sequences_png_img);
|