pgadmin3/frm/frmReport.cpp
lsv d7306e633c Add Compare options dialog.
При сравнении объектов добавлена возможность исключать сравнение привелегий и комментариев.
2020-09-04 15:37:58 +05:00

2348 lines
69 KiB
C++
Raw Blame History

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// frmReport.cpp - The report file dialogue
//
//////////////////////////////////////////////////////////////////////////
// App headers
#include "pgAdmin3.h"
#include <wx/file.h>
#include <wx/regex.h>
#include "frm/frmMain.h"
#include "frm/frmReport.h"
#include "utils/sysSettings.h"
#include "utils/misc.h"
#include "ctl/ctlListView.h"
#include "schema/pgObject.h"
#include "schema/pgCollection.h"
#include "schema/pgServer.h"
#include "schema/pgDatabase.h"
#include "schema/pgSchema.h"
#include "schema/pgTable.h"
#include "schema/pgColumn.h"
#include "schema/pgConstraints.h"
#include "agent/pgaJob.h"
#include "schema/pgForeignKey.h"
#include "schema/pgIndexConstraint.h"
#include "schema/pgCheck.h"
#include "utils/utffile.h"
#include <wx/stdpaths.h>
// XML2/XSLT headers
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#define txtTitle CTRL_TEXT("txtTitle")
#define txtNotes CTRL_TEXT("txtNotes")
#define txtHtmlFile CTRL_TEXT("txtHtmlFile")
#define txtXmlFile CTRL_TEXT("txtXmlFile")
#define txtHtmlStylesheet CTRL_TEXT("txtHtmlStylesheet")
#define txtXmlStylesheet CTRL_TEXT("txtXmlStylesheet")
#define btnOK CTRL_BUTTON("wxID_OK")
#define btnFile CTRL_BUTTON("btnFile")
#define btnStylesheet CTRL_BUTTON("btnStylesheet")
#define rbHtml CTRL_RADIOBUTTON("rbHtml")
#define rbXml CTRL_RADIOBUTTON("rbXml")
#define rbHtmlBuiltin CTRL_RADIOBUTTON("rbHtmlBuiltin")
#define rbHtmlEmbed CTRL_RADIOBUTTON("rbHtmlEmbed")
#define rbHtmlLink CTRL_RADIOBUTTON("rbHtmlLink")
#define rbXmlPlain CTRL_RADIOBUTTON("rbXmlPlain")
#define rbXmlLink CTRL_RADIOBUTTON("rbXmlLink")
#define rbXmlProcess CTRL_RADIOBUTTON("rbXmlProcess")
#define chkSql CTRL_CHECKBOX("chkSql")
#define chkBrowser CTRL_CHECKBOX("chkBrowser")
BEGIN_EVENT_TABLE(frmReport, pgDialog)
EVT_RADIOBUTTON(XRCID("rbHtml"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbXml"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbHtmlBuiltin"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbHtmlEmbed"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbHtmlLink"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbXmlPlain"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbXmlLink"), frmReport::OnChange)
EVT_RADIOBUTTON(XRCID("rbXmlProcess"), frmReport::OnChange)
EVT_TEXT(XRCID("txtHtmlFile"), frmReport::OnChange)
EVT_TEXT(XRCID("txtXmlFile"), frmReport::OnChange)
EVT_TEXT(XRCID("txtHtmlStylesheet"), frmReport::OnChange)
EVT_TEXT(XRCID("txtXmlStylesheet"), frmReport::OnChange)
EVT_BUTTON(XRCID("btnFile"), frmReport::OnBrowseFile)
EVT_BUTTON(XRCID("btnStylesheet"), frmReport::OnBrowseStylesheet)
EVT_BUTTON(wxID_HELP, frmReport::OnHelp)
EVT_BUTTON(wxID_OK, frmReport::OnOK)
EVT_BUTTON(wxID_CANCEL, frmReport::OnCancel)
END_EVENT_TABLE()
frmReport::frmReport(wxWindow *p)
{
parent = p;
header = wxT("");
SetFont(settings->GetSystemFont());
LoadResource(p, wxT("frmReport"));
// Icon
appearanceFactory->SetIcons(this);
RestorePosition();
btnOK->Disable();
wxString val;
bool bVal;
// Output format
settings->Read(wxT("Reports/ReportFormat"), &val, wxT("h"));
if (val == wxT("x"))
{
rbHtml->SetValue(false);
rbXml->SetValue(true);
}
else
{
rbHtml->SetValue(true);
rbXml->SetValue(false);
}
// HTML Stylesheet
settings->Read(wxT("Reports/HtmlStylesheetMode"), &val, wxT("b"));
if (val == wxT("e"))
{
rbHtmlBuiltin->SetValue(false);
rbHtmlEmbed->SetValue(true);
rbHtmlLink->SetValue(false);
}
else if (val == wxT("l"))
{
rbHtmlBuiltin->SetValue(false);
rbHtmlEmbed->SetValue(false);
rbHtmlLink->SetValue(true);
}
else
{
rbHtmlBuiltin->SetValue(true);
rbHtmlEmbed->SetValue(false);
rbHtmlLink->SetValue(false);
}
// XML Stylesheet
settings->Read(wxT("Reports/XmlStylesheetMode"), &val, wxT("p"));
if (val == wxT("l"))
{
rbXmlPlain->SetValue(false);
rbXmlLink->SetValue(true);
rbXmlProcess->SetValue(false);
}
else if (val == wxT("r"))
{
rbXmlPlain->SetValue(false);
rbXmlLink->SetValue(false);
rbXmlProcess->SetValue(true);
}
else
{
rbXmlPlain->SetValue(true);
rbXmlLink->SetValue(false);
rbXmlProcess->SetValue(false);
}
// Default values
settings->Read(wxT("Reports/LastNotes"), &val, wxT(""));
txtNotes->SetValue(val);
settings->Read(wxT("Reports/LastHtmlStylesheet"), &val, wxEmptyString);
txtHtmlStylesheet->SetValue(val);
settings->Read(wxT("Reports/LastXmlStylesheet"), &val, wxEmptyString);
txtXmlStylesheet->SetValue(val);
settings->Read(wxT("Reports/LastHtmlFile"), &val, wxEmptyString);
txtHtmlFile->SetValue(val);
settings->Read(wxT("Reports/LastXmlFile"), &val, wxEmptyString);
txtXmlFile->SetValue(val);
settings->Read(wxT("Reports/IncludeSQL"), &bVal, true);
chkSql->SetValue(bVal);
chkSql->Disable();
settings->Read(wxT("Reports/OpenInBrowser"), &bVal, true);
chkBrowser->SetValue(bVal);
wxCommandEvent ev;
OnChange(ev);
txtTitle->SetFocus();
}
frmReport::~frmReport()
{
SavePosition();
}
void frmReport::OnHelp(wxCommandEvent &ev)
{
DisplayHelp(wxT("reports"), HELP_PGADMIN);
}
void frmReport::OnChange(wxCommandEvent &ev)
{
bool enable = true;
if (rbHtml->GetValue())
{
// Show/hide the appropriate controls
rbHtmlBuiltin->Show(true);
rbHtmlEmbed->Show(true);
rbHtmlLink->Show(true);
txtHtmlStylesheet->Show(true);
txtHtmlFile->Show(true);
rbXmlPlain->Show(false);
rbXmlLink->Show(false);
rbXmlProcess->Show(false);
txtXmlStylesheet->Show(false);
txtXmlFile->Show(false);
// Enable/disable as appropriate
if (txtHtmlFile->GetValue().IsEmpty())
enable = false;
if (rbHtmlBuiltin->GetValue())
{
txtHtmlStylesheet->Disable();
btnStylesheet->Disable();
}
else
{
txtHtmlStylesheet->Enable();
btnStylesheet->Enable();
}
if (rbHtmlEmbed->GetValue())
{
if (!wxFile::Exists(txtHtmlStylesheet->GetValue()))
enable = false;
}
}
else
{
// Show/hide the appropriate controls
rbHtmlBuiltin->Show(false);
rbHtmlEmbed->Show(false);
rbHtmlLink->Show(false);
txtHtmlStylesheet->Show(false);
txtHtmlFile->Show(false);
rbXmlPlain->Show(true);
rbXmlLink->Show(true);
rbXmlProcess->Show(true);
txtXmlStylesheet->Show(true);
txtXmlFile->Show(true);
// Enable/disable as appropriate
if (txtXmlFile->GetValue().IsEmpty())
enable = false;
if (rbXmlPlain->GetValue())
{
txtXmlStylesheet->Disable();
btnStylesheet->Disable();
}
else
{
txtXmlStylesheet->Enable();
btnStylesheet->Enable();
}
if (rbXmlProcess->GetValue())
{
if (!wxFile::Exists(txtXmlStylesheet->GetValue()))
enable = false;
}
}
btnOK->Enable(enable);
}
void frmReport::OnOK(wxCommandEvent &ev)
{
wxString filename;
if (rbHtml->GetValue())
filename = txtHtmlFile->GetValue();
else
filename = txtXmlFile->GetValue();
wxFileName fn(filename);
fn.MakeAbsolute();
// Check if the file exsits, and if so, whether to overwrite it
if (wxFileExists(fn.GetFullPath()))
{
wxString msg;
msg.Printf(_("The file: \n\n%s\n\nalready exists. Do you want to overwrite it?"), fn.GetFullPath().c_str());
if (wxMessageBox(msg, _("Overwrite file?"), wxYES_NO | wxICON_QUESTION) != wxYES)
{
if (rbHtml->GetValue())
txtHtmlFile->SetFocus();
else
txtXmlFile->SetFocus();
return;
}
}
// Yield, to allow the messagebox to go
wxTheApp->Yield(true);
// Add the title, notes and SQL
if (txtTitle->GetValue() != wxT(""))
XmlAddHeaderValue(wxT("title"), txtTitle->GetValue());
if (txtNotes->GetValue() != wxT(""))
XmlAddHeaderValue(wxT("notes"), txtNotes->GetValue());
// Generate the report data
wxString report;
if (rbHtml->GetValue())
{
if (rbHtmlBuiltin->GetValue())
{
wxString xml = GetXmlReport(wxEmptyString);
wxString xsl = GetDefaultXsl(GetEmbeddedCss(GetDefaultCss()));
report = XslProcessReport(xml, xsl);
}
else if (rbHtmlEmbed->GetValue())
{
wxString xml = GetXmlReport(wxEmptyString);
wxString css = FileRead(txtHtmlStylesheet->GetValue());
if (css.IsEmpty())
{
wxLogError(_("No stylesheet data could be read from the file %s: Errcode=%d."), txtHtmlStylesheet->GetValue().c_str(), wxSysErrorCode());
return;
}
wxString xsl = GetDefaultXsl(GetEmbeddedCss(css));
report = XslProcessReport(xml, xsl);
}
else
{
wxString xml = GetXmlReport(wxEmptyString);
wxString xsl = GetDefaultXsl(GetCssLink(txtHtmlStylesheet->GetValue()));
report = XslProcessReport(xml, xsl);
}
}
else
{
if (rbXmlPlain->GetValue())
{
report = GetXmlReport(wxEmptyString);
}
else if (rbXmlLink->GetValue())
{
report = GetXmlReport(txtXmlStylesheet->GetValue());
}
else
{
wxString xml = GetXmlReport(wxEmptyString);
wxString xsl = FileRead(txtXmlStylesheet->GetValue());
if (xsl.IsEmpty())
{
wxLogError(_("No stylesheet data could be read from the file %s: Errcode=%d."), txtXmlStylesheet->GetValue().c_str(), wxSysErrorCode());
return;
}
report = XslProcessReport(xml, xsl);
}
}
// If report is empty, an error must have occurred
if (report.IsEmpty())
return;
// Save it to disk
wxFile file(fn.GetFullPath(), wxFile::write);
if (!file.IsOpened())
{
wxLogError(_("Failed to open file %s."), fn.GetFullPath().c_str());
return;
}
file.Write(report, wxConvUTF8);
file.Close();
// Open the file in the default browser if required
if (chkBrowser->GetValue())
#ifdef __WXMSW__
wxLaunchDefaultBrowser(fn.GetFullPath());
#else
wxLaunchDefaultBrowser(wxT("file://") + fn.GetFullPath());
#endif
// Save the settings for next time round
settings->Write(wxT("Reports/LastNotes"), txtNotes->GetValue());
if (rbHtml->GetValue())
settings->Write(wxT("Reports/ReportFormat"), wxT("h"));
else
settings->Write(wxT("Reports/ReportFormat"), wxT("x"));
if (rbHtmlBuiltin->GetValue())
settings->Write(wxT("Reports/HtmlStylesheetMode"), wxT("b"));
else if (rbHtmlEmbed->GetValue())
settings->Write(wxT("Reports/HtmlStylesheetMode"), wxT("e"));
else
settings->Write(wxT("Reports/HtmlStylesheetMode"), wxT("l"));
if (rbXmlPlain->GetValue())
settings->Write(wxT("Reports/XmlStylesheetMode"), wxT("p"));
else if (rbXmlLink->GetValue())
settings->Write(wxT("Reports/XmlStylesheetMode"), wxT("l"));
else
settings->Write(wxT("Reports/XmlStylesheetMode"), wxT("r"));
settings->Write(wxT("Reports/LastHtmlStylesheet"), txtHtmlStylesheet->GetValue());
settings->Write(wxT("Reports/LastXmlStylesheet"), txtXmlStylesheet->GetValue());
settings->Write(wxT("Reports/LastHtmlFile"), txtHtmlFile->GetValue());
settings->Write(wxT("Reports/LastXmlFile"), txtXmlFile->GetValue());
settings->WriteBool(wxT("Reports/IncludeSQL"), chkSql->GetValue());
settings->WriteBool(wxT("Reports/OpenInBrowser"), chkBrowser->GetValue());
// Now go away
if (IsModal())
EndModal(wxID_OK);
else
Destroy();
}
void frmReport::OnCancel(wxCommandEvent &ev)
{
if (IsModal())
EndModal(wxID_CANCEL);
else
Destroy();
}
void frmReport::OnBrowseStylesheet(wxCommandEvent &ev)
{
if (rbHtml->GetValue())
{
wxString def = txtHtmlStylesheet->GetValue();
if (!wxFile::Exists(def))
def.Empty();
#ifdef __WXMSW__
wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("HTML Stylesheet files (*.css)|*.css|All files (*.*)|*.*"), wxFD_OPEN);
#else
wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("HTML Stylesheet files (*.css)|*.css|All files (*)|*"), wxFD_OPEN);
#endif
if (file.ShowModal() == wxID_OK)
{
txtHtmlStylesheet->SetValue(file.GetPath());
OnChange(ev);
}
}
else
{
wxString def = txtXmlStylesheet->GetValue();
if (!wxFile::Exists(def))
def.Empty();
#ifdef __WXMSW__
wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("XML Stylesheet files (*.xsl)|*.xsl|All files (*.*)|*.*"), wxFD_OPEN);
#else
wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("XML Stylesheet files (*.xsl)|*.xsl|All files (*)|*"), wxFD_OPEN);
#endif
if (file.ShowModal() == wxID_OK)
{
txtXmlStylesheet->SetValue(file.GetPath());
OnChange(ev);
}
}
}
void frmReport::OnBrowseFile(wxCommandEvent &ev)
{
if (rbHtml->GetValue())
{
#ifdef __WXMSW__
wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtHtmlFile->GetValue(),
_("HTML files (*.html)|*.html|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
#else
wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtHtmlFile->GetValue(),
_("HTML files (*.html)|*.html|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
#endif
if (file.ShowModal() == wxID_OK)
{
txtHtmlFile->SetValue(file.GetPath());
OnChange(ev);
}
}
else
{
#ifdef __WXMSW__
wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtXmlFile->GetValue(),
_("XML files (*.xml)|*.xml|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
#else
wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtXmlFile->GetValue(),
_("XML files (*.xml)|*.xml|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
#endif
if (file.ShowModal() == wxID_OK)
{
txtXmlFile->SetValue(file.GetPath());
OnChange(ev);
}
}
}
void frmReport::SetReportTitle(const wxString &t)
{
txtTitle->SetValue(t);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// START STYLESHEET FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
wxString frmReport::GetCssLink(const wxString &file)
{
wxString data;
data = wxT(" <link rel=\"stylesheet\" href=\"") + file + wxT("\" type=\"text/css\" />\n");
return data;
}
wxString frmReport::GetEmbeddedCss(const wxString &css)
{
wxString data;
data = wxT(" <style type=\"text/css\">\n");
data += css;
data += wxT(" </style>\n");
return data;
}
const wxString frmReport::GetDefaultCss()
{
wxString data;
data = wxT(" body { font-family: verdana, helvetica, sans-serif; margin: 0px; padding: 0; }\n")
wxT(" h1 { font-weight: bold; font-size: 150%; border-bottom-style: solid; border-bottom-width: 2px; margin-top: 0px; padding-bottom: 0.5ex; color: #eeeeee; overflow: hidden; text-overflow: ellipsis; }\n")
wxT(" h2 { font-size: 130%; padding-bottom: 0.5ex; color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; border-bottom-style: solid; border-bottom-width: 2px; }\n")
wxT(" h3 { font-size: 110%; padding-bottom: 0.5ex; color: #000000; }\n")
wxT(" th { text-align: left; background-color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; color: #eeeeee; }\n")
wxT(" #ReportHeader { padding: 10px; background-color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; color: #eeeeee; border-bottom-style: solid; border-bottom-width: 2px; border-color: #999999; }\n")
wxT(" #ReportHeader th { width: 25%; white-space: nowrap; vertical-align: top; }\n")
wxT(" #ReportHeader td { vertical-align: top; color: #eeeeee; }\n")
wxT(" #ReportNotes { padding: 10px; background-color: #eeeeee; font-size: 80%; border-bottom-style: solid; border-bottom-width: 2px; border-color: #999999; }\n")
wxT(" .ReportSQL { margin-bottom: 10px; padding: 10px; display: block; background-color: #eeeeee; font-family: monospace; }\n")
wxT(" #ReportDetails { margin-left: 10px; margin-right: 10px; margin-bottom: 10px; }\n")
wxT(" #ReportDetails td, th { font-size: 80%; margin-left: 2px; margin-right: 2px; }\n")
wxT(" #ReportDetails th { border-bottom-color: #777777; border-bottom-style: solid; border-bottom-width: 2px; }\n")
wxT(" .ReportDetailsOddDataRow { background-color: #dddddd; }\n")
wxT(" .ReportDetailsEvenDataRow { background-color: #eeeeee; }\n")
wxT(" .ReportTableHeaderCell { background-color: #dddddd; color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; vertical-align: top; font-size: 80%; white-space: nowrap; }\n")
wxT(" .ReportTableValueCell { vertical-align: top; font-size: 80%; white-space: nowrap; }\n")
wxT(" .ReportTableInfo { font-size: 80%; font-style: italic; }\n")
wxT(" #ReportFooter { font-weight: bold; font-size: 80%; text-align: right; background-color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; color: #eeeeee; margin-top: 10px; padding: 2px; border-bottom-style: solid; border-bottom-width: 2px; border-top-style: solid; border-top-width: 2px; border-color: #999999; }\n")
wxT(" #ReportFooter a { color: #ffffff; text-decoration: none; }\n");
return data;
}
wxString frmReport::GetDefaultXsl(const wxString &css)
{
wxString data;
data = wxT("<?xml version=\"1.0\"?>\n")
wxT("<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n")
wxT("<xsl:output method=\"xml\" doctype-system=\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\" doctype-public=\"-//W3C//DTD XHTML 1.0 Transitional//EN\" indent=\"yes\" encoding=\"utf-8\" />\n")
wxT("<xsl:template match=\"/report\">\n")
wxT("\n")
wxT("<html>\n")
wxT(" <head>\n")
wxT(" <xsl:if test=\"header/title != ''\">\n")
wxT(" <title><xsl:value-of select=\"header/title\" /></title>\n")
wxT(" </xsl:if>\n")
wxT(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
data += css;
data += wxT(" </head>\n")
wxT("\n")
wxT(" <body>\n")
wxT(" <div id=\"ReportHeader\">\n")
wxT("\n")
wxT(" <xsl:if test=\"header/title != ''\">\n")
wxT(" <h1><xsl:value-of select=\"header/title\" /></h1>\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/generated != ''\">\n")
wxT(" <b>");
data += _("Generated");
data += wxT(": </b><xsl:value-of select=\"header/generated\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/server != ''\">\n")
wxT(" <b>");
data += _("Server");
data += wxT(": </b><xsl:value-of select=\"header/server\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/database != ''\">\n")
wxT(" <b>");
data += _("Database");
data += wxT(": </b><xsl:value-of select=\"header/database\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/catalog != ''\">\n")
wxT(" <b>");
data += _("Catalog");
data += wxT(": </b><xsl:value-of select=\"header/catalog\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/schema != ''\">\n")
wxT(" <b>");
data += _("Schema");
data += wxT(": </b><xsl:value-of select=\"header/schema\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/table != ''\">\n")
wxT(" <b>");
data += _("Table");
data += wxT(": </b><xsl:value-of select=\"header/table\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/job != ''\">\n")
wxT(" <b>");
data += _("Job");
data += wxT(": </b><xsl:value-of select=\"header/job\" /><br />\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" </div>\n")
wxT("\n")
wxT(" <xsl:if test=\"header/notes != ''\">\n")
wxT(" <div id=\"ReportNotes\">\n")
wxT(" <b>");
data += _("Notes");
data += wxT(": </b><br /><br />\n")
wxT(" <xsl:call-template name=\"substitute\">\n")
wxT(" <xsl:with-param name=\"string\" select=\"header/notes\" />\n")
wxT(" </xsl:call-template>\n")
wxT(" </div>\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <div id=\"ReportDetails\">\n")
wxT(" <xsl:apply-templates select=\"section\" >\n")
wxT(" <xsl:sort select=\"@number\" data-type=\"number\" order=\"ascending\" />\n")
wxT(" </xsl:apply-templates>\n")
wxT(" </div>\n")
wxT("\n")
wxT(" <div id=\"ReportFooter\">\n");
data += _("Report generated by");
data += wxT(" <a href=\"");
data += HtmlEntities(appearanceFactory->GetWebsiteUrl());
data += wxT("\">");
data += HtmlEntities(appearanceFactory->GetLongAppName());
data += wxT("</a>\n")
wxT(" </div>\n")
wxT("\n")
wxT(" <br />\n")
wxT(" </body>\n")
wxT("</html>\n")
wxT("\n")
wxT("</xsl:template>\n")
wxT("\n")
wxT("<xsl:template match=\"section\">\n")
wxT(" <xsl:if test=\"../section[@id = current()/@id]/@name != ''\">\n")
wxT(" <h2><xsl:value-of select=\"../section[@id = current()/@id]/@name\" /></h2>\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"count(../section[@id = current()/@id]/table/columns/column) > 0\">\n")
wxT(" <div style=\"overflow:auto;\">\n")
wxT(" <table>\n")
wxT(" <tr>\n")
wxT(" <xsl:apply-templates select=\"../section[@id = current()/@id]/table/columns/column\">\n")
wxT(" <xsl:sort select=\"@number\" data-type=\"number\" order=\"ascending\" />\n")
wxT(" <xsl:with-param name=\"count\" select=\"count(../section[@id = current()/@id]/table/columns/column)\" />\n")
wxT(" </xsl:apply-templates>\n")
wxT(" </tr>\n")
wxT(" <xsl:apply-templates select=\"../section[@id = current()/@id]/table/rows/*\" mode=\"rows\">\n")
wxT(" <xsl:sort select=\"@number\" data-type=\"number\" order=\"ascending\" />\n")
wxT(" <xsl:with-param name=\"column-meta\" select=\"../section[@id = current()/@id]/table/columns/column\" />\n")
wxT(" </xsl:apply-templates>\n")
wxT(" </table>\n")
wxT(" </div>\n")
wxT(" <br />\n")
wxT(" <xsl:if test=\"../section[@id = current()/@id]/table/info != ''\">\n")
wxT(" <p class=\"ReportTableInfo\"><xsl:value-of select=\"../section[@id = current()/@id]/table/info\" /></p>\n")
wxT(" </xsl:if>\n")
wxT(" </xsl:if>\n")
wxT("\n")
wxT(" <xsl:if test=\"../section[@id = current()/@id]/sql != ''\">\n")
wxT(" <pre class=\"ReportSQL\">\n")
wxT(" <xsl:call-template name=\"substitute\">\n")
wxT(" <xsl:with-param name=\"string\" select=\"../section[@id = current()/@id]/sql\" />\n")
wxT(" </xsl:call-template>\n")
wxT(" </pre>\n")
wxT(" </xsl:if>\n")
wxT("</xsl:template>\n")
wxT("\n")
wxT("<xsl:template match=\"column\">\n")
wxT(" <xsl:param name=\"count\" />\n")
wxT(" <th class=\"ReportTableHeaderCell\">\n")
wxT(" <xsl:attribute name=\"width\"><xsl:value-of select=\"100 div $count\" />%</xsl:attribute>\n")
wxT(" <xsl:call-template name=\"substitute\">\n")
wxT(" <xsl:with-param name=\"string\" select=\"@name\" />\n")
wxT(" </xsl:call-template>\n")
wxT(" </th>\n")
wxT("</xsl:template>\n")
wxT("\n")
wxT("<xsl:template match=\"*\" mode=\"rows\">\n")
wxT(" <xsl:param name=\"column-meta\" />\n")
wxT(" <tr>\n")
wxT(" <xsl:choose>\n")
wxT(" <xsl:when test=\"position() mod 2 != 1\">\n")
wxT(" <xsl:attribute name=\"class\">ReportDetailsOddDataRow</xsl:attribute>\n")
wxT(" </xsl:when>\n")
wxT(" <xsl:otherwise>\n")
wxT(" <xsl:attribute name=\"class\">ReportDetailsEvenDataRow</xsl:attribute>\n")
wxT(" </xsl:otherwise>\n")
wxT(" </xsl:choose>\n")
wxT(" <xsl:apply-templates select=\"$column-meta\" mode=\"cells\">\n")
wxT(" <xsl:with-param name=\"row\" select=\".\" />\n")
wxT(" </xsl:apply-templates>\n")
wxT(" </tr>\n")
wxT("</xsl:template>\n")
wxT("\n")
wxT("<xsl:template match=\"*\" mode=\"cells\">\n")
wxT(" <xsl:param name=\"row\" />\n")
wxT(" <td class=\"ReportTableValueCell\">\n")
wxT(" <xsl:choose>\n")
wxT(" <xsl:when test=\"$row/@*[name() = current()/@id]|$row/*[name() = current()/@id] != ''\">\n")
wxT(" <xsl:call-template name=\"substitute\">\n")
wxT(" <xsl:with-param name=\"string\" select=\"$row/@*[name() = current()/@id]|$row/*[name() = current()/@id]\" />\n")
wxT(" </xsl:call-template>\n")
wxT(" </xsl:when>\n")
wxT(" <xsl:otherwise>\n")
wxT(" <xsl:text> </xsl:text>\n")
wxT(" </xsl:otherwise>\n")
wxT(" </xsl:choose>\n")
wxT(" </td>\n")
wxT("</xsl:template>\n")
wxT("\n")
wxT("<xsl:template name=\"substitute\">\n")
wxT(" <xsl:param name=\"string\" />\n")
wxT(" <xsl:param name=\"from\" select=\"'&#xA;'\" />\n")
wxT(" <xsl:param name=\"to\">\n")
wxT(" <br />\n")
wxT(" </xsl:param>\n")
wxT(" <xsl:choose>\n")
wxT(" <xsl:when test=\"contains($string, $from)\">\n")
wxT(" <xsl:value-of select=\"substring-before($string, $from)\" />\n")
wxT(" <xsl:copy-of select=\"$to\" />\n")
wxT(" <xsl:call-template name=\"substitute\">\n")
wxT(" <xsl:with-param name=\"string\" select=\"substring-after($string, $from)\" />\n")
wxT(" <xsl:with-param name=\"from\" select=\"$from\" />\n")
wxT(" <xsl:with-param name=\"to\" select=\"$to\" />\n")
wxT(" </xsl:call-template>\n")
wxT(" </xsl:when>\n")
wxT(" <xsl:otherwise>\n")
wxT(" <xsl:value-of select=\"$string\" />\n")
wxT(" </xsl:otherwise>\n")
wxT(" </xsl:choose>\n")
wxT("</xsl:template>\n")
wxT("\n")
wxT("</xsl:stylesheet>\n");
return data;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END STYLESHEET FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// START XML FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void frmReport::XmlAddHeaderValue(const wxString &name, const wxString &value)
{
header += wxT(" <") + HtmlEntities(name) + wxT(">") + HtmlEntities(value) + wxT("</") + HtmlEntities(name) + wxT(">\n");
}
int frmReport::XmlCreateSection(const wxString &name)
{
int ind = sectionName.Add(HtmlEntities(name));
sectionData.Add(wxT(""));
sectionTableHeader.Add(wxT(""));
sectionTableRows.Add(wxT(""));
sectionTableInfo.Add(wxT(""));
sectionSql.Add(wxT(""));
return ind + 1;
}
void frmReport::XmlSetSectionTableHeader(const int section, int columns, const wxChar *name, ...)
{
va_list ap;
const wxChar *p = name;
wxString data;
va_start(ap, name);
for (int x = 0; x < columns; x++)
{
data += wxT(" <column id=\"c");
data += NumToStr((long)(x + 1));
data += wxT("\" number=\"");
data += NumToStr((long)(x + 1));
data += wxT("\" name=\"");
data += HtmlEntities(p);
data += wxT("\"/>\n");
p = va_arg(ap, wxChar *);
}
va_end(ap);
sectionTableHeader[section - 1] = data;
}
void frmReport::XmlAddSectionTableRow(const int section, int number, int columns, const wxChar *value, ...)
{
va_list ap;
const wxChar *p = value;
wxString data;
va_start(ap, value);
data = wxT(" <row id=\"r");
data += NumToStr((long)number);
data += wxT("\" number=\"");
data += NumToStr((long)number);
data += wxT("\"");
for (int x = 0; x < columns; x++)
{
data += wxT(" c");
data += NumToStr((long)(x + 1));
data += wxT("=\"");
data += HtmlEntities(p);
data += wxT("\"");
p = va_arg(ap, wxChar *);
}
data += wxT(" />\n");
va_end(ap);
sectionTableRows[section - 1] += data;
}
void frmReport::XmlAddSectionTableFromListView(const int section, ctlListView *list)
{
// Get the column headers
int cols = list->GetColumnCount();
wxString data;
wxListItem itm;
// Build the columns
for (int x = 0; x < cols; x++)
{
itm.SetMask(wxLIST_MASK_TEXT);
list->GetColumn(x, itm);
wxString label = itm.GetText();
data += wxT(" <column id=\"c");
data += NumToStr((long)(x + 1));
data += wxT("\" number=\"");
data += NumToStr((long)(x + 1));
data += wxT("\" name=\"");
data += HtmlEntities(label);
data += wxT("\" />\n");
}
sectionTableHeader[section - 1] = data;
// Build the rows
int rows = list->GetItemCount();
for (int y = 0; y < rows; y++)
{
data = wxT(" <row id=\"r");
data += NumToStr((long)(y + 1));
data += wxT("\" number=\"");
data += NumToStr((long)(y + 1));
data += wxT("\"");
for (int x = 0; x < cols; x++)
{
data += wxT(" c");
data += NumToStr((long)(x + 1));
data += wxT("=\"");
data += HtmlEntities(list->GetText(y, x));
data += wxT("\"");
}
data += wxT(" />\n");
sectionTableRows[section - 1] += data;
}
}
void frmReport::XmlAddSectionTableFromGrid(const int section, ctlSQLResult *grid)
{
// Get the column headers
int cols = grid->GetNumberCols();
int shift = 0;
wxString data;
wxListItem itm;
if (grid->GetRowCountSuppressed())
shift = 1;
for (int x = 1; x <= cols; x++)
{
wxString label = grid->OnGetItemText(-1, x - shift);
data += wxT(" <column id=\"c");
data += NumToStr((long)(x));
data += wxT("\" number=\"");
data += NumToStr((long)(x));
data += wxT("\" name=\"");
data += HtmlEntities(label);
data += wxT("\" />\n");
}
sectionTableHeader[section - 1] = data;
// Build the rows
int rows = grid->NumRows();
for (int y = 0; y < rows; y++)
{
data = wxT(" <row id=\"r");
data += NumToStr((long)(y + 1));
data += wxT("\" number=\"");
data += NumToStr((long)(y + 1));
data += wxT("\"");
for (int x = 1; x <= cols; x++)
{
data += wxT(" c");
data += NumToStr((long)(x));
data += wxT("=\"");
data += HtmlEntities(grid->OnGetItemText(y, x - shift));
data += wxT("\"");
}
data += wxT(" />\n");
sectionTableRows[section - 1] += data;
}
}
void frmReport::XmlSetSectionSql(int section, const wxString &sql)
{
sectionSql[section - 1] = HtmlEntities(sql);
if (!sectionSql[section - 1].IsEmpty())
chkSql->Enable();
else
chkSql->Disable();
}
void frmReport::XmlAddSectionValue(const int section, const wxString &name, const wxString &value)
{
sectionData[section - 1] += wxT(" <") + HtmlEntities(name) + wxT(">") + HtmlEntities(value) + wxT("</") + HtmlEntities(name) + wxT(">\n");
}
wxString frmReport::GetSectionTableColumns(const int section)
{
wxString data;
data = wxT(" <columns>\n");
data += sectionTableHeader[section - 1];
data += wxT(" </columns>\n");
return data;
}
wxString frmReport::GetSectionTableRows(const int section)
{
wxString data;
data = wxT(" <rows>\n");
data += sectionTableRows[section - 1];
data += wxT(" </rows>\n");
return data;
}
wxString frmReport::GetSectionTable(const int section)
{
wxString data;
data = wxT(" <table>\n");
data += GetSectionTableColumns(section);
data += GetSectionTableRows(section);
if (!sectionTableInfo[section - 1].IsEmpty())
{
data += wxT(" <info>");
data += sectionTableInfo[section - 1];
data += wxT("</info>\n");
}
data += wxT(" </table>\n");
return data;
}
wxString frmReport::GetSection(const int section)
{
wxString data;
data = wxT(" <section id=\"s");
data += NumToStr((long)section);
data += wxT("\" number=\"");
data += NumToStr((long)section);
data += wxT("\" name=\"");
data += sectionName[section - 1];
data += wxT("\">\n");
data += GetSectionTable(section);
if (chkSql->GetValue() && !sectionSql[section - 1].IsEmpty())
{
data += wxT(" <sql>");
data += sectionSql[section - 1];
data += wxT("</sql>\n");
}
data += sectionData[section - 1];
data += wxT(" </section>\n");
return data;
}
wxString frmReport::GetXmlReport(const wxString &stylesheet = wxT(""))
{
wxString data;
data = wxT("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
if (!stylesheet.IsEmpty())
{
data += wxT("<?xml-stylesheet type=\"text/xsl\" href=\"");
data += stylesheet;
data += wxT("\" ?>\n");
}
data += wxT("\n");
data += wxT("<report>\n\n");
data += wxT(" <header>\n");
data += header;
data += wxT(" </header>\n\n");
for (unsigned int x = 1; x <= sectionName.GetCount(); x++ )
{
data += GetSection(x);
data += wxT("\n");
}
data += wxT("</report>\n");
return data;
}
//
// libxml convenience macros
//
#define XML_FROM_WXSTRING(s) ((xmlChar *)(const char *)s.mb_str(wxConvUTF8))
#define WXSTRING_FROM_XML(s) wxString((char *)s, wxConvUTF8)
wxString frmReport::XslProcessReport(const wxString &xml, const wxString &xsl)
{
xmlChar *output = 0;
xmlDocPtr ssDoc = 0, xmlDoc = 0, resDoc = 0;
xsltStylesheetPtr ssPtr = 0;
int length;
wxBeginBusyCursor();
// Apply the stylesheet
xmlSubstituteEntitiesDefault (1); // Substitute entities
xmlLoadExtDtdDefaultValue = 1; // Load external entities
// Parse the stylesheet
ssDoc = xmlParseDoc(XML_FROM_WXSTRING(xsl));
if (!ssDoc)
{
wxEndBusyCursor();
wxLogError(_("Failed to parse the XML stylesheet!"));
goto cleanup;
}
ssPtr = xsltParseStylesheetDoc(ssDoc);
if (!ssPtr)
{
wxEndBusyCursor();
wxLogError(_("Failed to parse the XSL stylesheet!"));
goto cleanup;
}
// Parse the data
xmlDoc = xmlParseDoc(XML_FROM_WXSTRING(xml));
if (!xmlDoc)
{
wxEndBusyCursor();
wxLogError(_("Failed to parse the XML document!"));
goto cleanup;
}
// Apply the stylesheet
resDoc = xsltApplyStylesheet(ssPtr, xmlDoc, NULL);
if (!resDoc)
{
wxEndBusyCursor();
wxLogError(_("Failed to apply the XSL stylesheet to the XML document!"));
goto cleanup;
}
// Get the result
xsltSaveResultToString (&output, &length, resDoc, ssPtr);
if (!resDoc)
{
wxEndBusyCursor();
wxLogError(_("Failed to read the processed document!"));
goto cleanup;
}
cleanup:
// Cleanup
if (resDoc)
xmlFreeDoc(resDoc);
if (xmlDoc)
xmlFreeDoc(xmlDoc);
if (ssPtr)
xsltFreeStylesheet(ssPtr);
// This crashes - dunno why :-(
// if (ssDoc)
// xmlFreeDoc(ssDoc);
xsltCleanupGlobals();
wxEndBusyCursor();
if (output)
return WXSTRING_FROM_XML(output);
else
return wxEmptyString;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END XML FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SQL::SQL(const wxString &_sql, const wxString &_pathtree) {
// Construct a SQL with the specified operation and text.
sql=wxString(_sql);
pathtree=wxString(_pathtree) ;
countchild=0;
mode=0;
}
SQL::SQL() {
}
/**
* Display a human-readable version of this SQL.
* @return text version
*/
wxString SQL::toString() const {
wxString prettyText = sql;
// Replace linebreaks with Pilcrow signs.
//prettyText.replace('\n', L'\u00b6');
wxString c=wxEmptyString;
wxString cmp=wxEmptyString;
if (countchild>0) c.Printf(wxT("(%d)"), countchild);
bool r=false;
if (sql.Cmp(sql2)!=0) {
cmp="ne EQ ";
cmp.Printf(wxT("(ne EQ (%d, %d))"), sql.Len(),sql2.Len());
}
if (mode==__Remove) cmp=cmp+" - ";
if (mode==__Insert) cmp=cmp+" + ";
if (mode==__Equal) cmp=cmp+" = ";
return wxString(pathtree+c+"\n"+cmp+"SQL(" + wxString("\""))
+ prettyText + wxString("\")");
}
/**
* Is this SQL equivalent to another SQL?
* @param d Another SQL to compare against
* @return true or false
*/
bool SQL::operator==(const SQL &d) const {
return (d.sql == this->sql);
}
bool SQL::operator!=(const SQL &d) const {
return !(operator == (d));
}
#include <wx/listimpl.cpp>
WX_DEFINE_LIST(MyListSql);
#include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(ArraySQL)
wxString reportCompareFactory::GetNodePath(wxTreeItemId node) {
wxString path;
path = parent->GetBrowser()->GetItemText(node).Trim();
wxTreeItemId parent_id = parent->GetBrowser()->GetItemParent(node);
while (parent_id.IsOk())
{
path = parent->GetBrowser()->GetItemText(parent_id).BeforeFirst('(').Trim() + wxT("/") + path;
parent_id = parent->GetBrowser()->GetItemParent(parent_id);
}
return path;
}
wxString reportCompareFactory::ApplyCompareOpts(wxString sql,int metatype) {
if (sql.IsEmpty()) return "";
bool no_comment = parent->getChoiceSelect(1);
bool no_priv = parent->getChoiceSelect(0);
if (no_comment) {
int last = 0;
while (last!=-1) {
last = sql.Find("\nCOMMENT ON");
int start = last;
int end = -1;
while (last!=-1) {
last++;
if (sql.Length() == last) { last = -1; continue; }
wxChar c = sql.GetChar(last);
if (c == '\'') {
last++;
if (sql.GetChar(last) == '\'') { continue; }
if (sql.GetChar(last) == ';') { end = last; last = -1; continue; }
}
};
if (end != -1) {
sql=sql.Remove(start, end - start+1);
last = 0;
}
}
}
if (no_priv &&(metatype != PGM_ROLE)) {
int last = 0;
while (last != -1) {
last = sql.Find("\nGRANT ");
if (last==-1) last = sql.Find("\nREVOKE ");
int start = last;
int end = -1;
while (last != -1) {
last++;
if (sql.Length() == last) { last = -1; continue; }
wxChar c = sql.GetChar(last);
if (c == ';') {
end = last; last = -1;
}
};
if (end != -1) {
sql = sql.Remove(start, end - start + 1);
last = 0;
}
}
}
return sql;
}
void reportCompareFactory::GetExpandedChildNodes(wxTreeItemId node, wxArrayString &expandedNodes, ArraySQL &list, time_t *t, wxBusyInfo *w, MyHashSQL &h_path,int lvl)
{
wxTreeItemIdValue cookie;
ctlTree *browser=parent->GetBrowser();
wxTreeItemId child;
if (lvl==0) child = node;
else child = browser->GetFirstChild(node, cookie);
pgObject *obj;
wxString path;
time_t tmp;
int size=expandedNodes.Count();
while (child.IsOk())
{
obj=browser->GetObject(child);
if (obj && obj->GetMetaType()==PGM_FUNCTION && !browser->HasChildren(child))
path=GetNodePath(child);
else
path=parent->GetNodePath(child);
// tmp=wxDateTime::GetTimeNow();
// if (difftime(tmp,*t)>2.0) {
//w->~wxBusyInfo();
//wxSafeYield();
//wxMilliSleep(50);
//wxSafeYield();
//w = new wxBusyInfo(wxString::Format("Path = %s ,GetName() = %s, isCollection = %d",
// path.c_str(), obj->GetName().c_str(), obj->IsCollection()),parent);
//wxSafeYield();
//wxMilliSleep(50);
//wxSafeYield();
// *t=tmp;
// }
if (obj) {
// OutputDebugString(wxString::Format("Path = %s ,GetName() = %s, isCollection = %d\n",
// path.c_str(), obj->GetTypeName().c_str(), obj->IsCollection()));
if (obj->GetMetaType()==PGM_CATALOG
||obj->GetMetaType()==PGM_COLUMN
||obj->GetMetaType()==PGM_RULE
||obj->GetMetaType()==PGM_CATALOG
) {
child = browser->GetNextChild(node, cookie);
continue;
}
//obj->ShowTreeDetail(browser);
//obj->ShowTree(parent,browser);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ((obj->GetMetaType()==PGM_SCHEMA
||obj->GetMetaType()==PGM_DATABASE
||obj->GetMetaType()==PGM_TABLE
||obj->GetMetaType()==PGM_FOREIGNTABLE
)&&!obj->IsCollection()) {
obj->ShowTreeDetail(browser);
//obj->ShowTree(parent,browser);
} else
{
if (obj->GetMetaType()==PGM_VIEW) obj->ShowTreeDetail(browser); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (obj->GetMetaType()==PGM_EVENTTRIGGER) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
obj->ShowTreeDetail(browser);
}
}
//if (browser->IsExpanded(child))
if (browser->HasChildren(child))
{
bool rec=true;
if (obj && (obj->GetMetaType()==PGM_TABLE
//||obj->GetMetaType()==PGM_VIEW
)) {
wxTreeItemId Item = browser->GetItemParent(child);
obj=browser->GetObject(Item); // Tables
wxTreeItemId Item2 = browser->GetItemParent(obj->GetId());
obj=browser->GetObject(Item2); // Schemes
if (obj && obj->GetMetaType()==PGM_SCHEMA&& !obj->IsCollection()) {
rec=false; // <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
obj=browser->GetObject(child);
obj->ShowTreeDetail(browser);
} else obj=browser->GetObject(child);
}
if (obj && (obj->GetMetaType()==PGM_VIEW && !obj->IsCollection())) rec=false;
if (rec) {
GetExpandedChildNodes(child, expandedNodes,list,t,w,h_path,lvl+1);
//expandedNodes.Add(parent->GetNodePath(child));
obj=browser->GetObject(child);
}
}
if (obj ) {
wxString s=obj->GetSql(browser);
if (obj->GetMetaType()==PGM_SEQUENCE) s="";
s = ApplyCompareOpts(s, obj->GetMetaType());
int c=browser->GetChildrenCount(child,false);
if (size>0) {
wxString srcpath(path);
SQL *sq;
srcpath.Replace(expandedNodes[0],expandedNodes[2],false);
srcpath.Replace(expandedNodes[1],expandedNodes[3],false);
MyHashSQL::iterator it=h_path.find(srcpath);
if (h_path.end()==it) {
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
if (s!=wxEmptyString) {
sq =new SQL(wxEmptyString,srcpath);
sq->sql2=s;
sq->mode=__Remove;
list.Add(sq);
} else
{
sq =new SQL(wxEmptyString,srcpath);
sq->sql2=wxEmptyString;
sq->countchild=c;
sq->mode=__Remove;
list.Add(sq);
}
h_path[srcpath]=list.GetCount()-1;
}
else {
int i=it->second;
SQL& sql=list.Item(i);
sql.mode=__Equal;
sql.sql2=s;
}
} else {
if (s!=wxEmptyString) {
SQL *sq =new SQL(s,path);
sq->mode=__Insert;
list.Add(sq);
} else
{
SQL *sq =new SQL(s,path);
sq->countchild=c;
sq->mode=__Insert;
list.Add(sq);
}
h_path[path]=list.GetCount()-1;
}
}
child = browser->GetNextChild(node, cookie);
}
}
wxWindow *reportCompareFactory::StartDialog(frmMain *form, pgObject *obj)
{
parent = form;
// std::wstring r;
// std::wstring str1=L"";
// std::wstring str2=L"line#\nline2\nADD line 3\nline4\n";
// r=printdiff(str1,str2);
// return 0;
// wxBeginBusyCursor();
//frmReport *report = new frmReport(GetFrmMain());
//wxBusyInfo *waiting;
wxString msg;
// Generate the report header
wxDateTime now = wxDateTime::Now();
ctlTree *browser=form->GetBrowser();
wxTreeItemIdValue foldercookie;
wxTreeItemId folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
wxString path(form->GetNodePath(obj->GetId()));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/serverN/Datebases/dbname
// p1 p2 p3
wxString p_db;
int p1=path.Find('/');
if (p1<0) return 0;
int p2=path.find('/',p1+1);
if (p2<0) return 0;
startpathpos=p2;
int p3=path.find('/',p2+1);
wxString p_pref=path.substr(0,p2);
wxString p_server_obj;
if (!obj->GetConnection()) return 0;
if (obj && obj->GetDatabase() && obj->GetDatabase()->GetConnected())
p_db=obj->GetDatabase()->GetName();
else
p_db=obj->GetServer()->GetDatabaseName();
if (p3<0) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//if (wxMessageBox(wxString::Format("Path = %s ,GetName() = %s, isCollection = %d",
// path.c_str(), obj->GetTypeName().c_str(), obj->IsCollection()), _("Close"), wxYES_NO | wxICON_QUESTION) != wxYES)
//{
// return 0;
//}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/PostgreSQL 9.6
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
p_server_obj=path.substr(p2); // <20> /<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>N/
} else
{
// <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/PostgreSQL 9.6/<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/postgres
p_server_obj=path.substr(p2,p3-p2); // <20> /<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>N/
}
wxString p_db_replace=_("Databases")+"/"+p_db+"/";
wxString p_server_replace=_("Servers")+p_server_obj;
pgServer *server;
pgDatabase *db=NULL,*lastdb=NULL;
wxString trg_db_replace;
wxString trg_server_replace;
wxTreeItemId srvitem = obj->GetServer()->GetId();
while (folderitem)
{
if (browser->ItemHasChildren(folderitem))
{
wxTreeItemIdValue servercookie;
wxTreeItemId serveritem = browser->GetFirstChild(folderitem, servercookie);
while (serveritem)
{
server = (pgServer *)browser->GetItemData(serveritem);
if (server != NULL && server->IsCreatedBy(serverFactory))
{
trg_server_replace=browser->GetItemText(server->GetId()).BeforeFirst('(').Trim();
if (srvitem!=server->GetId() && server->GetConnected()) {
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pgCollection *coll = browser->FindCollection(databaseFactory, server->GetId());
if (coll)
{
treeObjectIterator dbs(browser, coll);
while ((db = (pgDatabase *)dbs.GetNextObject()) != 0)
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
lastdb=db;
if (db->GetConnected()) {
//if (db->GetName()!=wxT("postgres")) goto ex_out;
goto ex_out;
}
}
}
}
}
serveritem = browser->GetNextChild(folderitem, servercookie);
}
}
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
ex_out:
pgObject *trgobj;
wxString newpath;
if (lastdb!=NULL) {
p_db=browser->GetItemText(lastdb->GetId()).BeforeFirst('(').Trim();
trg_db_replace=_("Databases")+"/"+p_db+"/";
trg_server_replace=_("Servers")+"/"+trg_server_replace;
newpath=path;
//if (newpath.Replace(p_server_replace,trg_server_replace,false)==0)
newpath.Replace(p_server_replace,trg_server_replace,false);
newpath.Replace(p_db_replace,trg_db_replace,false);
if (!parent->SetCurrentNode(parent->GetBrowser()->GetRootItem(),newpath)) {
msg.Printf("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %s <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>.",newpath);
wxMessageBox(msg, _("Error"), wxOK | wxICON_INFORMATION);
return 0;
}
trgobj=browser->GetObject(browser->GetSelection());
} else
{
msg="<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> , <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.";
// msg.Printf("<22> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %s, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>.",browser->GetItemText(lastdb->GetServer()->GetId()).BeforeFirst('(').Trim());
wxMessageBox(msg, _("Error"), wxOK | wxICON_INFORMATION);
return 0;
}
if (!parent->StartChoiceDialog()) return 0;
time_t timer=wxDateTime::GetTimeNow();
wxArrayString expandedNodes;
ArraySQL list;
MyHashSQL h_path;
wxWindowDisabler disableAll;
{
#ifndef DEBUG
wxBusyInfo waiting(wxString::Format(" <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Path = %s ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = %s",
browser->GetItemText(obj->GetServer()->GetId()).c_str(), obj->GetName().c_str(),parent));
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(50);
wxSafeYield();
#endif
// waiting->~wxBusyInfo();
GetExpandedChildNodes(obj->GetId(),expandedNodes,list,&timer, NULL,h_path,0);
}
//waiting->~wxBusyInfo();
wxFileName fn("");
fn.MakeAbsolute();
wxSafeYield();
wxMilliSleep(50);
wxSafeYield();
// return 0;
{
wxBusyInfo waiting(wxString::Format(" <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Path = %s\n<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = %s",
browser->GetItemText(trgobj->GetId()).c_str(), trgobj->GetName().c_str(),parent));
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(50);
wxSafeYield();
timer=wxDateTime::GetTimeNow();
wxArrayString expandedNodes2;
expandedNodes2.Add(trg_server_replace);
expandedNodes2.Add(trg_db_replace);
expandedNodes2.Add(p_server_replace);
expandedNodes2.Add(p_db_replace);
GetExpandedChildNodes(trgobj->GetId(),expandedNodes2,list,&timer, NULL,h_path,0);
}
//waiting->~wxBusyInfo();
int e_count=list.GetCount();
int linecount=0;
int nstart=0,lastpos=0;
int c,minlen=100000,root=0;
wxArrayInt* child;
wxArrayPtrVoid level(15);
wxHashTable htab(wxKEY_STRING);
wxString key;
int npos=p2;
for (int i = 0; i < e_count; ++i)
{
SQL& sq = list.Item(i);
c=0;
nstart=0;
if ((nstart=sq.pathtree.rfind('/'))!=wxNOT_FOUND ) {
key=sq.pathtree.SubString(npos,nstart-1);
if (minlen>key.Len()) {minlen=key.Len(); root=i;}
}
child=(wxArrayInt *)htab.Get(key);
if (child==NULL) {
child=new wxArrayInt;
htab.Put(key,(wxObject *)child);
}
child->Add(i);
linecount++;
}
MyListSql::iterator iter2;
//e_count=list.GetCount();
//for (int i = 0; i < e_count; ++i)
//{
// SQL& sq = list.Item(i);
//}
// file2.Write(report, wxConvUTF8);
// file2.Close();
//return 0;
titleline=wxEmptyString;
list_head=wxEmptyString;
rowlist=wxEmptyString;
list_end=wxEmptyString;
tableheader=wxEmptyString;
head=wxEmptyString;
tableheader2=wxEmptyString;
tableshtml=wxEmptyString;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#ifndef _DEBUG
wxString fDir=wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\')+wxT("\\");
#else
wxString fDir=wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\')+wxT("\\");
#endif
wxString f=fDir+"textcompare_report.template";
wxString buffer;
wxUtfFile file3(f, wxFile::read, wxFONTENCODING_UTF8);
if (file3.IsOpened())
{
file3.Read(buffer);
file3.Close();
} else
{
wxLogError(_("Failed to open file %s."), f.c_str());
return 0;
}
buffer.Replace('\r',wxEmptyString,true);
wxStringTokenizer lines(buffer, wxT("\n"));
Diff_EditCost=4;
Match_Threshold=0.5;
Match_Distance=1000;
bool mline=false;
while (lines.HasMoreTokens())
{
wxString tmp = lines.GetNextToken();
//if (tmp.length()>0 && tmp[tmp.length()-1]=='\r') tmp.RemoveLast();
wxString line = tmp.Strip(wxString::both);
if (tmp.StartsWith("@end@")) break;
int l=wxString("@titleline").Len();
if (tmp.StartsWith("@titleline")) {titleline=tmp.Mid(l)+"\n"; continue;}
l=wxString("@[list").Len();
if (tmp.StartsWith("@[list")) {list_head=tmp.Mid(l)+"\n"; continue;}
l=wxString("@]list").Len();
if (tmp.StartsWith("@]list")) {list_end=tmp.Mid(l)+"\n"; continue;}
l=wxString("@rowlist").Len();
if (tmp.StartsWith("@rowlist")) {rowlist=tmp.Mid(l)+"\n"; continue;}
l=wxString("@tableheader2").Len();
if (tmp.StartsWith("@tableheader2")) {tableheader2=tmp.Mid(l)+"\n"; continue;}
if (tmp==wxString("@tableheader@")) {mline=!mline; continue;}
if (mline) { tableheader+=tmp+"\n";continue;}
// diff config
if (tmp.StartsWith("@Match_Distance=")) {Match_Distance=(int)StrToDouble(tmp.After('=')); continue;}
if (tmp.StartsWith("@Diff_EditCost=")) {Diff_EditCost=StrToDouble(tmp.After('=')); continue;}
if (tmp.StartsWith("@Match_Threshold=")) {Match_Threshold=(float)StrToDouble(tmp.After('=')); continue;}
head+=tmp+"\n";
}
//
{
wxBusyInfo waiting(wxString::Format(" <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ...",0));
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(50);
wxSafeYield();
wxString content=printlvl(root,0,list,htab);
wxString tmp(titleline);
tmp.Replace("$titleline$","Left : "+path);
wxString tmp2(titleline);
tmp2.Replace("$titleline$","Right: "+newpath);
head.Replace("$titleline$",tmp+tmp2);
head.Replace("$list$",content);
head.Replace("$tables$",tableshtml);
tableshtml=wxEmptyString;
content=wxEmptyString;
}
//head+="</div></body></html>";
fDir=wxStandardPaths::Get().GetTempDir()+wxT("\\cmp.html");
//fn="D:\\PostgreSQL\\cmp.html";
fn=fDir;
fn.MakeAbsolute();
wxString html(head);
wxFile file4(fn.GetFullPath(), wxFile::write);
if (!file4.IsOpened())
{
wxLogError(_("Failed to open file %s."), fn.GetFullPath().c_str());
return 0;
}
file4.Write(html, wxConvUTF8);
file4.Close();
head=wxEmptyString;
list.RemoveAt(0,list.GetCount());
e_count=list.GetCount();
for (int i = 0; i < e_count; ++i)
{
//SQL *p=&sq;
//list.RemoveAt(0,list.GetCount());
// SQL *p = list.Detach(i);
// delete p;
}
//htab.DeleteContents(true);
h_path.clear();
//MyHashSQL::iterator it, en;
//for( it = h_path.begin(), en = h_path.end(); it != en; ++it )
//{
// h_path.erase(it);
//}
//htab.Clear();
//list.Empty();
#ifdef __WXMSW__
wxLaunchDefaultBrowser(fn.GetFullPath());
#else
wxLaunchDefaultBrowser(wxT("file://") + fn.GetFullPath());
#endif
return 0;
}
#if defined(DELETE)
#undef DELETE
#endif // DUMMYSTRUCTNAME
std::wstring reportCompareFactory::printdiff(std::wstring str1, std::wstring str2 )
{
diff_match_patch dmp(Diff_EditCost,Match_Threshold,Match_Distance);
std::list<Diff> diffs;
if (str1==str2) {
return L"";
}
diffs=dmp.diff_main(str1,str2);
int nstart=0;
int pos=0;
countdiffline=0;
std::wstring cur_l;
std::wstring ncur_l; std::wstring p_ncur_l;std::wstring p_ncur_r;
std::wstring cur_r;
std::wstring ncur_r;
std::wstring tex;
std::wstring t;
std::wstring tableline;
int rline=1,lline=1;
std::list<Diff>::const_iterator it; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
it = diffs.begin(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Diff aDiff;
bool modify=false;
bool oneline=false;
nstart=0;
while (it != diffs.end()) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
{
aDiff=*it;
tex=aDiff.text;
nstart=0;
while (nstart<tex.length()) {
pos=tex.find('\n',nstart);
if (pos==-1) {t.assign(tex,nstart,tex.length());nstart=tex.length();} else {t.assign(tex,nstart,pos-nstart);nstart=pos;}
if (t.length()>0) {
// <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (aDiff.operation==Operation::INSERT) cur_r+=L"<span class=\"differencei\">"+t+L"</span>";
if (aDiff.operation==Operation::DELETE) cur_l+=L"<span class=\"differenced\">"+t+L"</span>";
if (aDiff.operation==Operation::EQUAL) {
cur_r+=t;
cur_l+=t;
} else modify=true;
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
oneline=true;
} else
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \n
nstart=pos+1;
ncur_l=std::to_wstring(lline);
ncur_l=L""; ncur_r=L"";
// if (p_ncur_r==ncur_r) { ncur_r=L""; modify=true;}
// if (p_ncur_l==ncur_l) { ncur_l=L""; modify=true;}
std::wstring t_cur_l=cur_l;
std::wstring t_cur_r=cur_r;
if (aDiff.operation==Operation::DELETE) {
t_cur_r=L"";
ncur_l=std::to_wstring(lline);
modify=true;
lline++;
} else if (aDiff.operation==Operation::INSERT) {
t_cur_l=L"";
ncur_r=std::to_wstring(rline);
modify=true;
rline++;
} else if (aDiff.operation==Operation::EQUAL) {
ncur_r=std::to_wstring(rline);
ncur_l=std::to_wstring(lline);
rline++; lline++;
}
if (modify) countdiffline++;
// if (( (ncur_r.empty()&&(!ncur_l.empty()))
// ||(ncur_l.empty()&&(!ncur_r.empty()))
// )&&(!modify)) modify=true;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//left
tableline+=L"<tr><td class=\"diff_next\" onclick=\"c(this)\"></td>";
tableline+= modify ? L"<td class=\"has_difference\" onclick=\"d(this)\">"+ncur_l+"</td>" : L"<td class=\"diff_header\" onclick=\"d(this)\">"+ncur_l+"</td>";
tableline+=L"<td class=\"lineContent\"><pre>"+t_cur_l+"</pre></td>";
// right
tableline+=L"<td class=\"diff_next\" onclick=\"c(this)\"></td>";
tableline+= modify ? L"<td class=\"has_difference\" onclick=\"d(this)\">"+ncur_r+"</td>" : L"<td class=\"diff_header\" onclick=\"d(this)\">"+ncur_r+"</td>";
tableline+=L"<td class=\"lineContent\"><pre>"+t_cur_r+"</pre></td>";
tableline+=L"</tr>";
if (ncur_r.length()>0) p_ncur_r=ncur_r;
if (ncur_l.length()>0) p_ncur_l=ncur_l;
if (aDiff.operation==Operation::DELETE) {
cur_l=L"";
} else if (aDiff.operation==Operation::INSERT) {
cur_r=L"";
} else if (aDiff.operation==Operation::EQUAL) {
cur_r=L"";cur_l=L"";
}
//
modify=false;
oneline=false;
}
} // <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Diff
++it;
}
#ifdef _DEBUG
wxFileName fn("cmp_debug.txt");
fn.MakeAbsolute();
wxFile file(fn.GetFullPath(), wxFile::write);
if (!file.IsOpened())
{
wxLogError(_("Failed to open file %s."), fn.GetFullPath().c_str());
}
wxString report;
report.Append(wxString::Format(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n%s\n",tableline));
file.Write(report, wxConvUTF8);
file.Close();
#endif
return tableline;
}
wxString reportCompareFactory::printlvl(int element,int lvl,ArraySQL &list, wxHashTable &htab)
{
wxString l(list_head);
wxString r=wxEmptyString;
wxArrayInt* child;
wxString key,name;
int e=element;
int nstart;
SQL& sq=list.Item(e);
if ((nstart=sq.pathtree.rfind('/'))!=wxNOT_FOUND ) {
name=sq.pathtree.AfterLast('/');
key=sq.pathtree.Mid(startpathpos);
}
wxString tid=wxString::Format("id%d",e);
wxString rlist=HtmlEntities(name);
wxString cdiff=wxEmptyString;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
countdiffline=0;
if (sq.sql.length()+sq.sql2.length()>0) {
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::wstring t1=sq.sql.wc_str();
std::wstring t2(sq.sql2.wc_str());
t1.erase(std::remove(t1.begin(), t1.end(), '\r'), t1.end());
t2.erase(std::remove(t2.begin(), t2.end(), '\r'), t2.end());
std::wstring rez=printdiff(t1,t2);
if (rez.length()>0) {
//L"</tbody></table>"
//tableshtml
wxString tmp(tableheader);
tmp.Replace("@idtablecmp@",tid);
tmp.Replace("$rowlist$",rlist);
tableshtml+=tmp+"\n";
tmp=tableheader2;
tmp.Replace("@idtablecmp@",tid);
tmp.Replace("$rowlist$",rlist);
tableshtml+=tmp;
tableshtml+=rez;
tableshtml+="</tbody></table>\n";
cdiff=wxString::Format(" ( %d )",countdiffline);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
child=(wxArrayInt *)htab.Get(key);
r=rowlist;
r.Replace("$rowlist$",rlist+cdiff);
if (sq.mode==__Insert) r.Replace("@color@","insert");
else if (sq.mode==__Remove) r.Replace("@color@","remove");
else if (countdiffline>0) r.Replace("@color@","ne"); else {
if (child!=NULL) r.Replace("@color@","eq"); else r.Replace("@color@","eqhidden");
}
r.Replace("@idtablecmp@",tid);
l+=r;
if (child!=NULL) {
for (int j=0;j<child->GetCount();j++) {
l+=printlvl(child->Item(j),lvl+1,list,htab);
}
}
l+=list_end;
return l;
}
///////////////////////////////////////////////////////
// Report base
///////////////////////////////////////////////////////
wxWindow *reportBaseFactory::StartDialog(frmMain *form, pgObject *obj)
{
parent = form;
wxBeginBusyCursor();
frmReport *report = new frmReport(GetFrmMain());
// Generate the report header
wxDateTime now = wxDateTime::Now();
report->XmlAddHeaderValue(wxT("generated"), now.Format(wxT("%c")));
if (obj->GetServer())
report->XmlAddHeaderValue(wxT("server"), obj->GetServer()->GetFullIdentifier());
if (obj->GetDatabase())
report->XmlAddHeaderValue(wxT("database"), obj->GetDatabase()->GetName());
if (obj->GetSchema())
{
if (obj->GetSchema()->GetMetaType() == PGM_CATALOG)
report->XmlAddHeaderValue(wxT("catalog"), obj->GetSchema()->GetDisplayName());
else
report->XmlAddHeaderValue(wxT("schema"), obj->GetSchema()->GetName());
}
if (obj->GetJob())
report->XmlAddHeaderValue(wxT("job"), obj->GetJob()->GetName());
if (obj->GetTable())
report->XmlAddHeaderValue(wxT("table"), obj->GetTable()->GetName());
GenerateReport(report, obj);
wxEndBusyCursor();
report->ShowModal();
return 0;
}
///////////////////////////////////////////////////////
// Properties report
///////////////////////////////////////////////////////
reportObjectPropertiesFactory::reportObjectPropertiesFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&Properties Report"), _("Generate a Properties report for this object."));
}
bool reportObjectPropertiesFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (obj->IsCollection())
return false;
else
return true;
}
return false;
}
void reportObjectPropertiesFactory::GenerateReport(frmReport *report, pgObject *object)
{
report->SetReportTitle(object->GetTranslatedMessage(PROPERTIESREPORT));
int section = report->XmlCreateSection(object->GetTranslatedMessage(PROPERTIES));
ctlListView *list = GetFrmMain()->GetProperties();
object->ShowProperties();
report->XmlAddSectionTableFromListView(section, list);
report->XmlSetSectionSql(section, object->GetSql(NULL));
}
///////////////////////////////////////////////////////
// DDL report
///////////////////////////////////////////////////////
reportObjectDdlFactory::reportObjectDdlFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&DDL Report"), _("Generate a DDL report for this object."));
}
bool reportObjectDdlFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (obj->GetMetaType() == PGM_SERVER || obj->GetMetaType() == PGM_CATALOGOBJECT || obj->IsCollection())
return false;
else
return true;
}
return false;
}
void reportObjectDdlFactory::GenerateReport(frmReport *report, pgObject *object)
{
report->SetReportTitle(object->GetTranslatedMessage(DDLREPORT));
int section = report->XmlCreateSection(object->GetTranslatedMessage(DDL));
report->XmlSetSectionSql(section, object->GetSql(NULL));
}
///////////////////////////////////////////////////////
// Data dictionary report
///////////////////////////////////////////////////////
reportObjectDataDictionaryFactory::reportObjectDataDictionaryFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&Data Dictionary Report"), _("Generate a Data Dictionary report for this object."));
}
bool reportObjectDataDictionaryFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if ((obj->GetMetaType() == PGM_TABLE || obj->GetMetaType() == GP_PARTITION) && !obj->IsCollection())
return true;
else
return false;
}
return false;
}
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++;
}
}
///////////////////////////////////////////////////////
// Statistics report
///////////////////////////////////////////////////////
reportObjectStatisticsFactory::reportObjectStatisticsFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&Statistics Report"), _("Generate a Statistics report for this object."));
}
bool reportObjectStatisticsFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (!obj->HasStats())
{
if (obj->IsCollection())
{
pgaFactory *f = obj->GetFactory();
if (f)
{
if (f->GetMetaType() == PGM_TABLE ||
f->GetMetaType() == GP_PARTITION ||
f->GetMetaType() == PGM_TABLESPACE ||
f->GetMetaType() == PGM_DATABASE)
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return true;
}
}
return false;
}
void reportObjectStatisticsFactory::GenerateReport(frmReport *report, pgObject *object)
{
report->SetReportTitle(object->GetTranslatedMessage(STATISTICSREPORT));
int section = report->XmlCreateSection(object->GetTranslatedMessage(OBJSTATISTICS));
ctlListView *list = GetFrmMain()->GetStatistics();
object->ShowStatistics(GetFrmMain(), list);
report->XmlAddSectionTableFromListView(section, list);
}
///////////////////////////////////////////////////////
// Dependencies report
///////////////////////////////////////////////////////
reportObjectDependenciesFactory::reportObjectDependenciesFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&Dependencies Report"), _("Generate a Dependencies report for this object."));
}
bool reportObjectDependenciesFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (!obj->HasDepends())
return false;
else
return true;
}
return false;
}
void reportObjectDependenciesFactory::GenerateReport(frmReport *report, pgObject *object)
{
report->SetReportTitle(object->GetTranslatedMessage(DEPENDENCIESREPORT));
int section = report->XmlCreateSection(object->GetTranslatedMessage(DEPENDENCIES));
ctlListView *list = GetFrmMain()->GetDependencies();
object->ShowDependencies(parent, list);
report->XmlAddSectionTableFromListView(section, list);
}
///////////////////////////////////////////////////////
// Dependents report
///////////////////////////////////////////////////////
reportObjectDependentsFactory::reportObjectDependentsFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&Dependents Report"), _("Generate a Dependents report for this object."));
}
bool reportObjectDependentsFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (!obj->HasReferences())
return false;
else
return true;
}
return false;
}
void reportObjectDependentsFactory::GenerateReport(frmReport *report, pgObject *object)
{
report->SetReportTitle(object->GetTranslatedMessage(DEPENDENTSREPORT));
int section = report->XmlCreateSection(object->GetTranslatedMessage(DEPENDENTS));
ctlListView *list = GetFrmMain()->GetReferencedBy();
object->ShowDependents(parent, list);
report->XmlAddSectionTableFromListView(section, list);
}
///////////////////////////////////////////////////////
// Object list report
///////////////////////////////////////////////////////
reportObjectListFactory::reportObjectListFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar)
: reportBaseFactory(list)
{
mnu->Append(id, _("&Object List Report"), _("Generate an Object List report for this collection."));
}
bool reportObjectListFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (!obj->IsCollection())
{
return false;
}
else
{
pgaFactory *f = obj->GetFactory();
if (obj)
{
if (f->GetMetaType() == PGM_SERVER)
return false;
}
else
return false;
return true;
}
}
return false;
}
void reportObjectListFactory::GenerateReport(frmReport *report, pgObject *object)
{
report->SetReportTitle(object->GetTranslatedMessage(OBJECTSLISTREPORT));
int section = report->XmlCreateSection(object->GetFullIdentifier());
ctlListView *list = GetFrmMain()->GetProperties();
object->ShowProperties();
report->XmlAddSectionTableFromListView(section, list);
}