pgadmin3/schema/pgSequence.cpp
lsv cf7314facb Fixed the sequence property is_cycled
Начиная с 10 версии это свойство ошибочно всегда определялось как false.
2024-02-02 19:13:34 +05:00

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);