/***** * * TOra - An Oracle Toolkit for DBA's and developers * Copyright (C) 2003-2005 Quest Software, Inc * Portions Copyright (C) 2005 Other Contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; only version 2 of * the License is valid for this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, you have permission to link this program * with the Oracle Client libraries and distribute executables, as long * as you follow the requirements of the GNU GPL in regard to all of the * software in the executable aside from Oracle client libraries. * * Specifically you are not permitted to link this program with the * Qt/UNIX, Qt/Windows or Qt Non Commercial products of TrollTech. * And you are not permitted to distribute binaries compiled against * these libraries without written consent from Quest Software, Inc. * Observe that this does not disallow linking to the Qt Free Edition. * * You may link this product with any GPL'd Qt library such as Qt/Free * * All trademarks belong to their respective owners. * *****/ #include "utils.h" #include "toconf.h" #include "toconnection.h" #include "tohtml.h" #include "toextract.h" #include "toreport.h" #ifndef WIN32 #include #else #include #endif #include #include static bool SameContext(const QString &str, const QString &str2) { if (str.startsWith(str2)) { if (str.length() == str2.length()) return true; if (str.length() > str2.length() && str.at(str2.length()) == QChar('\001')) return true; } return false; } static bool HasChildren(std::list &desc, std::list::iterator i, const QString &context) { if ((*i).length() > context.length()) return true; i++; if (i == desc.end()) return false; return SameContext(*i, context); } static std::list::iterator FindItem(std::list &desc, std::list::iterator i, int level, const QString &context, const QString &search) { while (i != desc.end()) { if (!SameContext(*i, context) && !context.isEmpty()) return desc.end(); if (toExtract::partDescribe(*i, level) == search) return i; i++; } return desc.end(); } static QString GenerateConstraint(const QString &name, const QString &def, const QString &status) { return QString::fromLatin1("%1%2%3\n"). arg(toHtml::escape(name)). arg(toHtml::escape(def)). arg(toHtml::escape(status)); } static QString DescribeConstraints(std::list &desc, std::list::iterator i, int level, const QString &context) { QString ret = QString::fromLatin1("

CONSTRAINTS

\n" "" "\n"); QString lastName; QString status; QString definition; do { if (!SameContext(*i, context)) break; QString name = toExtract::partDescribe(*i, level); QString extra = toExtract::partDescribe(*i, level + 1); if (lastName != name) { if (!lastName.isNull()) ret += GenerateConstraint(lastName, definition, status); definition = QString::null; status = QString::null; lastName = name; } if (extra == QString::fromLatin1("DEFINITION")) definition += toExtract::partDescribe(*i, level + 2) + " "; else if (extra == QString::fromLatin1("STATUS")) { QString t = toExtract::partDescribe(*i, level + 2); if (t.startsWith(QString::fromLatin1("ENABLE")) || t.startsWith(QString::fromLatin1("DISABLE"))) status += t + QString::fromLatin1(" "); } i++; } while (i != desc.end()); ret += GenerateConstraint(lastName, definition, status); ret += QString::fromLatin1("
NameConstraintStatus
\n"); return ret; } struct toReportColumn { QString Order; QString Datatype; QString Comment; }; static QString DescribeColumns(std::list &desc, std::list::iterator i, int level, const QString &context) { bool hasComments = false; bool hasDatatype = false; int maxCol = 1; std::map cols; do { if (!SameContext(*i, context)) break; QString col = toExtract::partDescribe(*i, level + 0); QString extra = toExtract::partDescribe(*i, level + 1); if (extra == QString::fromLatin1("ORDER")) { cols[col].Order = toExtract::partDescribe(*i, level + 2); maxCol = std::max(maxCol, cols[col].Order.toInt()); } else if (extra == QString::fromLatin1("COMMENT")) { cols[col].Comment = toExtract::partDescribe(*i, level + 2); hasComments = true; } else if (!extra.isEmpty()) { cols[col].Datatype += extra + QString::fromLatin1(" "); hasDatatype = true; } i++; } while (i != desc.end()); QString ret = qApp->translate("toReport", "

COLUMNS

\n" ""); if (hasDatatype) ret += qApp->translate("toReport", ""); if (hasComments) ret += qApp->translate("toReport", ""); ret += QString::fromLatin1("\n"); for (int j = 1;j <= maxCol;j++) { for (std::map::iterator k = cols.begin();k != cols.end();k++) { if ((*k).second.Order.toInt() == j) { ret += QString::fromLatin1(""); if (hasDatatype) { ret += QString::fromLatin1(""); } if (hasComments) { ret += QString::fromLatin1(""); } ret += QString::fromLatin1("\n"); break; } } } ret += QString::fromLatin1("
NameDefinitionDescription
"); ret += toHtml::escape((*k).first); ret += QString::fromLatin1(""); if (!(*k).second.Datatype.isEmpty()) ret += toHtml::escape((*k).second.Datatype); else ret += QString::fromLatin1("
"); ret += QString::fromLatin1("
"); if (!(*k).second.Comment.isEmpty()) ret += toHtml::escape((*k).second.Comment); else ret += QString::fromLatin1(" "); ret += QString::fromLatin1("
\n"); return ret; } static QString ValidPart(std::list &desc, std::list::iterator &i, int level) { QString part = toExtract::partDescribe(*i, level); while (part.isNull() && i != desc.end()) { i++; part = toExtract::partDescribe(*i, level); } return part; } static QString DescribePart(std::list &desc, std::list::iterator &i, int level, const QString &parentContext) { QString ret; QString text; QString lastPart; std::list::iterator start = i; do { if (!SameContext(*i, parentContext)) break; QString part = ValidPart(desc, i, level); do { QString part = toExtract::partDescribe(*i, level); } while (part.isNull()); if (lastPart != part) { if (lastPart.isNull()) { i = FindItem(desc, start, level, parentContext, QString::fromLatin1("TABLE")); if (i == desc.end()) { i = start; part = ValidPart(desc, i, level); } else part = toExtract::partDescribe(*i, level); } else { while (part == QString::fromLatin1("TABLE")) { i++; if (i == desc.end()) return ret; part = toExtract::partDescribe(*i, level); } } if (lastPart == QString::fromLatin1("TABLE")) { i = start; part = ValidPart(desc, i, level); } lastPart = part; } QString child = parentContext + QString::fromLatin1("\001") + part; if (part == QString::fromLatin1("COLUMN") || part == QString::fromLatin1("COMMENT") || part == QString::fromLatin1("CONSTRAINT")) { i++; } else if (HasChildren(desc, i, child)) { ret += QString::fromLatin1("

%2

\n"). arg(level + 1). arg(toHtml::escape(part)). arg(level + 1); std::list::iterator com = FindItem(desc, i, level + 1, child, QString::fromLatin1("COMMENT")); if (com != desc.end()) ret += "

" + toHtml::escape(toExtract::partDescribe(*com, level + 2)) + "

"; std::list::iterator col = FindItem(desc, i, level + 1, child, QString::fromLatin1("COLUMN")); if (col != desc.end()) ret += DescribeColumns(desc, col, level + 2, child + QString::fromLatin1("\001COLUMN")); std::list::iterator con = FindItem(desc, i, level + 1, child, QString::fromLatin1("CONSTRAINT")); if (con != desc.end()) ret += DescribeConstraints(desc, con, level + 2, child + QString::fromLatin1("\001CONSTRAINT")); ret += DescribePart(desc, i, level + 1, child); } else { if (!part.isEmpty()) text += QString::fromLatin1("

") + toHtml::escape(part) + QString::fromLatin1("

\n"); i++; } } while (i != desc.end()); return text + ret; } QString toGenerateReport(toConnection &conn, std::list &desc) { char host[1024]; gethostname(host, 1024); QString db = conn.host(); if (db.length() && db != QString::fromLatin1("*")) db += QString::fromLatin1(":"); else db = QString::null; db += conn.database(); QString ret = qApp->translate("toReport", "Report on database %7\n" "

Report on database %8

\n" "\n" "\n" "\n" "\n" "\n" "
Generated by:TOra, Version %1
At:%2
From:%3, an %4 %5 database
On:%6
\n"). arg(QString::fromLatin1(TOVERSION)). arg(QString::fromLatin1(host)). arg(db). arg(conn.provider()). arg(conn.version()). arg(QDateTime::currentDateTime().toString()). arg(db). arg(db); std::list::iterator i; i = FindItem(desc, desc.begin(), 0, QString::null, QString::fromLatin1("NONE")); if (i != desc.end()) { ret += qApp->translate("toReport", "

Global Objects

\n"); ret += DescribePart(desc, i, 1, QString::fromLatin1("NONE")); } i = desc.begin(); QString lastContext; while (i != desc.end()) { QString context = toExtract::partDescribe(*i, 0); if (context != QString::fromLatin1("NONE")) { if (context != lastContext) { if (context == QString::fromLatin1("public")) ret += qApp->translate("toReport", "

Public

"); else ret += qApp->translate("toReport", "

Schema %1

\n").arg(toHtml::escape(context)); } ret += DescribePart(desc, i, 1, context); lastContext = context; } else i++; } ret += QString::fromLatin1("\n"); return ret; }