diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..dda65ac7f9 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +--- +custom: ["https://pgmodeler.io/#donationForm"] diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 0000000000..4d054a0f2e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,38 @@ +--- +name: Report a bug +about: Instructions on how to report pgModeler bugs. Before report any bug please + check if someone already has submited issues similiar to yours. Duplicated issues + will be ignored. + +--- + +**Bug description** +_A clear and concise description of what the bug is._ + +**How to reproduce** +_Please, if the bug can be reproduceable describe the steps in full details. If possible provide a sample model and/or a SQL dump for test purposes._ + +**Expected behavior** +_A clear and concise description of what you expected to happen._ + +**Screenshots** +_If applicable, add screenshots to help explain your problem._ + +**Info about your desktop** + - OS: + - Version: + - Window manager: + - pgModeler version: + - Qt version: + +**Stacktrace / Debug info** +_If pgModeler crashed after the bug raised attach the stacktrace below_ + +``` + + Put the stacktrace here! + +``` + +**Additional info** +_Add any other information that you may find useful to help in the problem solving._ diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md new file mode 100644 index 0000000000..219c04f5c1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -0,0 +1,8 @@ +--- +name: General discussion +about: For any discussion not related to bugs or feature requests please use this + one. + +--- + + diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 0000000000..f3ad5eb15b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature request / improvement +about: Give your suggestions for improvements to this project. + +--- + +**Feature description** +_A clear and concise description of what the problem is._ + +**Sample image** +_If the feature requested is a visual improvement, please, attach some images to make it clear._ + +**Additional info** +_Add any other context or screenshots about the feature request here._ diff --git a/.github/workflows/linuxbuild.yml b/.github/workflows/linuxbuild.yml new file mode 100644 index 0000000000..1df7ad4332 --- /dev/null +++ b/.github/workflows/linuxbuild.yml @@ -0,0 +1,34 @@ +name: Linux build + +on: + push: + branches: [ master, develop, 0.9.*, '*fix*', '*change*', '*support*' ] + tags: 0.9.* + + pull_request: + branches: [ master, develop, 0.9.* ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + qt: ['5.15.0', '5.14.2', '5.13.2', '5.12.9', '5.11.3', '5.10.1', '5.9.9'] + + steps: + - uses: actions/checkout@v2 + + - name: Installing Qt framework + uses: jurplel/install-qt-action@v2 + with: + version: ${{ matrix.qt }} + + - name: Running qmake + run: cd $GITHUB_WORKSPACE; qmake pgmodeler.pro -r PREFIX=$GITHUB_WORKSPACE/build CONFIG+=debug + + - name: Building pgModeler + run: make -j6 + + - name: Deploying pgModeler + run: make install diff --git a/.github/workflows/macosbuild.yml b/.github/workflows/macosbuild.yml new file mode 100644 index 0000000000..48717cc688 --- /dev/null +++ b/.github/workflows/macosbuild.yml @@ -0,0 +1,34 @@ +name: macOs build + +on: + push: + branches: [ master, develop, 0.9.*, '*fix*', '*change*', '*support*' ] + tags: 0.9.* + + pull_request: + branches: [ master, develop, 0.9.* ] + +jobs: + build: + runs-on: macos-latest + + strategy: + matrix: + qt: ['5.15.0', '5.14.2', '5.13.2', '5.12.9', '5.11.3', '5.10.1', '5.9.9'] + + steps: + - uses: actions/checkout@v2 + + - name: Installing Qt framework + uses: jurplel/install-qt-action@v2 + with: + version: ${{ matrix.qt }} + + - name: Running qmake + run: cd $GITHUB_WORKSPACE; qmake pgmodeler.pro -r PREFIX=/Applications/pgModeler.app/Contents PGSQL_INC=`pg_config --includedir` PGSQL_LIB=`pg_config --libdir`/libpq.dylib CONFIG+=debug + + - name: Building pgModeler + run: make -j6 + + - name: Deploying pgModeler + run: make install diff --git a/.github/workflows/windowsbuild.yml b/.github/workflows/windowsbuild.yml new file mode 100644 index 0000000000..c88a868f00 --- /dev/null +++ b/.github/workflows/windowsbuild.yml @@ -0,0 +1,48 @@ +name: Windows build + +on: + push: + branches: [ master, develop, 0.9.*, '*fix*', '*change*', '*support*' ] + tags: 0.9.* + + pull_request: + branches: [ master, develop, 0.9.* ] + +jobs: + build: + runs-on: windows-latest + + strategy: + matrix: + qt: ['5.15.0'] + + defaults: + run: + shell: msys2 {0} + + steps: + - uses: actions/checkout@v2 + + - uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: base-devel mingw-w64-x86_64-make mingw-w64-x86_64-gcc mingw-w64-x86_64-postgresql mingw-w64-x86_64-qt5 + + # Workaround: Instead of using $GITHUB_WORKSPACE in PREFIX we actually use the path converted to unix-like + # since we're running the building inside msys2 + - name: Running qmake + run: | + cd $GITHUB_WORKSPACE; + qmake pgmodeler.pro -r PREFIX=D:/a/pgmodeler/pgmodeler/build \ + XML_INC=$(cygpath -m /mingw64/include/libxml2) \ + XML_LIB=$(cygpath -m /mingw64/bin/libxml2-2.dll) \ + PGSQL_INC=$(cygpath -m /mingw64/include) \ + PGSQL_LIB=$(cygpath -m /mingw64/bin/libpq.dll) \ + CONFIG+=debug + + - name: Building pgModeler + run: mingw32-make -j6 + + - name: Deploying pgModeler + run: mingw32-make install diff --git a/.gitignore b/.gitignore index ca413d0a72..32bd6c8000 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,35 @@ +.qmake.stash + *.[oa] +*.dll +*.exe *.so.* *.so -ui_*.h -moc_*.cpp -obj/* -moc/* -Makefile -build/* *.pro.user *.directory *.run +*.Debug +*.Release +*.old + +moc_*.cpp +moc_*.h +qrc_resources.cpp +ui_*.h +windeploy.log +Makefile + +build/* +dist/* +installer/template/packages/io.pgmodeler/data +installer/template/packages/io.pgmodeler/meta/package.xml +installer/template/config/config.xml +moc/* +obj/* +plugins +plugins/* +release/* +apps/pgmodeler/build/* +apps/pgmodeler-cli/build/* +apps/pgmodeler-ch/build/* +apps/pgmodeler-sce/build/* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ac057b6c7..00a820ec2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,974 @@ -Change Log +Changelog --------- +v0.9.4 +------ +Release date: December 17, 2021
+ +* [New] Added a fix step in CLI to reconstruct enum types XML code in new format. +* [Change] Changed the way XML code for enum types is generated and loaded. +* [Change] Minor improvement in reverse engineering to import enum types in the new format. +* [Change] Minor adjust in the demo version warning message. +* [Change] Minor adjustment in permission id generation. Now the object's signature is used instead of name. +* [Change] Minor refactor in the reconstruction of XML related to enum types in CLI. +* [Fix] Minor fix in deployment script to support new libicui versions. +* [Fix] Minor fix in order to set read/write permissions when copying configuration files with read-only permissions. +* [Fix] Minor fix in CLI to avoid the usage of '-platform offscreen' when calling the application. +* [Fix] Fixed a bug in file selectors on ModelExportForm that was not allowing to select output folders on Windows and macOs. + +v0.9.4-beta1 +------ +Release date: November 08, 2021
+ +* [New] Added extra PostGiS data types to PgSQLType. +* [New] Created the method PgSqlType::isPostGiSType() which returns true if the current type is a PostGiS one. +* [New] Created the method PgSqlType::reset() that clears some attributes of the type. +* [New] Added the built-in type pg_lsn in order to make databases using timescaledb extension to be imported correctly. +* [Change] Minor adjustment in windowsdeploy.sh to create zip packages. +* [Change] Minor adjustment in demo version warning messages. +* [Change] Adjusted the catalog query filters in ModelDatabaseDiffForm to retrieve system and extension objects according to the checkboxes "Import system objects" and "Import extension objects". +* [Change] Adjusted the reverse engineering in such a way that the table children will follow the SQL disabled state of their parent tables. +* [Change] Allowing importing pg_lsn attributes in usertype.sch. +* [Change] Allowing the use of commas in enum type labels. +* [Change] Improved the output of model fix operation in CLI. +* [Change] The constants DataSeparator, UnescValueStart, UnescValueEnd, WildcardChar, FilterSeparator, FilterWildcard, FilterRegExp were moved from CoreUtilsNs to UtilsNs in order to be used in the parsers module. +* [Change] In SchemaParser the meta char $ds (dollar sign) was renamed to $ms (money sign). Also, a new meta char $ds (data separator) was added and translates to the special data separator character UtilsNs::DataSeparator. +* [Change] Minor adjustments in table.sch and foreigntable.sch schema files. +* [Change] Improved DatabaseModel::getUserDefTypesReferences in order to get all references to postgis data types. +* [Change] Improved ModelValidationHelper in order to set postgis extension a default comment when automatically creating it. +* [Change] PgSQLTypeWidget now can be configured in such a way to disallow the configuration of type qualifiers like length, precision, interval, and some other. This is useful when configuring data types for objects that don't require such attributes in the data type like parameter, aggregates, transforms, casts, operators. +* [Change] Changed the behavior of Parameter::getCodeDefinition when generating SQL code. Now, any type qualifier (except dimension descriptor []) will be discarded. +* [Fix] Fixed the catalog query that lists policies. +* [Fix] Added a minor workaround in DatabaseImportHelper::getType in order to treat the "any" pseudo-type correctly. +* [Fix] Minor fix in DatabaseImportForm in order to disable option buttons when no connection is selected. +* [Fix] Fixed a segfault when importing domains with long expressions. +* [Fix] Fixed the broken SQL generation for tables with columns/constraints disabled. +* [Fix] Fix the name of the checkbox related to updates checking to avoid breaking the building when enabling NO_UPDATE_CHECK via qmake. +* [Fix] Fixed the shortcuts of Copy/Paste actions in DataManipulationForm. + +v0.9.4-beta +------ +Release date: September 20, 2021
+ +* [New] Added the shortcut Alt+C to trigger the cancel action in DatabaseImportForm ModelDatabaseDiffForm and ModelExportForm. +* [New] Added support for the generation of GRANT/REVOKE commands to control roles memberships via the diff process. +* [New] Added a fix step to reconfigure roles membership considering the deprecation of Role:RefRole attribute. +* [New] Added support for included columns on indexes. +* [New] Added the ability to reference view columns on indexes. +* [New] Added support to use view's SimpleColumn in ColumnPickerWidget as well as Index. +* [New] Added .dtd extension to SchemaEditorForm::showFileDialog. +* [New] Created the widget ColumnPickerWidget by isolating the code that handles constraint columns in ConstraintWidget for reusing in other portions of the tool. +* [New] Added the method Constraint::addColumns(). +* [New] Two buttons were added aside the date input fields in partial diff tab (ModelDatabaseDiffForm) in order to allow the quick assignment of the first and last modification dates. +* [New] Added support for toggling update notifications for alpha/beta versions. +* [New] Added support for save and restore the tree state in DatabaseExplorerWidget. +* [Change] Minor improvement in ModelsExportHelper by adding more breaking points related to export canceled. +* [Change] Minor improvement in ObjectRenameWidget in such a way to fill the new name field with the object's name in the first show when a single object is selected for renaming. +* [Change] Dropped the support for MemberOf (Role::RefRoles) in order to make the diff between two roles more precise. +* [Change] In RoleWidget the tab "Member Of" now works only as a convenience feature that adds the role being edited to the ones listed in that tab. +* [Change] Restored the file pgmodeler.appdata.xml. +* [Change] Refactored BaseObject::isCodeDiffersFrom (and its variants in children classes) to use QStringList instead of vector as parameters. +* [Change] Allowing swap cluster level object ids in SwapObjectsIdsWidget when the objects are of the same kind. +* [Change] Minor refactoring in RoleWidget, Role and DatabaseModel to use Role::RefRole, Role::MemberRole and Rele::AdminRole constants as loop indexes. +* [Change] Minor adjustment in demo features. +* [Change] Minor refactoring in Role::setRoleAttribute. +* [Change] Minor improvement in ModelExportHelper::exportToDbms to send the SQL command via a signal when creating roles and the database. +* [Change] Improvements in pgmodeler-se in such a way to control syntax highlighting settings per open editor. +* [Change] Avoided the use of a working dir in .desktop file when installing mime types system-wide. +* [Change] Improved the way layers rectangles are updated after undoing/redoing operations in OperationListWidget. +* [Change] Isolated SimpleColumn struct on its own file for reusing in other modules. +* [Change] Moved the constants ProtRowBgColor, ProtRowFgColor, RelAddedRowBgColor, RelAddedRowFgColor from BaseObjectWidget to GuiUtilsNs. +* [Change] Changed the default match type in foreign key constraint to MATCH SIMPLE. +* [Change] Minor adjustment in the ModelWidget::updateSceneLayers to force the update of all schemas. +* [Change] Avoided a lambda function call when checking updates to prevent segfaults. +* [Change] Exceptions raised in BugReportForm when the "lastmodel" file isn't found are now ignored. +* [Change] Minor change in ModelValidationHelper to use table's signature instead of name during the name validation process. +* [Change] Avoided calling the functions xmlInitParser() and xmlCleanupParser() more than once per app execution in XmlParser class to avoid unexpected behavior. +* [Change] Minor adjustment in viewport drawing mode in order to redraw objects by bounding rect changes. +* [Change] Minor improvements in the changelog widget in order to display the first modification date. +* [Change] Refactored Connection::requestCancel in order to avoid using PQrequestCancel which is deprecated. +* [Fix] Fixed a glitch when drawing StyledTextboxView instaces. +* [Fix] Fix the diff between columns using PostGiS datatypes. +* [Fix] The attributes Qt::AA_UseHighDpiPixmaps and Qt::AA_EnableHighDpiScaling are now correctly set before the instantiation of Application based classes. +* [Fix] Fixed a crash in diff process caused by the ModelExportHelper instance when canceling the export to DBMS when an exception was raised. +* [Fix] Fixed a crash in SwapObjectsIdsWidget when the user tried to swap objects using arrow keys. +* [Fix] Fixed the tab names in RoleWidget. +* [Fix] Minor fix in DatabaseExplorerWidget to display view's children source code. +* [Fix] Fixed the building of IndexWidget on Qt 5.14 and below. +* [Fix] Fixed the problem on ModelDatabaseDiffForm that was not accepting pressing Return/Esc to respectively run the diff and close the dialog due to a conflict with the event loop instance in ModelDatabaseDiffForm::exec(). +* [Fix] Minor fix in the configuration of ObjectGroupId element in DatabaseImportForm::updateObjectsTree in order to avoid crashes when no root element is specified. +* [Fix] Fixed the generation of aggregate functions when they use functions that contain parameters in which data type have spaces (double precision, character varying). +* [Fix] Fixed a segfault that can happen when changing the number of parameters of a function already associated with an aggregate. +* [Fix] Additional fix for layers not being correctly loaded from dbm file. + +v0.9.4-alpha1 +------ +Release date: July 19, 2021
+ +* [New] The bulk editing form now can be confirmed by the Ctrl+Return shortcut. +* [New] The CLI now is capable of fixing models created before 0.9.4-alpha1 that have columns, functions, and other objects that reference extension types with simple names instead of schema-qualified names. +* [New] Added an option to GeneralConfigWidget to toggle the displaying of schema names of columns data types on design view. This option affects only the rendering of objects, the code generation will keep displaying user-defined type names in a schema-qualified way. +* [New] Created the DeletableItemDelegate which draws a delete button aside combobox items. +* [New] Added the ability to drop databases from the database listing in SQLToolWidget. +* [New] Added support to strikeout attribute in SyntaxHighlighter. +* [New] Created an auxiliary tool called pgModeler Schema Editor in order to help to edit *.sch files as well as validate their syntax. +* [New] GeneralConfigWidget now restores the sch-highlight.conf to default. +* [New] Added the environment variable name for schema editor app in GlobalAttributes. +* [New] Added a specific icon for CLI on Windows. +* [New] Added the methods SchemaParser::getCurrentColumn and SchemaParser::getCurrentLine. +* [New] Added signal s_hideRequested to FindReplaceWidget to notify connected slots that the close button on that widget was clicked. +* [New] Added an attribute capture-nearby to the word-separators tag that is read by SchemaParser to indicate if word separators must be capture altogether in the same word if they appear contiguously. +* [New] Added options to create only missing config files or recreate all config file in CLI. +* [New] Added support for saving SQL definition in split files. +* [New] Added support for split SQL generation in CLI. +* [New] Added the ability to cancel the SQL file export process in GUI. +* [New] Created the methods UtilsNs::saveFile and UtilsNs::loadFile in order to replace repetitive save/load code by them. +* [New] Created the function PgSqlVersions::parseString that checks the forced PostgreSQL version is valid, returning a fallback version when needed or raising an error if the version is malformed or is unsupported. +* [New] Added new metacharacter to SchemaParser: $hs for #, $ps for %, $at for @, $ds for $. +* [New] Added the option --force to the mime type handling operation on CLI. +* [Change] Changed the behavior of column click on DataManipulationForm. Now, the sorting is triggered by holding control and clicking the desired column. Clicking a column without holding control will select all the items in that column. +* [Change] Changed the behavior of extension types registration, now they will be forcibly registered with complete name (schema.name) in order to follow the same rule of user-defined data types so the reverse engineering can work properly for both types handled by extensions and those not. +* [Change] Improved the type searching on PgSqlTypeWidget in such a way to display a popup with the data types matching the text typed by the user. +* [Change] Improved TableObjectView to be rendered with/without schema names appended to user-defined data type names. +* [Change] Minor adjustment on icon size of QTreeWidget instances. +* [Change] Improved the NewObjectOverlayWidget in such a way to allow only one action to be executed at a time. +* [Change] Several clean-ups in the source code root. Removed unused files. +* [Change] The subproject libpgmodeler was renamed to libcore and now moved to libs/ +* [Change] The subproject libpgmodeler_ui was renamed to libgui and now moved to libs/ +* [Change] The subproject libobjrenderer was renamed to libcanvas and now moved to libs/ +* [Change] The main executable subproject was renamed to pgmodeler and now moved to apps/ +* [Change] The main-cli executable subproject was renamed to pgmodeler-cli and moved to apps/ +* [Change] The crashhandler subproject was renamed to pgmodeler-ch and moved to apps/ +* [Change] Created a subfolder called "assets" to store all deployed files that aren't libraries or executables: conf, lang, schemas, samples, etc. +* [Change] Refactored all .pro/.pri files in order to reference pgModeler libraries from variables $$LIB[LIBNAME] instead of relative paths. +* [Change] Renamed all icons that were in Portuguese to English. +* [Change] In SnippetsConfigWidget replaced the SQL highlight by Schema micro-language highlighting. +* [Change] Renamed BlockInfo class to TextBlockInfo and moved to a dedicated source file. +* [Change] Changed the workflows to build any *fix, *change, *support branches. +* [Change] Minor improvement on QMainWindow to resize general toolbar buttons. +* [Change] Widgets that were emitting the signal s_visibilityChanged(bool) only on hide event no emit s_hideRequested instead. The s_visibilityChanged(bool) is now reserved to widgets that need to notify visibility changes passing the current state to slots (hidden/displayed) in for of a bool parameter. +* [Change] Minor hint text typos fixes. +* [Change] Improved the syntax error messages in SchemaParser. +* [Change] Minor adjustment in the minimum width of the general toolbar when resizing the buttons. +* [Change] BaseForm::setMainWidget(QWidget *) version will use the same icon as the widget being inserted. +* [Change] Adjusting the general toolbar width according to the screen DPI. +* [Change] Renamed the namespace PgModelerUiNs to GuiUtilsNs. +* [Change] Renamed the namespace PgModelerNs to CoreUtilsNs +* [Change] Source files and ui files in libgui were reorganized by contexts (widgets, tools, settings, utils, dbobjects) +* [Change] Applied an automatic indentation to all schema files. +* [Change] pgModeler will now create missing config files in the startup. +* [Change] Replaced duplicated code that saves files and raises exception by UtilsNs::saveFile +* [Change] The class Schema now has its own id interval (4000 - 4999) in order to make the split code generation be done properly. +* [Change] Minor adjustment in AppearanceConfigWidget to enable scrollbars in the viewport so users on small screens can see the entire model. +* [Fix] Fixed the crash handler and bug report form in such a way to load the last modified model opened before their execution. +* [Fix] Fixed the column positions in ObjectDepsRefsWidget. +* [Fix] Fixed a crash when the database import process fails to create an inheritance relationship somehow. +* [Fix] Fixed a bug in the database import process that not correctly setting up the data type name of columns when the types were handled by extensions. Types handled by extension don't need to have the schema name prepended. +* [Fix] Minor fix in database import process in such a way to properly update the table rendering to hide schema names from title box. +* [Fix] Fixed a malformed SQL code when configuring timestamptz in PgSqlType. +* [Fix] Fixed the reference to libutils in deploy scripts. +* [Fix] Fixed doxygen references for libraries and executables. +* [Fix] Fixed the path to globalattributes.cpp in deploy scripts. +* [Fix] Added missing file windows_ico.qrc. +* [Fix] Fixed a bug in SyntaxHighlighter that was wrongly highlighting the entire document when a multiline group had a line break as the final expression. +* [Fix] Fixed the syntax highligting files (xml, sql). +* [Fix] Minor fix in CLI in order to associate .sch files to the scheditor. +* [Fix] Fixed a bug that was causing all layers to be active even if there was some inactive (invisible) when adding a new layer. +* [Fix] Fixed the method PgModelerCliApp::handleWindowsMimeDatabase to properly insert sch file association in Windows registry. +* [Fix] Fixed the "iCCP: CRC error" in PNGS at libs/libgui/res/icons +* [Fix] Minor fix in SyntaxHighlighter in order to return unformatted word when the group can't be forcibly defined in all exception cases when the word doesn't match any group. +* [Fix] Fixed the description of the option --output in CLI. +* [Fix] Fixed a bug in CLI that could lead to segfault when using diff option and a database model as input. +* [Fix] Fix broken build on Qt 5.11.x. +* [Fix] Minor fix in PgSQLTypeWidget to capture the text changing signal on data type combo so the type format input can be properly updated when the user types the desire data type. + +v0.9.4-alpha +------ +Release date: May 12, 2021
+ +* [New] Added compatibility code that allows loading models created in versions before 0.9.4-alpha without losing layers and active layers information. +* [New] Added an option to the metadata handling operation that serves to indicate if duplicated objects (textboxes, tags, generic sql) must be merged or not. +* [New] Added support for configuration parameters and transform types on functions and procedures. +* [New] Added the compatibility method QtCompat::horizontalAdvance(QFont, QString). +* [New] Added the ability to rename the default layer. +* [New] DatabaseModel now stores in XML code all the new settings related to layers (rect and name colors, rect and names display status). +* [New] Added several methods in ObjectsScene to handle layer colors that helps to save and restore colors from database model files. +* [New] Add support for custom layer colors in LayerConfigWidget. +* [New] Added the class LayerItem to create custom items for displaying layout rects in canvas. +* [New] Added an option to toggle layers rectangles and names from LayerConfigWidget. +* [New] Added support for setup, in general settings, the custom color for grid lines, canvas area and page delimiter lines. +* [New] Added support for multiple layers on the model. +* [New] Added support for PARALLEL attribute to functions. +* [Change] Minor improvement on "Forced filtering" option on ObjectsFilterWidget in order to use a list widget instead of single actions for each object type. +* [Change] Adjusted the default Qt version to 5.15.2 in the deployment scripts. +* [Change] Minor adjustments on Messagebox resizing during first display. +* [Change] Minor improvement on Messagebox in order to display the stack trace toggle button in a more intuitive way. +* [Change] Changed the behaviour of the method ObjectsScene::removeLayers, now it'll allow the resetting or not the layers of the objects. +* [Change] Minor adjustment on QTableWidget vertical header size on DataManipulationForm, ObjectsTableWidget and SqlExecultionWidget. +* [Change] Minor size adjustment policy in the comboboxes in DataManipulationForm, ModelNavigationWidget and ModelValidationWidget. +* [Change] Minor improvement in DatabaseImportHelper::setBaseFunctionAttribs in such a way to discover the name of the functions transform types from their oids. +* [Change] Isolated the duplicated code in DatabaseModel::createFunction and DatabaseModel::createProcedure in the method DatabaseModel::setBasicFunctionAttributes. +* [Change] Adjusted the minimum size of the main window to 640x480 so it can fit in smaller screens. +* [Change] Minor refactoring on SchemaView::configureObject to avoid unecessary calculations when the layers are not visible. +* [Change] Added forced updates of schema rectangles after setting layers to children objects. +* [Change] Change on the search path for PluginsDir to use getPathFromEnv(). +* [Change] LayersConfigWidget will now emit a signal when toggling layer rects/names so the overview widget on mainwindow is properly updated. +* [Change] DatabaseModel will now create a default layer in the constructor. +* [Change] The database model will add the default layer to the loaded model if there isn't a single layer identified. +* [Change] DatabaseModel when loading older database model files will generate random layer colors. +* [Change] The scene now will update layer rects when catching the signal s_objectDimensionChanged from tables and textboxes. +* [Change] Adjust the ObjectsScene to resize layer rects when one or more layers are removed. +* [Change] Improved the window title of DataManipulationForm in sucha a way to display the currently browsed table. +* [Change] Improved the selection of layers to be associated to object in context menu (Quick > Set layers). Now a floating widget is use to select multiple layers for the object selection in the canvas area. +* [Change] Updated the sample models to use "layers" attributes on graphical objects. +* [Change] Changed the value separator for attributes layers and active-layers on from semi-colon to comma. +* [Change] pgModeler CLI will now rename "layer" attributes to "layers" in order to reflect the multiple layers support for older models. +* [Change] Minor copyright updates. +* [Change] The option "Truncate before alter columns" in the diff process was removed since its use is discouraged and dangerous in some situations. +* [Fix] Minor fix in the table's catalog query in order to avoid setting up a partitioning strategy when the table is not a partitioned one. +* [Fix] Minor fix in database import in such a way to update scene layers info before adding it to the main window. +* [Fix] Fixed the layers configuration of example.dbm. +* [Fix] Minor fix in function.sch in order to generate transform types only for PostgreSQL >= 9.5. +* [Fix] Fixed DatabaseModel::getUserDefTypesReferences in such a way to detect that procedures and functions are referencing a user-defined type from their list of transform types. +* [Fix] Fixed ObjectsTableWidget in such a way to control whether the ResizeColsButton can be displayed or not via ObjectsTableWidget::setButtonConfiguration. +* [Fix] Minor fix to avoid black canvas when using settings from 0.9.3 or below on 0.9.4-alpha. +* [Fix] Minor fix in BaseObjectView in such way to avoid the adjustment of its position to the scene grid when the object is not selected. This can avoid undesired adjustment when moving a schema box and having only a portion of its children selected. +* [Fix] Minor fix in ObjectsScene in such a way to update layer rects when the grid alignment option is toggled. +* [Fix] Fixed the buttons shortcuts on LayerConfigWidget. +* [Fix] Minor fix on SchemaView to compute the last position any time the object is reconfigured. +* [Fix] Minor fix in BaseObjectWidget to avoid mark the object as modified in finishConfiguration() before adding it to the parent. +* [Fix] Fixed the key combination to trigger the magnifier tool. +* [Fix] Fixed LayerItem in order to build in Qt 5.9. +* [Fix] Minor fixes in ModelWidget, MainWindow to update scene layer settings correctly. +* [Fix] Fixed the CLI in such a way to update scene layer settings so the exporting processes can generate graphical files correctly. +* [Fix] Minor fix in LayersConfigWidget in such a way to mark the correct active layers when setting up the model to operate on. +* [Fix] Fixed a bug in the layers removal process that was causing objects to be placed in a incorrect layer index after the removal. +* [Fix] Fixed the "Fix" menu in main tool bar. +* [Fix] Fixed a bug in ModelWidget that was causing overlay to be displayed when a textbox object was selected. +* [Fix] Fixed wrong text in collationwidget.ui. +* [Fix] Fixed a bug during the loading of changelog entries. +* [Fix] Fixed the display of warnings during export in ModelExportForm. +* [Fix] Fixed the display of warning messages during export in ModelDatabaseDiffForm. +* [Fix] Fixed a malformed SQL code for triggers. +* [Fix] Fixed typos in README.md. +* [Fix] Fixed the broken build on Qt 5.9.x. +* [Fix] Fixed a bug that was preventing special PKs to be properly configured. +* [Fix] Fixed the SQL generation of functions based on internal language. + +v0.9.3 +------ +Release date: December 30, 2020
+ +* [New] Added support for deterministic and provider attributes in collations. +* [New] Added missing check constraints in the data dictionary. +* [New] Added support for selecting all relationships of a table at once via right-click on a table > select relationships. +* [New] Added extra search fields in ObjectFinderWidget. Now it's possible to search relationships by the involved tables (source and destination table), constraints by their columns (source and referenced columns), and relationships by the foreign keys related to them. +* [Change] The warning message about the unchecked option related to drop missing objects now pops up only when there are partial diff filters configured. +* [Change] Improved the extended fade in/out options for tables/views/foreign tables. +* [Change] The partial diff filters generated from changelog will ignore table children objects in order to avoid the wrong generation of diff code. +* [Change] Minor refactoring in DatabaseModel::addChangelogEntry in order to use new attributes to define changelog operations. +* [Fix] Fixed a crash when trying to select children objects of a schema that has no rectangle defined. +* [Fix] Fixed a crash during the importing of domain objects. +* [Fix] Fixed a crash during the importing of objects into the current model in very specific cases when the model had some tables/views referencing columns added by relationship. +* [Fix] Fixed the full diff switching when there are no filtered objects in ModelDatabaseDiffForm. +* [Fix] Fixed a bug in DatabaseModel::addChangelogEntry that was causing the registration of empty signature for some objects. +* [Fix] Fixed a bug in CLI that was not accepting the use of --list-conns parameter +* [Fix] Fixed the data dictionary generation in such a way to include nextval(sequence) calls in the "default value" column. +* [Fix] Fixed a bug when configuring spatial data types during reverse engineering/diff. +* [Fix] Fixed a bug in Catalog::parseDefaultValues that was causing ARRAY[] values to be wrongly split. +* [Fix] Fixed a bug that was causing infinite validation of imported sequences. + +v0.9.3-beta1 +------ +Release date: October 5, 2020
+ +* [New] Added the version descriptor for PostgreSQL 13. +* [New] Added support for procedures in design, import and diff processes. +* [New] Added support for transforms in design, import and diff processes. +* [New] Added an entry in NewObjectOverlayWidget for procedures. +* [New] Added a custom version of addParameter to Procedure in order to validate the usage of out parameters. +* [New] Added a tool button for transform objects in NewObjectOverlayWidget +* [New] Added a unit test to verify schema files syntax (sql, xml, alter). +* [New] Added the method Cast::setName to override the default behavior of BaseObject::setName. +* [New] Added the class PgModelerUnitTest that must be inherited so the child test class can have access to schema files path. +* [New] Added support for modifying attributes toggler colors from appearance settings. +* [New] Tag objects now include attribute toggler colors. +* [Change] Changed the behavior of the generation of SQL code for database object, now it'll respect the SQL disabled status of the object. +* [Change] The ModelExportHelper will abort the export process if the SQL code of the database object is disabled. +* [Change] The database model is now flagged as modified everytime the objects are swapped. +* [Change] Improved the ObjectSelectorWidget in order to save/restore the geometry of internal ModelObjectsWidget instances. +* [Change] Ajusted the Qt version check in QFontMetricsCompat and QPlainTextEditCompat in order to avoid deprecation warnings. +* [Change] pgModeler will alert about a possible data/work loss if the user is trying to save a model in which there're other instances loaded other tabs. +* [Change] Refactored FunctionWidget in such way to make it a subclass of BaseFunctionWidget. +* [Change] Removing unused method DatabaseModel::removeObject(unsigned,ObjectType). +* [Change] Moved the DTD defintion of parameter tag to a dedicated file to be shared betwen function.dtd and procedure.dtd. +* [Change] Making the class Function be a direct child of BaseFunction. +* [Change] Moved the common code between functions and procedures to a base class called BaseFunction. +* [Change] Replaced the attributes PhysicalTable::DataSeparator and DatabaseExplorerWidget::ElemSeparator usages by PgModelerNs::DataSeparator. +* [Change] Minor improvement on data dictionary in order to add the current year in the footer. +* [Change] ModelExportHelper now is capable of indetifying a transform and procedure objects being exported. +* [Change] Minor fields sizes adjustment in pgsqltypewidget.ui +* [Change] Improved the schema files syntax tests to include all folder under / schemas. +* [Change] Refactored the schema files in order to remove code duplication related to ddl-end token. +* [Change] Minor improvement in ConfigurationForm by adding a splitter between config items (left) and settings page (right). +* [Change] Minor improvements on objects rendering in order to consider screen dpi when configuring objects border sizes. +* [Change] Minor refactoring in the parameter/signature generation in class Function. +* [Change] Making the NewObjectOverlay less transparent in order to enhance reading. +* [Fix] Fixed a bug in constraint.sch that was avoiding the correct importing of exclude of constraints. +* [Fix] Fixed source file name for PgModelerCliApp. +* [Fix] Minor fix in the SyntaxHighlighter in order to highlight correctly multline blocks (specially comments). +* [Fix] Fixed a bug in DatabaseImportHelper that was causing failure when importing some objects' permissions. +* [Fix] Minor fixes on the CLI menu. +* [Fix] Fixed a bug on MainWindow that was wrongly showing the main menu bar in certain cases at startup. +* [Fix] Minor fix in BaseFunction::createSignature in order to remove OUT keywords from signature. +* [Fix] Fixed a bug when importing triggers in which functions arguments contain json/jsonb values. Now values are properly formatted. +* [Fix] Fixed a bug in XmlParser::convertCharsToXMLEntities that was not converting json/jsonb default values correctly breaking the entire XML code of the database model. +* [Fix] Fixed a bug in Parameter class that was causing default values to be ignored. +* [Fix] Fixed a bug in SchemaParser related to exceptions being raised wrongly in expressions evaluation. +* [Fix] Fixed the objects style template config files. +* [Fix] Removed some deprecation warnings when building on Qt 5.15.1. +* [Fix] Fixed a bug in ModelFixForm that was passing arguments to CLI in wrong format. +* [Fix] Minor fix in some project files to remove unnused include paths. +* [Fix] Fixed a bug in CLI that was ignoring input-db parameter when doing diff. +* [Fix] Minor fix in the graphical objects rendering in 4k screens when QT_AUTO_SCREEN_SCALE_FACTOR is set to. Now they are rendered in acceptable proportions. +* [Fix] Minor fix in ModelsDiffHelper in order to avoid generating ALTER...ADD COSTRAINT related to constraints (check and unique) in which parent table is also being created. + + +v0.9.3-beta +------ +Release date: July 10, 2020
+ +* [New] Added GitHub actions scripts in order to test the building on each platform. On Linux and macOs the build will occur on all Qt versions from 5.15 to 5.9, on Windows the build happens only on Qt 5.15 (due to the usage of msys2 that uses the most recent version of the framework). +* [New] Added default constructors in the form "Class(const &)" for Connection, Parameter and TypeAttribute in order to avoid deprecated-copy warnings on GCC9. +* [New] The CLI now validates the mixing of options of different operation modes. +* [New] Added support for partial diffs between a model and database or between two databases. +* [New] Created an internal changelog on DatabaseModel to register object's modification over time being useful for partial diff operations. +* [New] Added the widget called ChangelogWidget to control the model's internal changelog settings in the design view. +* [New] Added support for save/load changelog from model file. +* [New] The CLI now supports partial diffs too. +* [New] Create the method ModelsDiffHelper::getRelationshipFilters. +* [New] Added a warning message prior to the partial diff without using "Do not drop missing objects" option. +* [New] Created a method ObjectsFilterWidget::setModelFilteringMode that disables some options when the filtering widget is being used to filter database model objects. +* [New] Added cast and user mapping to the list of filterable objects. +* [New] Added a hint text in ObjectsFilterWidget to inform about exact match searching. +* [New] Added the methods Catalog::clearObjectFilter and Catalog::clearObjectFilters. +* [New] Added support for DatabaseImportHelper to create a sequence assigned to a column via default value if automatic dependencies resolution is enabled. +* [New] Created the namespace QtCompat that will reunite all the specific code that isn't compatible between different Qt versions. The goal of this namespace is to store in a central point all the code that uses QT_VERSION_CHECK to perform different operations depending on the current Qt version. +* [New] Added the method SchemaParser::getExpressionResult in order to perform comparisons between QVariant values correctly due to the QVariant operators deprecation in Qt 5.15. +* [New] Added the signal ObjectsFilterWidget::s_filtersRemoved that is emitted whenever all filters are removed. +* [Change] Modified the script wingetdate.bat in order to return the build number based on the current local date correctly and renamed it to getbuildnum.bat. +* [Change] Updated to 5.15 the Qt version used by default in linuxdeploy.sh and macdeploy.sh. +* [Change] Replacing verbose QString() calls by "" for string initialization purposes. +* [Change] Improved the sequences assignments to columns in DatabaseImportHelper::assignSequencesToColumns. +* [Change] Improved the method ModelsDiffHelper::setFilteredObjects in order to treat tables/view/foreign tables properly by appending their children objects to the creation order list of filtered objects. +* [Change] Adjusted the Catalog::setObjectFilters in order to configure exact match filters when any wildcard filter provided has no *. +* [Change] Adjusted the partial diff process between a model and a database in which there's one or more many-to-many relationships filtered. +* [Change] Minor adjustment on objects grids in SwapObjectsIdsWidget, DatabaseImportForm and ModelDatabaseDiffForm by changing the columns order. +* [Change] Improved the method ModelsDiffHelper::setFilteredObjects in order to detect the proper creation order of the provided objects. +* [Change] Minor change in ObjectsFilterWidget by making the action "Only matching" checked by default. +* [Change] Minor improvement on CLI to accept the value "all" for the paramenter --force-children in order to force all table children at once. +* [Change] BaseObject::configureSearchAttributes now configures the signature attribute as a formatted string. +* [Change] Minor improvement on ObjectFinderWidget::updateObjectTable in order to optionally create checkable items in the first column. +* [Change] Attributes related to object filters were moved from Catalog to PgModelerNs in order to be shared between Catalog and DatabaseModel classes. +* [Change] Minor improvement in Connection::getConnectionId in order to return an optional HTML formatted string. +* [Change] Isolated the method DatabaseImportForm::listFilteredObjects in a static one in order to reuse it on ModelDatabaseDiffForm. +* [Change] Improved the objects filtering in such way to allow filter by name or signature. +* [Change] Improved the UI of ObjectsFilterWidget by moving all options to a popup menu. +* [Change] Several changes in all catalog queries in order to support signature matching. +* [Change] Minor adjustemnt in Catalog::getFilterableObjectNames. +* [Change] Adjusted the appimages building process. +* [Change] Changing the default font size of graphical objects to 10pt in order to try to solve the intermittend issue of disappearing texts. +* [Change] Updated the French translation. +* [Fix] Fixed a regression in ObjectFinderWidget that was not opening objects form with double-click on an item on the results grid. +* [Fix] Fixed a bug when drawing relationships in FK to PK connection mode. Now when one of the tables is collapsed the center points of both are used as connection points to the relationship. +* [Fix] Fixed a crash in ModelDatabaseDiffForm while enabling/disabling the partial diff tab. +* [Fix] Fixed the diff process for inheritance relationships created for two existing tables. +* [Fix] Fixed a crash in LayersWidget when renaming a layer. +* [Fix] Minor fix in DatabaseImportHelper::assignSequencesToColumns. +* [Fix] Fixed a wrong comparison in Catalog::getObjectsOIDs. +* [Fix] Minor fix in ConstraintWidget that was trying to validate FK relationships for generated tables of many-to-many relationships. +* [Fix] Fixed a bug in Catalog::getObjectsOIDs that was executing a catalog query for a certain object when it was not being filtered. +* [Fix] Minor fix in ModelDatabaseDiffForm tabs enabling/disabling steps. +* [Fix] Fixed the QProcess usage in ModelFixForm due to QProcess::start() deprecation in Qt 5.15. +* [Fix] Fixed a crash when trying to move several objects to a layer from the object finder widget and in the selected set one or more objects aren't graphical ones. + +v0.9.3-alpha1 +------ +Release date: May 20, 2020
+ +* [New] Added support for creating initial configuration files from CLI. +* [New] The CLI is now capable of using the objects filtering in reverse engineering. +* [New] Added a warning message when trying to import a big database. +* [New] Added support for object filtering in reverse engineering dialog. +* [New] Adding support for AppImage building for Linux. +* [New] Added support for importing PostgreSQL 12 generated columns. +* [New] Adding support for PostgreSQL 12 generated columns. +* [New] The ModelNavigationWidget now will display a save icon if the current model is pending a save operation. +* [New] pgModeler now guesses if a FK relationship consists in a one-to-one based upon the foreign keys and unique keys settings. +* [New] Improved the rendering of FK relationships. Now it recognizes the minimum cardinality by using the right crow's foot descriptor o|< or ||< in the destination entity. +* [New] Added support for the conversion of 1-1 and 1-n relationships, allowing the user to perform modifications over objects generated by those relationships. +* [New] Added "virtual" keyword in classes that inherit others so the destruction order can be followed correctly. +* [New] Adding support for copy model validation widget output as text as well preview it as texts. +* [New] Added support for show/hide all layers in LayersWidget. +* [New] Added the paramenter application_name to Connection in order to indentify connections created by pgModeler when querying pg_stat_activity. +* [New] Added support for save/restore Z value attribute in MetadataHandlingForm. +* [New] Created an improved and reusable file selector widget. +* [Change] Improvements done in DatabaseImportHelper in order to speed up the listing of types as well the importing user-defined types on demand. +* [Change] Refactored the way default value fields states are setup by user's actions. +* [Change] Adjusted the default size of DatabaseImportForm. +* [Change] Avoiding retrieve all types (system and user defined) at once before the reverse engineering in DatabaseImportHelper (Experimental). +* [Change] Minor improvement on DatabaseImportHelper in order to display the correct message while assingning sequences to columns. +* [Change] Improved the catalog queries in order to retrive parent oids and type when using the list queries. +* [Change] Minor updates on windeploy.sh and macdeploy.sh +* [Change] Minor improvement on DatabaseImportHelper in order to speed up the objects creation. +* [Change] Improved the execution time for the catalog query of data types. +* [Change] Improved the catalog query for sequences. +* [Change] Avoiding the diff process to generate default value changes for generated columns. +* [Change] Minor improvement on DatabaseModel::validateRelationships. +* [Change] Improved the ModelWidget::convertRelationship1N() in order to avoid segfaults in certain cases. +* [Change] Minor adjustment in PhysicalTable::restoreRelObjectsIndexes in order to diminish memory usage. +* [Change] Minor improvement on update icon. +* [Change] Minor improvement in LayersWidget in order to allow manual resizing using the mouse. +* [Change] Improved the following classess in order to use the new file selector widget: ModelExportForm, ModelFixForm, MetadataHandlingForm, ModelDatabaseDiffForm, GeneralConfigWidget, PluginsConfigWidget, CsvLoadWidget, CrashHandlerForm and BugReportForm. +* [Fix] Minor fix in OperationList in order to update FK relationships related to FKs that contains the column being handled by the list. +* [Fix] Fixed a bug when retrieving the refs to some objects in DatabaseModel. +* [Fix] Minor fix in CLI menu and error messages. +* [Fix] Fixed the role importing process. Now referenced roles are auto resolved. +* [Fix] Fixed the dependency checking for user defined types in DatabaseModel. +* [Fix] Fixed a bug when loading extension that has no schema specified. +* [Fix] Minor fix in DatabaseImportHelper::createFunction in order to solve eventual duplicated parameter names when importing some functions. +* [Fix] Fixed a bug that was causing global name patterns for relationships to never be used even if they were properly configured. +* [Fix] Minor fix in ModelObjectsWidget and ModelWidget to provide the correct information about objects' selection in SceneInfoWidget. +* [Fix] Fixed a bug in RelationshipWidget that was causing the cursor never to be restored to its original icon when an exception occurred during relationship editing. +* [Fix] Fixed a crash in some situations when closing models. + +v0.9.3-alpha +------ +Release date: March 26, 2020
+ +* [New] Added support for multiselection in ModelObjectsWidget. +* [New] Added an optional parameter in PgModelerNs::generateUniqueName to avoid comparing the input object. +* [New] Added support for objects' bulk renaming. +* [New] Added support for multiselection in ObjectFinderWidget. +* [New] Added support for middle button click on source code panel in order to paste the selected code in the current open SQL execution widget. +* [New] Using the CRTP (Curiosly Recurring Template Pattern) approach to create a template type based on BaseType in such way that the static member from that template but used on all derived classes of TemplateType can be unique for each derived class. +* [New] Added a "Stacking" action in popup menu that is used to control the z value of graphical objects. +* [New] Adding support for move objects on the Z stack up and down. +* [New] Added support for CLI to write system wide mime database on Linux and Windows. +* [New] Added a method GlobalAttributes::setSearchPath so the application can setup the path in which the internal folders (schemas, lang, etc) can be found. +* [New] Added the ability to remove owners from objects from Quick Actions > Change owner. +* [New] Added an fix step that removes IN keyword from functions signatures. +* [Change] Refactored the method DatabaseModel::getObjectDependecies by splliting it into small portions that handles specific object types dependecies. +* [Change] The DatabaseModel::getObjectReferences was splitted in other get[object]References() in order to facilitate maintainance. +* [Change] Minor adjustments in order to make the objects listing a bit faster for large databases. +* [Change] Minor improvement on ObjectRenameWidget in order to apply renaming in reverse id order of the object so objects invalidations (due to relationships revalidations) diminishes. +* [Change] In DatabaseModel the invalidated special objects are now stored in a list which is destroyed only when the model is destroyed too. This will avoid segfaults in some cases when the objects in that list are still being referenced in the operation list (Experimental). +* [Change] Minor adjustment in ModelObjectsWidget and ObjectFinderWidget in order to emit the signal ModelWidget::s_sceneInteracted so the left menu at MainWindow can be updated accordingly. +* [Change] Minor change in PgModelerNs::generateUniqueName in order to remove quotes from names before perform the comparison. +* [Change] Refactored ObjectRenameWidget in order to support multiple objects renaming. +* [Change] Refectored all the classes derivated from BaseType moving them to dedicated sources files in order to make them reuse TemplateType class isolating the related keywords, improving maintainance. +* [Change] Removed the class LanguageType since it was replaced by namespace DefaultLanguages namespace. +* [Change] Isolated the default language names into a namespace called DefaultLanguages and removed any reference to LanguageType in the code. +* [Change] Improved the DataManipulationForm in such way that the user can sort results by clicking the column names in the result grid. This will cause a new query to be performed by using the clicked column as sorting criteria. +* [Change] The current model's popup menu is now used as the "More" actions menu at MainWindow > general toolbar. +* [Change] Refactored the ModelWidget::configurePopupMenu separating some portions in new methods to make maintainance more easy. +* [Change] Moved the 'Fix model' and 'Objects metadata' actions to the general toolbar (left) at main window under the menu "Fix". +* [Change] The class HintTextWidget was removed and replaced by simple html QToolTips. +* [Change] Small change in the icon related to new tab opening in SQLToolWidget. +* [Change] Minor adjustment or rows resizing policy on datamanipulationform.ui. +* [Change] Minor adjustment on updatenotifierwidget.ui to allow link opening. +* [Change] Refined the installer wizard pages. +* [Change] Improved the installer script to work better on Windows. +* [Change] Improving the installer on Linux and Windows to select the installation for all users or current user. +* [Change] Improved the linuxdeploy.sh in order to remove the need to use the startup scripts by the binaries in the installer. +* [Change] Fixed the installscript.qs in order to correctly update the mime database on Linux. +* [Change] Minor improvements on the usability of swap objects ids form. +* [Change] Separated the code that handles mime db on linux and windows, using a #ifdef switch to call the correct method depending on the platform. +* [Change] Adjusting the linker options to make the executables search for libraries in PRIVATELIBDIR without forcing the usage of LD_LIBRARY_PATH. +* [Change] The class Application was moved to libutils and has a basic implementation of just initialize the search path on GlobalAttributes. +* [Change] Rename the classes Application and PgModelerCli to respectively PgModelerApp and PgModelerCliApp and they now inherits the new Application class in order to take advantage of the GlobalAttributes::setSearchPath. +* [Change] The crash handler application is now executed under a Application instance not a QApplication anymore in order to use GlobalAttributes::setSearchPath. +* [Change] Changed the namespace GlobalAttributes to a singleton in order try to solve problems with fallback paths. +* [Change] Updated deployment scripts to use Qt 5.14.x +* [Change] Changing the exposed main window from QMainWindow to MainWindow in PgModelerPlugin interface. +* [Change] Moved the method SchemaParser::convertCharsToXMLEntities to XmlParser. +* [Change] Minor buttons position adjustments on WelcomeWidget. +* [Change] Minor refactoring on OperationListWidget in order to show a more compact text when displaying operations done over objects. +* [Change] Removed the workaround code that disables the ALTER SET OWNER when the role associated to it is disabled and the object itself not. The best approach is to dissociate the role from the object so the ALTER instruction is not generated. +* [Fix] Fixed a shortcut duplication in DatabaseExplorerWidget +* [Fix] Fixed the shortcut for partitioning relationships in new object overlay +* [Fix] Fixed a minor bug in MainWindow that was causing the bottom widgets bar to be displayed even when object finder widget and model validation widget weren't visible. +* [Fix] Fixed a bug that was causing copy options to stay hidden for copy relationships in the relationship form. +* [Fix] Fixed the importing of extensions on PostgreSQL 9.4 and below. +* [Fix] Fixed the name uniqueness generation when the name is truncated when exceeding 63 bytes. +* [Fix] Fixed a bug that was preventing the recent menus cleaning to be persisted in the conf file. +* [Fix] Fix a bug in the validation of collation objects. +* [Fix] Fixed a crash in ObjectRenameWidget when renaming several objects in which there was the need to revalidate relationships; +* [Fix] Fixed the method PgSqlType::getTypes in order to avoid returning the first (null) type. +* [Fix] Fix the importing/diff of columns based on PostGiS data types. +* [Fix] Fix a crash in UpdateNotifierWidget when compiling pgModeler using Qt 5.14.x. +* [Fix] Minor fix in PgSQLTypeWidget to avoid show an error message box when the user types an invalid data type name. +* [Fix] Additional fix on XmlParser::convertCharsToXMLEntities in order to replace special char to xml entities correctly. +* [Fix] Minor fix in the update notifier widget display position. +* [Fix] Minor fix in diff regarding to the comparison on column/domain default values. Now the values are compared in insensitive case. +* [Fix] Fixed the Windows installer in order to create the start menu item correctly (system wide). +* [Fix] Minor fix on CLI in order to allocate export/import/diff helpers and config widgets only when they are required (when one of the options related are used). +* [Fix] Fixed a bug that was allowing the applying changes of the forms on relationship added objects by hitting ENTER causing crashes. +* [Fix] Fixed the bug that was causing model restoration to be displayed when the application was started from a double click on a model file. +* [Fix] Fixed a bug in the metadata handling that was not restoring the collapse mode of tables. +* [Fix] Fixed a crash on UpdateNotifierWidget after upgrading to 5.14. A wrong deletion was being performed where deleteLater() needed to be used instead +* [Fix] Removing lots of Qt 5.14 deprecation warnings in the code. +* [Fix] Fix a bug that was causing wrong replacements during the reverse engineering of functions. +* [Fix] Fixed the method XmlParser::convertCharsToXMLEntities in order to avoid chars replacements within Release date: December 26, 2019
+ +* [New] Add support for data dictionaries generation in HTML format in ModelExportForm. +* [New] Added options to control data dictionary generation in CLI. +* [New] Plugins now can optionally be associated to a menu action or not. Generally, an plugin not associated to a menu action is automatilly executed during the startup (see PgModelerPlugin::initPlugin). +* [New] Added a missing model fix step on CLI that removes the IN keyword from functions signatures. +* [Change] Making BaseRelationship::getReferenceForeignKey() public. +* [Change] Isolated duplicated code in MainWindow::isToolButtonsChecked that checks if any tool button of the bottom or right widget bars is checked. +* [Change] Removing the plugins from core code. +* [Change] Modified pgmodeler.pro to include plugins folder when present in the source root (either in debug or release mode). +* [Change] Ignoring plugins folder in the core code. +* [Change] Minor improvement on ModelWidget::rearrangeSchemasInGrid in order to consider the amount of tables to determine the minimum grid size used to rearrange table. +* [Change] Minor text adjustments in CLI. +* [Change] Added an additional checking during relationship creation in order to avoid the creation of 1-* or n-n relationships involving partition tables. +* [Change] Removing the restriction to create 1-1, 1-n and n-n relationships in which the involved tables are partitioned ones. +* [Change] Disabling the SQL statment ALTER...OWNER TO in the object's SQL when the owner role has its SQL disabled but the object itself not. This will avoid reference errors when validating/exporting code. +* [Fix] Fixed the "Save" action enabled state according to the current model's modified state. +* [Fix] Fixed a crash when the user tried to edit connections in ModelDatabaseDiffForm and right after select a connection in the "Compare to" field. +* [Fix] Fixed the generation of escaped comments for columns. + +v0.9.2-beta2 +------ +Release date: November 1st, 2019
+ +* [New] Added support for foreign tables. +* [New] Added the method DatabaseModel::getObject(QString,vector) to return the first ocurrency in the lists related to the provided types. +* [New] Added support for select all foreign tables in ModelWidget. +* [New] Created the method BaseTable::isBaseTable to help determining if an object type is of Table, View or ForeignTable. +* [New] Added extra support for foreign tables on DatabaseExplorerWidget and DataManipulationForm. +* [New] Added the method DatabaseImportHelper::createColumns in order to isolate the code to create table/foreign table columns during reverse engineering. +* [New] Added support for foreign table importing as well its children objects (columns, constraints, triggers). +* [New] Added server and options fields on TableWidget for foreign table. +* [New] TableWidget now fully supporting the edition of foreign tables. +* [New] Added the ability to TableView to render ForeignTable objects. +* [New] Added support for swap objects ids using arrow keys by changing creation order between two close objects on the grid. +* [New] Added support for save diff settings in form of presets. +* [New] Added an option to BaseObject to force the comment escaping making multilined comments be presented as single lines but without changing their semantics. +* [New] Adding support for parse escaped text delimiters and value separators in CSVLoadWidget. +* [Change] Avoiding the usage of "Generate ALTER commands" option when the table is a partition or partitioned. +* [Change] Avoid unchecking PK checkboxes on TableWidget when adding a new column. +* [Change] Validating the dialogs geometry regarding to screens geometry in order to avoid their appearance in an invalid position (out of range). +* [Change] Limiting the size of the exceptions stack in 50 elements. +* [Change] Improved the GenericSQL::isObjectReferenced in order to check if, when a referenced object is a column, the provided object is the same as the parent of that referenced object. +* [Change] Restricting the usage of "Default partition" option for partitioning relationships when the partition table is a foreign table. +* [Change] Making ModelObjectsWidget update the foreign table subtree. +* [Change] Making ReferenceWidget to use foreign tables from referenced table selector. +* [Change] Improved the Relationship class to accept foreign tables. +* [Change] Improved the DatabaseModel::getObjectDependecies and DatabaseModel::getObjectReferences to include ForeignTable. +* [Change] Updated View class to accept reference foreign table columns. +* [Change] Moved the original implementation of DatabaseModel::createTable to a template method createPhysicalTable in order to reuse it to create tables and foreign tables. +* [Change] ForeignObject is not a BaseObject child anymore due to multi inheritance problem that it can generate in ForeignTable class. +* [Change] Minor ajustment in Relationship class to accept PhysicalTable in its constructor so relationships can be used by ForeignTable class as well. +* [Change] Isolated the code common to Table and ForeignTable classes in a parent class named PhysicalTable. +* [Change] Disabling mime type update on installers. +* [Change] Minor adjustment on SQLExecutionWidget::generateBuffer to escape line breaks and separators when generating CSV buffer. +* [Change] Removing unused code from NumberedTextEditor. +* [Change] Changed the way temp source file is handled by the tool in order to solve a sharing violation problem on Windows. +* [Change] Minor adjustment on HtmlItemDelegate to avoid creating local variables in paint() everytime the method is called. +* [Fix] Fixed an bug in SQL generation of columns that was wrongly removing a comma from decimal data types. +* [Fix] Fixed some catalog queries in order to support PostgreSQL 12. +* [Fix] Fixed ObjectsScene to remove foreign tables during destruction. +* [Fix] Fixed the View::getObjectCount in order to return 0 when the provided object type is invalid. +* [Fix] Fixed the ObjectFinderWidget in order to fade out correctly the listed/not listed elements. +* [Fix] Fixed the quick actions menu at ModelWidget in order to include the "Edit data" action for foreing tables. +* [Fix] Fixed the DatabaseImportHelper::assignSequencesToColumns in order to correctly assign sequences to foreign table columns. +* [Fix] Fixed a crash in ModelValidationHelper that was caused by wrong checking when validating generic sql objects. +* [Fix] Fixed the source code display for tables and foreign tables on DatabaseExplorerWidget. +* [Fix] Fixed the CodeCompletionWidget to display foreign table children. +* [Fix] Fixed the loading of generic SQL objects when a referenced object was a column. +* [Fix] Additional fixes to correctly reference foreign tables and tables in the portions were both classes are acceptable/desirable. +* [Fix] Fixed the diff process in order recognize partition foreign tables attach/detach. +* [Fix] Fixed the generation of XML code of partitioning relationships. +* [Fix] Fixed the Relationship::getAlterRelationshipDefinition to include foreign tables. +* [Fix] Fixed the preset.sch since it was not registering the "Reuse sequences" options correctly. +* [Fix] Improved the DataManipulationForm in order to restore the columns visibility when retrieving again the data of the current table. +* [Fix] Fixed the drop action in DatabaseExplorerWidget for user mappings. +* [Fix] Fixed the ModelWidget::rearrangeTablesInGrid to adjust position of foreign tables. +* [Fix] Fixed the generation of SQL code of partition tables in order to avoid the inclusion of partitioned tables columns on the code. +* [Fix] Fixed a crash on DatabaseImportHelper when destroying detached inherited columns. +* [Fix] Fixed the object duplication operation in model widget to accept duplicate foreign table children objects. +* [Fix] Fixed the creation of relationships involving foreign tables. +* [Fix] Fixed the permission object in order to support foreign tables. +* [Fix] Fixed the model export helper to support foreign tables. +* [Fix] Fixed ModelWidget to show missing popup actions for foreign tables. +* [Fix] Fixed the NewObjectOverlayWidget to display tool buttons related to foreign table children. +* [Fix] Fixed the SchemaView::fetchChildren to include foreign tables in the returned list. +* [Fix] Fixed the ModelValidationHelper to validate foreign tables and table-view relationships. +* [Fix] Fixed ColumnWidget and ConstraintWidget to accept foreign tables usage. +* [Fix] Fixed a regression when importing permissions related to functions. +* [Fix] Fixed the OperationList to handle foreign tables. +* [Fix] Fixed create methods in DatabaseModel related to table children object in order to accept foreign tables. +* [Fix] Fixed the SwapIdsWidget postion/size saving and restoration. +* [Fix] Minor tooltip fix in GeneralConfigWidget. +* [Fix] Minor fix in default conf files removing unused tag attribute. +* [Fix] Additional fix to the extension import to correctly indetify it as a data type handler. +* [Fix] Fixed a bug on Role's SQL generation due to a missing attribute. +* [Fix] Additional fix in GeneralConfigWidget to save correctly the settings of dockwidgets. +* [Fix] Minor fix in DatabaseModel to write ddl end token in the appended/prepended custom code. +* [Fix] Fixed a false-positive result when doing the diff between two fuctions that contains the same signature. +* [Fix] Fixed the diff generation for Role objects when setting up an blank password. +* [Fix] Fixed the "Prepend at the beggining of the model" option behavior on CustomSQLWidget. +* [Fix] Fixed the catalog query for extension in order to indetify correctly if this object handles a data type. +* [Fix] Fixed the Variadic option enabling on ParameterWidget. +* [Fix] Fixed the saving of validator widget settings. There was a conflict between pgsql-ver attributes present on the validator settings and the default attribute added by the schema parser. The solution was to use a different attribute (version) in the validator. +* [Fix] Fixed the "Clear items" action in popup menu at DataManipulationForm. +* [Fix] Fixed the importing of tables and views in such way to automatically create correctly the domains referenced by their columns. +* [Fix] Fixed a bug on ModelDatabaseDiffForm that was causing the form to be reseted on the middle of a diff process when the user minimize the diff dialog causing unexpected behavior (or even crashes sometimes). +* [Fix] Minor fix in AboutWidget. +* [Fix] Minor fix in ModelDatabaseDiffForm to avoid using uniform items height in output widget. + +v0.9.2-beta1 +------ +Release date: September 2, 2019
+ +* [New] Added a routine to write a backup file during the saving of model files in order to avoid data loss in some rare cases. +* [New] Added a new action on DataManipulationForm to clear the selected items by pressing Ctrl+R. +* [New] Enabling/disabling the save model action according to the model's modified status. +* [New] The main window instance is now exposed to plugins to make the extra features development more flexible. +* [New] Avoiding selecting table items in BaseTableView::mousePressEvent which doens't contain an underlying (source) object. +* [New] Adding support for duplicate several table objects at once. +* [New] Added support for table children multiselection by using Ctrl+Shift+Click on them. +* [New] Added support for load the generated diff code in the SQL tool and automatically browsing the destination server for manual diff applying. +* [New] Added a button to create a new data manipulation form from within another data manipulation form. +* [New] Added a confirmation message before closing a database explorer widget. +* [Change] Minor adjustments in PgModelerUiNs::createOutputListItem and PgModelerUiNs::createOutputTreeItem to better display formatted messages. +* [Change] Minor improvement on CSV text copying to exclude from the buffer the hidden columns. +* [Change] Adjusted the font weight on WelcomeWidget (only for Linux). +* [Change] Minor adjustment on tool buttons font size on DataManipulationForm. +* [Change] Improved the UI of the DataManipulationForm by rearranging the tool buttons to the left of the dialog. +* [Change] Improved the clipboard text pasting on DataManipulationForm in order to parse the text as CSV when Ctrl+Shift+V is pressed. +* [Change] The filter input on SQLExecutionWidget is now automatically focused when toggling the filter widget. +* [Change] Changed the default behavior of result set filtering to Qt::MatchContains on SQLExecutionWidget. +* [Change] Avoiding showing the "Swap ids" action in popup menu when we have only columns/constraints selected +* [Change] Minor adjustment on SceneInfoWidget to avoid display dimensions of selected columns/constraints on the canvas. +* [Change] Renamed the method BaseGraphicObject::getReceiverObject to getOverlyingObject (to make sense with its counter part BaseObjctView::getUnderlyingObject) +* [Change] Avoiding clear the whole scene selection when the table is already selected and the user requested popup menu. +* [Change] Renamed BaseObjectView::getSourceObject to getUnderlyingObject. +* [Change] Improved the object protection action in ModelWidget in order to accept the multi item selection on tables. +* [Change] Changed the way the PSVI attribute is handled in xmlparser to retrieve big line numbers on a xml document. +* [Change] Improved the diff code preview allowing the user to close the dialog without going back to previous tab and click 'Cancel'. +* [Change] Minor adjustment on buttons shortcuts/tooltips on DataManipulationForm. +* [Change] Changed the way the model saving timers are controlled to avoid infinity savings on the model (when the auto saving option is disabled) making the application unusable. +* [Change] Making the mime update operation return exit code 0 even if there was errors (still displayed in the console). This will avoid the installer to abort installation when the dbm mime update fails. +* [Change] Avoiding applying fillfactor to gin indexes. +* [Change] Moved the method DatabaseImportHelper::parseIndexExpressions to Catalog class. +* [Fix] Fixed a broken diff code generation for policies. +* [Fix] Fixed the object duplication action when only a single table object is selected. +* [Fix] Fixed a bug in ModelWidget::removeObjects that was causing the removal of relationship added columns +* [Fix] Fixed the ModelWidget::configurePopupMenu to consider the table's multi item selection. +* [Fix] Fixed a false-positive diff result when dealing with timestamptz. +* [Fix] Fixed the progress calculation of dbm files loading. +* [Fix] Fixed a bug that was causing the generation of broken view code. +* [Fix] Fixed the display of index expressions on DatabaseExplorerWidget. +* [Fix] Minor fix on SQLExecutionWidget to avoid results grid to overlap command execution history widget in certain cases. + +v0.9.2-beta +------ +Release date: May 31, 2019
+ +* [New] Added support for user mapping. +* [New] Added support for foreign server. +* [New] Added support for foreign data wrapper. +* [New] Added support for reduced verbosity on diff, export and import processes in order to improve performance. +* [New] Adding missing tootip on ObjectFinderWidget. +* [New] Generic SQL objects now support dynamic references to objects which can be used in the definition code. +* [New] Added support for compare foreign servers on diff process. +* [New] Created a generic getAlterDefinition on ForeignObject. +* [New] Added ForeignServer toolbutton in NewObjectOverlayWidget. +* [New] Added support for the reverse engineering user mapping objects. +* [New] Added support for the reverse engineering foreign server objects. +* [New] Added code snippets for foreign data wrapper and foreign server. +* [New] Added support for diff user mapping. +* [New] Added support for diff foreign data wrappers. +* [New] Added support for set permissions to foreign data wrapper. +* [New] Added the WRAPPER, SERVER and MAPPING key words to sql-highlight.conf. +* [New] Added the method PgSqlType::isExactTo in order to do a full comparison (all attributes) between two data types. +* [New] Added the ability to view references to store referenced tables. This feature will cause relationships to be created between the view and the referenced tables. This is useful when we're using reverse engineering feature in which, in previous versions, couldn't determine the tables that were linked to a view. Now, with this feature a relationship is created between the view and all involved tables. +* [New] Added missing data type macaddr8. +* [New] Enabling quick clear button on several input fields. +* [New] Added support for result set filtering in the SQL execution widget. +* [New] Adding a column labeled "Comment" in TableWidget and ViewWidget to hold comments of children objects. +* [Change] Changed the shortcut of run SQL action in SQLExecutionWidget to F5. +* [Change] Changed the shortcut of tree update action in DatabaseExplorerWidget to F6. +* [Change] Change "New object" action in popup menu in order categorize object types when clicking the database object diminishing the amount of items displayed on the screen. +* [Change] Improved the object search mechanism in such way that various attributes of the object can be matched. New searchable attribute may be added in the future. +* [Change] Added missing code documentation. +* [Change] Minor adjustment on ForeignDataWrapper::getAlterDefinition. +* [Change] Minor improvement on ModelDatabaseDiffForm to show the connection id of the databases being imported in the output tree. +* [Change] Formatting server objects' attributes on DatabaseExplorerWidget. +* [Change] Minor adjustments on the icons of the buttons in ObjectsTableWidget. +* [Change] Improved the method DatabaseModel::getObjectReferences to detected foreign data wrappers as functions' references. +* [Change] Minor code refactoring on Table and View classes. +* [Change] Renamed the method Exception::getErrorType to Exception::getErrorCode. +* [Change] Improved the ModelValidationWidget in such way that is possible to operate over objects on the output list through their respective context menu (the same as in the ModelWidget). +* [Change] Now its possible to trigger the swap ids dialog for two selected objects, causing their ids to be swapped more quickly. +* [Change] Minor refactor on schema files. +* [Change] Minor attributes refactoring on several classes. +* [Change] Minor change in the PgSqlType constructor by turning some parameters optional in order to facilitate the creation of array only types. +* [Change] Minor update on disclaimer text at start of the source files. +* [Change] Allowing copied object to be pasted multiple times. This feature works only with copy/paste operation without remove the pasted objects from the clipboard, for cut/paste the behaviour is unchanged. +* [Change] Increased the maximum limit of SQL history. +* [Change] Updated the windeploy.sh and the installer scripts. +* [Change] Adjusted the installer scripts. +* [Change] Changed the windows deploy script to use Qt Installer Framework. +* [Change] Adjusted the deploy script to use Qt 5.12. +* [Change] Fixed the windows deploy script to use newer version of the compiler in 64 bits environment. +* [Change] Minor improvements in SQLToolWidget and SQLExecutionWidget to avoid segmentation faults when trying to close a execution tab while the command is still running. +* [Change] Adjusted the resize parameters in DataManipulationForm to avoid wrong dialog resizings mainly on Windows. +* [Fix] Fixed a bug in DataManipulationForm that was deleting new rows wrongly. +* [Fix] Fixed a bug that was causing domain constraints not to be extracted correctly during reverse engineering. +* [Fix] Fixed a bug that was causing a fk relationship not to be deleted if the fk tied to it was changed by the user. +* [Fix] Fixed a bug on CLI that was not fixing broken models correctly when they had no role declaration. +* [Fix] Fixed a bug that was causing tables not to be moved on the canvas using mouse. +* [Fix] Fixed a crash related to destruction of special objects on DatabaseModel::destroyObjects. +* [Fix] Fixed a bug that could crash the application when no language was specified to a funcion and the SQL/XML code was being generated. +* [Fix] Minor fix a bug on index importing. +* [Fix] Minor fix on View::isReferencingTable. +* [Fix] Fixed a crash when a query executed in SQLExecutionWidget was a DDL one or was not returning results. +* [Fix] Fixed a bug in CLI that was failing to fix model in certain cases. +* [Fix] Minor fix on buttons tooltips. +* [Fix] Fixed a bug that was causing syntax error if the last column of a table had the SQL code disabled. +* [Fix] Fixed a bug on diff process due to a missing attribute on the generation of diff code for inheritance relationships. +* [Fix] Fixed a bug when rendering several self relationships attached to the same table. +* [Fix] Fixed the CLI in order to restore the layers information when fixing a broken model. +* [Fix] Fixed a bug in object finder that was causing objects from a hidden layer to be displayed causing inconsistency on the layer state. + + +v0.9.2-alpha1 +------ +Release date: December 17, 2018
+ +* [New] Added support for scene layers. +* [New] Added support for view's columns importing in DatabaseImportHelper. +* [New] Added the ability to load view columns from database model file in DatabaseModel::createView. +* [New] Added a tab "Columns" in ReferenceWidget where the user will be able to insert columns to be used as view columns. +* [New] Added support for pagination of tables and views columns pagination. +* [New] Added a pagination toggler action on context menu at ModelWidget. +* [New] Added a fix step on CLI to remove the deprecated attribute hide-ext-attribs from tables and views xml code. +* [New] Added a configuration option to control attributes per pages in tables and views. +* [New] Added support for save collapsing states and current attributes pages to the database model file. +* [New] Added constants to reference child objects of TableObjectView. +* [New] Added the class TextPolygonItem which can be used to draw a text over a background polygon. +* [New] Added support for OLD/NEW tables aliases on triggers. +* [New] Added a hint text on RelationshipWidget to document the correct usage of default partitions. +* [New] Added support for partition attaching/detaching detection in diff process. +* [New] Added auxiliary methods in Table class in order to add/remove and retrieve partition tables. +* [New] Added support for importing partitioned/partition tables on DatabaseImportHelper. +* [New] Added a missing validation in Relationship to avoid creating other types of relationships involving partitioned or partition tables. +* [New] Added support for specify partition bounding expression on partitioning relationships. +* [New] Added support for resize grid cells to fit contents on ObjectsTableWidget. +* [New] Added a tab "Partition keys" that will handle partitioning configuration on TableWidget. +* [New] Added a method in ObjectsTableWidget to hide some horizontal header sections. +* [New] Added some validations when creating partitioning relationships. +* [New] Added support for hide columns on data manipulation dialog. +* [New] Added a transient attribute to objects DatabaseModel, Table and View in order to give a hint on the maximum count of objects held. This attribute is used to preallocate the vectors which store the children objects in order to avoid excessive memory allocation/deallocation due to vector resizing. +* [New] Added a column labeled "Alias" on all objects tables in TableWidget so the aliases of children can be displayed. +* [New] Added support for adding tabs via shortcut or corner button in the SQL Execution panel. +* [Change] Minor adjustments on MainWindow to make the overview widget to update its contents whenever the active layers change on the current model. +* [Change] Minor adjusment in ObjectsScene::addItem to make the item (in)visible according to the visibility of its related layer. +* [Change] Minor fix in AttributesTogglerItem in order to consider the parent's opacity during painting. +* [Change] Minor fixes in OperationList in order to force views to be updated correctly when operating over a table which is referenced by those objects. +* [Change] Minor adjustments on SchemaView and BaseTableView (and its children classes) to update the geometry when they switch from invisble to visible state. +* [Change] Changed views in such way so they can use the struct SimpleColumn to represent their deduced columns. +* [Change] Improved the update of views when referenced columns and tables change their structure. +* [Change] Improved database model loading times by avoiding the rendering of tables while the children objects (indexes, trigger, rules, etc) are being added. +* [Change] Removed the several operators ~ overloading that statically cast enums to their underlying type and created a template function called enum_cast in C++14 syntax. +* [Change] The zoom in/out level is now sensible on how much the user rolls the mouse wheel. +* [Change] Move the default implementation of configureObjectShadow and configureObjectSelection from BaseObjectView to BaseTableView. +* [Change] Disabling configureObjectSelection and configureObjectShadow on TableObjectView and RelationshipView. +* [Change] Minor adjustment on protected icon position on TableTitleView and TextboxView. +* [Change] Minor performance adjustments in ModelWidget. +* [Change] Minor improvement in TextboxView to use only a TextPolygonItem to hold text and the object's rectangle instead of a box and a text items. +* [Change] Replaced the sql_info_txt and sql_info_box items by a single instance of TextPolygonItem to denote SQL disabled status. +* [Change] Replace the tag_body and tag_name elements on BaseTableView by the tag_item which is a instance of TextPolygonItem. +* [Change] Improved the TableObjectView to avoid adding extra scene items. +* [Change] Improved the TableTitleView to avoid adding children items. A custom paint() method now draws them. +* [Change] Removing unused fr_FR UI translations. +* [Change] Minor update on known issues sections at README.md. +* [Change] Renamed the namespace ParsersAttributes to Attributes and its attributes has been refactored. +* [Change] Refactored all static const attributes of the classes present in pgsqltypes.h. +* [Change] Renamed PgModelerNS to PgModelerNs. +* [Change] Renamed PgModelerUiNs to PgModelerUiNs. +* [Change] Renamed XMLParser to XmlParser. +* [Change] Removing uneeded temporary QString instance created from Exception::getErroMessage call before throwing exceptions. +* [Change] Refactored static const attributes of BaseObject. +* [Change] Refactored the items in the enum ObjectType by removing the prefix 'OBJ'. +* [Change] The enums ErrorType and ObjectType were transformed into scoped enums. Also the ErrorType enum was renamed to ErrorCode. +* [Change] Code refactoring done in order to make it more close to C++14 in order to take advantage of new features introduced by that standard. +* [Change] Removed unused labels and fixed warning frame on ModelWidget. +* [Change] Minor improvements on table's attributes displaying on DatabaseExplorerWidget. +* [Change] Improved the diff process in such way to avoid generating unnecessary/noise commands related to changing types of columns to integer and setting nextval() call as default value. +* [Change] Partition tables are now displayed in the "Tables" tab at TableWidget. +* [Change] Removed the cached catalog query test feature from Catalog. +* [Change] Fine tuning on the validation of the entities used in the partitioning relationship creation. +* [Change] Forcing the partitioning relationship to be invalidated when the reference table (partitioned) partitioning type is set to null (no partitioning). +* [Change] Move the FK settings, copy options and name patterns group boxes to a dedicated tab on RelationshipWidget. +* [Change] Improved the models destruction when closing the application. +* [Change] Improved the Index/Exclude/ParitionKey elements handling by creating a generic form/grid that handles these kinds of objects (ElementsTableWidget). +* [Change] Modified the RelationshipWidget in order to handle partitioning relationships. +* [Change] Modified RelationshipConfigWidget in order to write name partterns for partitioning relationships. +* [Change] Improved the column copying and validation on class Relationship to include partitioning relationship logics. +* [Change] Improved the reverse engineering performance by avoiding update relationships as they are being imported. +* [Change] Improved the object duplication feature in ModelWidget. +* [Change] When the model is loaded it is copied to the temporary models storage as a first version of the temporary dbm file. +* [Change] Simplified the temporary models saving process by removing the thread that was controlling it. Actually the thread was unnacessary because the process was being executed in the main thread no matter if there was another thread to control the saving. +* [Change] Minor adjustment on the hint text resizing. +* [Change] Increasing to 5 minutes the period in which the temporary model saving will be executed. +* [Change] pgModeler will now use the official docs url in the help buttons. +* [Fix] Fixed a minor bug that was preventing the copy action to be enabled in DataManipulationForm. +* [Fix] Fixed some sample models to remove deprecated attributes. +* [Fix] Fixed a crash while renaming view's children objects. +* [Fix] Fixed the rendering of views which contain only a single reference that is the whole object's defintion. +* [Fix] Fixed the column name deduction for recursive views. +* [Fix] Fixed a bug that was causing crashes while configure new constraints on tables. +* [Fix] Fixed the view's resizing. +* [Fix] Fixed a regression in schema's rectangle selection. +* [Fix] Fixed the StyledTextboxView bounding rectangle. +* [Fix] Fixed an artifact when user switched on and off the compact view. +* [Fix] Fixed the Linux deploy script. +* [Fix] Fixed the macOs deploy script. +* [Fix] Fixed some compilation problems on macOs due to the usage of C++14. +* [Fix] Fixed some compilation problems on Windows due to the usage of C++14. +* [Fix] Fixed a bug in DatabaseModel::destroyObjects that could lead to segfault when the destroyed model had permissions on it. +* [Fix] Fixed a bug when importing columns which data types is some user defined type in form of array, e.g., custom_type[]. +* [Fix] Fixed a bug in SchemaParser that was causing only the first %set line in a if block to be parsed no matter that there were others %set below the same block. +* [Fix] Fixed the tooltip of some graphical objects by adding their comments and aliases. +* [Fix] Fixed the catalog query for tables to select partitioned tables correctly. +* [Fix] Fixed the catalog query for types to avoid selecting partitioned tables as being data types. +* [Fix] Fixed a bug that was causing special primary key configured on a relationship to make the original primary key of the table to disappear after disconnect the relationship. Now pgModeler stores in memory the original PK prior the connection of relationship and creation of the special PK. When disconnected the relationship, the original primary key is restored on its parent table. +* [Fix] Fixed the creation of elements (index, exclude, patition key) on DatabaseModel. +* [Fix] Fixed the class Relationship to reuse compatible columns when handling partitioning relationships. +* [Fix] Fixed the diff process in such way to create new columns with their respective COMMENT ON statement when present. +* [Fix] Fixed the detection of comment changes for columns on diff process. +* [Fix] Fixed the order of recent models saved on the file pgmodeler.conf. +* [Fix] Fixed a bug when creating a view reference as the whole view definition. +* [Fix] Minor tooltip fix on DatabaseExplorerWidget. +* [Fix] Making pgModeler honor the columns arrangement in primary keys. +* [Fix] Fixed a bug that was causing FK relationship deletion to crash the application sometimes. +* [Fix] Some fixes were done in the ModelOverviewWidget in order to support large models without exceed the screen size when configuring the size of the overall widget. +* [Fix] Fixes a bad erase in View::removeReference. +* [Fix] Fixed some bugs related to dialog size restoration in DataManipulationForm and TableWidget. + +v0.9.2-alpha +------ +Release date: August 20, 2018
+ +* [New] Added the support for cancelling SQL execution in SQLExecutionWidget. +* [New] Added support for save/restore the dialogs sizes and positions. +* [New] Added support for truncate tables in DataManipulationForm. +* [New] Added support for aliases on some graphical objects that is used in the compact view mode. +* [New] Added support for save/load object's metadata containing aliases information. +* [New] Added support for compact view of the model where graphical objects can have a more friendly name for a reduced view as well for those who don't need to see details about tables (clients of the business, for instance). +* [New] Added support for sequence options for identity columns. +* [New] Added the ability to paste CSV text from clipboard into the TableDataWidget. +* [New] Added support for bulk data edit in TableDataWidget. +* [Change] Added missing copy options on copy relationships. +* [Change] Minor adjustments on the item delegates in order draw text in the right alignment. +* [Change] Minor adjustment on buttons style in DatabaseExplorerWidget, DataManipulationForm and SQLExecutionWidget. +* [Change] Minor adjustment on OperationList::removeFromPool to avoid throw an exception when an invalid index is passed. +* [Change] Changed the behaviour of the fade in/out of relationships linked to a table by applying the effect on the other tables that are related to the selected one. +* [Change] Refactored the view editing dialog by moving the references handling form to a dedicated modal dialog. +* [Change] Improved the model loading from file by blocking signals of relationships avoiding excessive/repetive rendering of objects. The whole model is fully rendered when the file was completely loaded. +* [Change] Minor adjustment on constraints rendering at extended attributes section of tables. +* [Change] French translation update. +* [Change] Updated the other lang dictionaries with the new text brought by new releases. +* [Change] Removing icons at the top of the dialogs: DatabaseImportForm, MetaDataHandlingForm, ModelDatabaseDiffForm, ModelExportForm, ModelFixForm. +* [Change] Minor adjustments in the features of the demo version. +* [Change] Minor adjustments in the UI stylesheet. +* [Change] In DatabaseExplorerWidget the root item will come automatically selcted when browsing a database. +* [Change] Minor performance tuning when handling big models. +* [Change] Added some statistics attributes for tables on DatabaseExplorerWidget. +* [Change] Minor adjustment in NewObjectOverlayWidget by putting the tool buttons under categories. +* [Fix] Fixed a bug in ObjectFinderWidget that was forcing schemas rectangles to appear even if the flag indicating them to be visible was set to false. +* [Fix] Fixed the editing form cancel operation. Now operations done when the form was active are undone correctly. +* [Fix] Fixed a bug that was preventing to create a view containing the same name as a table but in different schema. +* [Fix] Fixed a regression that caused notices not to be shown in the output panel at SQLExecutionWidget. +* [Fix] Fixed the query catalog for policies which was causing syntax error when combining import system objects and extension objects options. +* [Fix] Fixed the disabling of some actions related to design when switching to manage view. +* [Fix] Minor fix on stylesheet in order to display the extended button on general toolbar. +* [Fix] Fix a shortcut conflict in DataManipulationform. +* [Fix] Fixed the offset of strings composing the StorageType. +* [Fix] Minor form size adjustments. +* [Fix] Minor fix in sqlexecutionwidget.ui to force the exhibition of grid headers +* [Fix] Minor fix in SQLExecutionWidget allowing the output widget to be resized to a size lower than the default one. +* [Fix] Fixed the tab order in PolicyWidget. +* [Fix] Fixed the generation of Database object source in DatabaseExplorerWidget. +* [Fix] Fixed the method BaseObjectWidget::setRequiredField to make object selector fields as required correctly. +* [Fix] Minor fix in HintTextWidget to stay on top of all widget when being displayed. +* [Fix] Fixed a bug that was not quoting extension name when needed. +* [Fix] Fixed a crash when trying to remove a fk relationship when it was created from a foreign key which references protected columns (added by relationship). +* [Fix] Fix a crash when importing CSV files into DataManipulationForm. +* [Fix] Minor typo in TableDataWidget. +* [Fix] Minor fix on schema file sql/table.sch. + +v0.9.1 +------ +Release date: May 14, 2018
+ +* [New] Added support for line selection by clicking and moving the mouse over the line numbers widget in any source code field. +* [New] The validator now checks if the model has columns referencing spatial data types and creates the postgis extension automatically when fixing the model. +* [New] Added support for RESTART IDENTITY on truncate tables in DatabaseExplorerWidget. +* [New] Added an custom option checkbox in Messagebox for general purpose usage. +* [New] Added support for diff operation in CLI. +* [New] Added support for import database from CLI. +* [New] Adding missing types regrole and regnamespace. +* [Change] Improved the copy/duplicate operation in order to copy rules, index, trigger and policies together to their parents. +* [Change] Added column names to the code completion widget used in the filter widget at DataManipulationForm. +* [Change] Improved the SQLExecutionWidget in such way that it'll display large amount of data more quickly and consuming less memory. +* [Change] Minor improvement in SQLExecutionWidget to show the amount of time took to run a query. +* [Change] Minor improvement in the text find widgets in SQL tool in order to make them closable via dedicated button. +* [Change] Improved the set tag operation in ModelWidget in order to cleanup the assigned tags to a set of objects. +* [Change] Minor improvement on DatabaseExplorerWidget to show the rls attributes labels correctly in the attributes grid. +* [Change] Refactored all the CLI options. +* [Change] Minor change in Connection::generateConnectionString in order to put the dbname param in the start of the string. +* [Change] Improved the performance of the row duplication action in DataManipulationForm. +* [Change] Minor improvement in order to update the schemas boxes when the tables have their extended attributes box toggled. +* [Change] Improved the performance of "Move to schema" operation. +* [Change] Added an busy cursor while closing a model. +* [Change] Improved the object selection in object finder. +* [Change] Changed the behaviour of select and fade buttons in ObjectFinderWidget in such way to enable the user to select/fade the objects in the listing (or not included in the results). +* [Fix] Fixed a bug when import identity columns in certain cases when the identity column was followed by another column which data type was not accepted for identity, e.g, text after smallint. +* [Fix] Fixed the check boxes disabling when dealing with identifier relationships. +* [Fix] Disabled the drag & drop for items in the side listing at ConfigurationForm. +* [Fix] Fixed the tab behavior on comment box in all editing forms of database objects. +* [Fix] Fixed the catalog query for user defined types. +* [Fix] Fixed the import of user defined types which names contains uppercase characters. +* [Fix] Minor typo fixes in CLI. +* [Fix] Fix window scaling on HiDPI/Retina screens. +* [Fix] Minor fix in Connection::getConnectionId in order to omit port when that parameter is not configured in the connection. +* [Fix] Fixed a bug in ModelExportHelper that was failing to remane the database when the command appeared. +* [Fix] Fixed a bug in CollationWidget that was referencing the collation attributes LC_??? using the wrong constant. +* [Fix] Fixed the behaviour of the message box that warns about the need of validate the model prior to export, save or diff. Now rejecting the dialog (i.e. closing it) will be considered that the user wants to proceed with the pending operation even with an invalid model. +* [Fix] Fixed the import of comments for constraints,triggers, index and rules. +* [Fix] The value input in BulkDataEditWidget will be focused as soon as the widget appears. +* [Fix] Fixed a bug in the aggregate import process. +* [Fix] Minor fix in DataManipulationForm to avoid the generation of a where clause when the filter is filled only with spaces. +* [Fix] Minor fix in the magnfier tool to use the same render hints as the canvas viewport. +* [Fix] Fixed a bug in the diff process that was trying to recreate the whole database when the "Force recreation" option was set. +* [Fix] Fixed a bug when showing the source of tables in DatabaseExplorerWidget when these objects have permissions assigned. +* [Fix] Adjusting tables position when the parent schema is moved and the alignment to grid is enabled. +* [Fix] Minor fix in the CLI menu. +* [Fix] Fixed the saving process for large models by stopping the threads related to temp models saving while the model file is being written. + v0.9.1-beta1 ------ Release date: April 6, 2018
@@ -8,21 +976,21 @@ v0.9.1-beta1 * [New] Added the ability to create multiples one-to-many and many-to-many relatationships between the same pair of tables. * [New] Added the ability to use more special ascii chars in the middle of object names. * [New] Added missing SQL keywords into sql-highlight.conf -* [New] Added support to multi line comments in UI. +* [New] Added support for multi line comments in UI. * [New] Added code snippets for CREATE and ALTER policy. -* [New] Added full support to row level security (RLS), including export, import and diff of this kind of object. +* [New] Added full support for row level security (RLS), including export, import and diff of this kind of object. * [New] Added the method DatabaseExplorerWidget::formatPolicyAttribs in order to display some attributes values correctly. -* [New] Added support to bulk data editing in DataManipulationForm. +* [New] Added support for bulk data editing in DataManipulationForm. * [New] Added an option to diff process to force the generation of DROP commands for columns and constraints even if the missing objects need to be preserved. This is useful to work with partial models and the user need to remove columns/constraints and preserve the rest of objects. * [New] Added the ability to generate diff code to Enable/Force RLS attribute of tables. -* [New] Added support to RLS on tables. -* [New] Added the support to detect identity columns in diff. -* [New] Added support to identity columns (PostgreSQL 10). -* [New] Added the support to BYPASSRLS option on roles. -* [New] Added support to IS_TEMPLATE and ALLOW_CONNECTIONS options in database object. +* [New] Added support for RLS on tables. +* [New] Added the support for detect identity columns in diff. +* [New] Added support for identity columns (PostgreSQL 10). +* [New] Added the support for BYPASSRLS option on roles. +* [New] Added support for IS_TEMPLATE and ALLOW_CONNECTIONS options in database object. * [New] Added the procedures to fix old style domains in CLI. -* [New] Added support to multiple check constraint in domains. -* [New] Added support to sort items alphabetically (ascending) or by oid in DatabaseExplorerWidget. +* [New] Added support for multiple check constraint in domains. +* [New] Added support for sort items alphabetically (ascending) or by oid in DatabaseExplorerWidget. * [Change] Changed the input mode of the password field in ConnectionsConfigWidget in order to hide the passwords in the form. NOTE: the passwords are still in plain text in the config file. * [Change] Moved extensions from schema level to database level in order to reproduce better the PostgreSQL's behavior. * [Change] The filter widget is now toggled in DatabaseExplorerWidget via filter menu. @@ -57,7 +1025,7 @@ v0.9.1-beta ------ Release date: January 26, 2018
-* [New] Added support to GROUP BY/HAVING clauses in Views by adding a new kind of reference. Proper changes done in ViewWidget to allow configuring those clauses. +* [New] Added support for GROUP BY/HAVING clauses in Views by adding a new kind of reference. Proper changes done in ViewWidget to allow configuring those clauses. * [New] Added the method Catalog::isSystemObject(oid) which indicates if the provided OID is related to a system object. * [Change] Minor adjustment in the copy/paste operation to generate suffix in the pasted objects only when there're conflics. * [Change] Removed the port range limitation in connection configuration dialog. @@ -80,7 +1048,7 @@ v0.9.1-alpha1 * [New] Improved the data manipulation dialog in such way that when dealing with deletes in tables without PK, tuples with NULL values can be correctly considered. * [New] Improved the validations on ResultSet class. * [New] Added a method to indicate if a column value is null in ResultSet. -* [New] Added support to fade in/out objects in object finder in order to highlight the graphical objects retrieved from the search. +* [New] Added support for fade in/out objects in object finder in order to highlight the graphical objects retrieved from the search. * [New] Added an attribute in pgmodeler.conf to store the current status of the "Fade in" button in object finder widget. * [Change] Minor improvement in the diff generated metadata. * [Change] Increased the maximum allowed amount of lines in command history. @@ -93,14 +1061,14 @@ v0.9.1-alpha ------ Release date: October 20, 2017
-* [New] Added support to crow's foot notation. +* [New] Added support for crow's foot notation. * [New] Added the crow's foot notation switch in RelationshipConfigWidget. * [New] Added the grid arrangement in the arrangment menu at MainWindow. * [New] Added the schema arrangement (scattered). * [New] Added an action to toggle schemas rectangle on ModelWidget. * [New] CLI now loads the relationship and general settings to reflect relationship styles in export modes. -* [New] Added support to connect relatinship on tables' edges when using classical notation. -* [New] Added support to apostrophes in the middle of object's name. +* [New] Added support for connect relatinship on tables' edges when using classical notation. +* [New] Added support for apostrophes in the middle of object's name. * [Change] Removed the controls related to arragement in DatabaseImportForm. * [Change] Minor adjustments in tables' spacing in auto arrangement process. * [Change] Minor improvement on SQLExecutionWidget and DataManipulationForm in order to make possible to paste csv buffer from SQLExecutionWidget to DataManipulationForm. @@ -139,8 +1107,8 @@ v0.9.0 * [New] Created the method CsvLoadWidget::loadCsvFromBuffer to make the code that extract csv document from string buffer reusable by other classes. * [New] Added a new sample model donated by the maintainers of 3D City DB project. * [New] Added the language "internal" to the set of system languages available when creating a new model. -* [New] Added support to override the default language settings via GeneralConfigWidget. -* [New] Added support to toggle curved relationship lines in GeneralConfigWidget. +* [New] Added support for override the default language settings via GeneralConfigWidget. +* [New] Added support for toggle curved relationship lines in GeneralConfigWidget. * [Change] Improved the MetadataHandlingForm enabling user to only extract metada to a backup file. * [Change] Small update on sample models. * [Change] Minor adjustments in the graphical points when relationships are selected. @@ -175,11 +1143,11 @@ v0.9.0-beta2 * [New] Added a widget that shows some info about the canvas and the selected objects at the bottom of main window in design view. * [New] Enabled the usage of snippets in other portions of the software like GenericSQLWidget, FunctionWidget, ViewWidget, CustomSQLWidget. * [New] Added the ability to quickly jump to the tables related to a relationship. -* [New] Added support to select all objects in the canvas by type (table, view, textbox, schema, relationship). -* [New] Added support to bulk relationship points removal. +* [New] Added support for select all objects in the canvas by type (table, view, textbox, schema, relationship). +* [New] Added support for bulk relationship points removal. * [New] Added a magnifier tool so the user can visualize objects when the zoom is too small. This tool allows the user to click to select or activate the context menu over the objects. -* [New] Added support to generic sql objects that serve as an improved way to use custom SQL. -* [New] Added support to handle metadata related to generic sql objects. +* [New] Added support for generic sql objects that serve as an improved way to use custom SQL. +* [New] Added support for handle metadata related to generic sql objects. * [New] Added the first object auto-arrange algorithm. * [Change] pgModeler will now accept (connect) to a PostgreSQL server even if the version of the server is not supported falling back to the most recent supported. * [Change] Minor improvements on DatabaseImportForm, ModelExportForm, ModelDatabaseDiffForm and MetadataHandlingForm to toggle uniformRowsHeight of the output tree at the start and the end of each process to avoid slowdowns and allow the items to be resized correctly when expanded. @@ -207,7 +1175,7 @@ v0.9.0-beta1 * [New] Added the ability to standalone dialogs like import, diff, export and others to be resized according to the screen dpi and resolution. * [New] Added an experimental routine that will resize windows according to the current screen resolution and font dpi. -* [New] Added support to browse referrer and referenced in DataManipulationForm. +* [New] Added support for browse referrer and referenced in DataManipulationForm. * [New] Added an item under table items that stores the referrer tables in the DatabaseExplorerWidget. * [New] Added the method BaseObjectView::getScreenDpiFactor to help resize scene objects according to the screen dpi/resolution. * [Change] Minor adjustment on readonly items regarding to referenced and referrer tables in DatabaseExplorerWidget. @@ -228,8 +1196,8 @@ v0.9.0-beta ------ Release date: April 4, 2017
-* [New] Added support to indexes in Views. -* [New] Added the support to edit/load the source code in NumberedTextEditor in external application. +* [New] Added support for indexes in Views. +* [New] Added the support for edit/load the source code in NumberedTextEditor in external application. * [New] Added the ability to save/load metadata related to fade out status and extended attributes display status. * [New] Added the ability toggle the extended attributes area in tables and views. The toggle status is persisted in the model file and restores during loading * [New] Added constraints to the extended attributes section in the tables at canvas area in order to improve the quick access to these objects. @@ -237,7 +1205,7 @@ v0.9.0-beta * [New] Fade status is now persisted in the dbm file and restored during loading. * [New] Added the ability to control zoom factor from overview widget. * [New] Added a shortcut for "Duplicate" action in design view. -* [New] Added support to (back)slash char in object's names. +* [New] Added support for (back)slash char in object's names. * [New] Enabled the usage of NewObjectOverlayWidget for views. * [Change] Changed the default characters used to escape values in DataManipulationForm and TableDataWidget from {} to // due to problems with json data. * [Change] Improved the file manipulation in SQLExecutionWidget. Added option to save the commands to the current file or in another file (save as). @@ -247,7 +1215,7 @@ v0.9.0-beta * [Change] Improved the diff between the complete database and a partial model representing it. * [Fix] Minor fix in AppearanceConfigWidget in order to set the font color correctly. * [Fix] Minor fix in the default file objects-style.conf -* [Fix] Added the missing support to drop event triggers from database model. +* [Fix] Added the missing support for drop event triggers from database model. * [Fix] Fixed the drop cast command generation. * [Fix] Minor fix in windows deploy script to use newer PostgreSQL. * [Fix] Minor fix in template connections.conf file. @@ -264,21 +1232,21 @@ v0.9.0-alpha1 ------ Release date: February 07, 2017
-* [New] Added support to object moving via arrow keys in canvas area. -* [New] Added support to easily create primary keys just by checking the desired columns in table's editing form. -* [New] Added support to use middle button to handle panning mode. +* [New] Added support for object moving via arrow keys in canvas area. +* [New] Added support for easily create primary keys just by checking the desired columns in table's editing form. +* [New] Added support for use middle button to handle panning mode. * [New] Added a more user friendly message at startup whenever a missing or corrupted configuration file is detected. The user is now presented to an option to restore default settings for the problematic file. * [New] Now any default file restored in ConfigurationForm has a backup saved into the directory 'backups' inside the configuration storage. -* [New] Added support to hide the database explorer widget in SQL tool via splitter handler. +* [New] Added support for hide the database explorer widget in SQL tool via splitter handler. * [New] Added a method to disable the custom context menu of the class NumberedTextEditor. -* [New] Added support to object fading in ModelWidget. -* [New] Added the support to persist the object opacity factor in config file. +* [New] Added support for object fading in ModelWidget. +* [New] Added the support for persist the object opacity factor in config file. * [New] Added the method PgModelerUiNS::getIconPath() in order to retrieve icons from resource. -* [New] Added support to column, constraint, trigger, rule and index duplication in TableWidget. -* [New] Added support to item duplication in ObjectTableWidget. +* [New] Added support for column, constraint, trigger, rule and index duplication in TableWidget. +* [New] Added support for item duplication in ObjectTableWidget. * [New] Added a loading cursor when the user opens the DataManipulationForm. * [New] The database explorer now creates the root item in the tree as the server itself which contains data related to this latter. -* [New] Added the support to parenthesis in the middle of objects' names. +* [New] Added the support for parenthesis in the middle of objects' names. * [Change] Improvements done in the SQL history at SQL execution widget. Now the command history is saved into a specific file and restored when the application starts. * [Change] Minor improvement in DataManipulationForm to show a wait cursor while filtering results. * [Change] Minor improvements in GeneralConfigWidget. Added an readonly input that exposes the path to the current user's configuration storage. @@ -344,7 +1312,7 @@ v0.8.2 * [New] Created the PlainTextItemDelegate replacing the ReadOnlyItemDelegate where needed. * [New] Added the ability to the table to create insert commands from the initial data buffer. -* [New] Added the support to interpret initial-data tag in DatabaseModel::createTable. +* [New] Added the support for interpret initial-data tag in DatabaseModel::createTable. * [New] Create the attribute initial-data for Table in order to store the initial set of values in a CSV-like buffer. * [New] Created the form to handle table's initial data. * [New] Added the ability to duplicate rows in DataManipulationForm. @@ -352,12 +1320,12 @@ v0.8.2 * [New] Added the ability to clear and copy text from history to the sql command input field using middle mouse button in SQL tool. * [New] Added the ability to set the default connection for operations import, export, diff and validation in ConnectionsConfigWidget. * [New] Added the usage of default connections in ModelValidationWidget. -* [New] Added support to save/load default connections in the ConnectionsConfigWidget. +* [New] Added support for save/load default connections in the ConnectionsConfigWidget. * [New] Added attributes to the Connection class in order to control wheter the connection is the default for export, import, diff or validation operations. * [New] Added the ability to save the current grid options to the pgmodeler.conf file. * [New] Added a reference the svg library to the deployment scripts. -* [New] Added support to export model to SVG file in UI and CLI. -* [New] Added the support to change case and identation of the selected text in NumberedTextEditor using context menu or shortcuts. +* [New] Added support for export model to SVG file in UI and CLI. +* [New] Added the support for change case and identation of the selected text in NumberedTextEditor using context menu or shortcuts. * [New] Added a method PgModelerUiNS::createOutputListItem which created list items with an icon and text. * [New] Connections now can have a timeout between command executions. When this timeout exceeds the next command is not executed. This is a workaround to avoid the crash of the program due to connections being (unexpectedly or not) closed by the server. * [New] Added the ability to show connections notice/warning in SQL tool. @@ -419,7 +1387,7 @@ v0.8.2-beta1 * [New] Created a signal BaseObjectWidget::s_closeRequested to tell the parent form close after successfuly edit an object. * [New] Created template methods in RelationshipWidget and ViewWidget to handle child object manipulation. * [New] Created a template method TableWidget::openEditingForm to handle the editing form for children objects. -* [New] Added support to placeholder objects when moving graphical objects improving performance mainly when moving tables and relationships avoiding excessive update operations. +* [New] Added support for placeholder objects when moving graphical objects improving performance mainly when moving tables and relationships avoiding excessive update operations. * [New] Added an option to protect schema's children when protecting the schema itself. * [New] Added the abitily to diff partial models without drop the not imported ones from the original database. * [Change] CentralWidget renamed to WelcomeWidget. @@ -527,8 +1495,8 @@ v0.8.2-beta Release date: January 12, 2016
* [New] Added version descriptor for PostgreSQL 9.5 enabling pgModeler to connect to it. -* [New] Added access method BRIN for indexes, operator classes and operator families as an initial support to PostgreSQL 9.5. -* [New] Added event "table_rewrite" for event triggers as an initial support to PostgreSQL 9.5. +* [New] Added access method BRIN for indexes, operator classes and operator families as an initial support for PostgreSQL 9.5. +* [New] Added event "table_rewrite" for event triggers as an initial support for PostgreSQL 9.5. * [New] Added "Diff" action to File menu. * [Change] Minor improvement in DataManipulationForm adding the shortcut of "Copy selection" button to its tooltip. * [Change] Improvements on DataManipulationForm on how pk columns are handled and used in the generated DML commands for UPDATE and DELETE. @@ -845,7 +1813,7 @@ v0.8.0 Codename: Faithful Elephant
Release date: February 28, 2015
-* [New] Added support to multiple SQL execution widget instances for the same browsed database in SQL tool. +* [New] Added support for multiple SQL execution widget instances for the same browsed database in SQL tool. * [New] Added truncate table actions on DatabaseExplorerWidget. * [Change] Minor adjustments on ModelValidationHelper. * [Change] Minor adjustments on CustomSQLWidget. @@ -886,7 +1854,7 @@ v0.8.0-beta2 * [New] Created missing getters and setters for Operation class. * [New] Added the ability to set owner, schema and tag for several objects at once through the quick actions menu. * [New] Added an option to diff process to reuse sequences if the source model has serial columns in which the generated sequence name matches a sequence's name on the imported model. -* [New] Added the support to per-user configuration. Now each user on the system will have his separated configuration folder. +* [New] Added the support for per-user configuration. Now each user on the system will have his separated configuration folder. * [New] Added a bug report form on main window to give user the chance to report a bug without use crash handler. * [New] Added action to enable/disable an object's sql from quick actions menu at ModelWidget. * [New] Created a new namespace PgModelerUiNS to store shared constants and function in libpgmodeler_ui subproject. @@ -1161,7 +2129,7 @@ v0.8.0-alpha1 * [New] Added a field on all object's editing form to expose the object's internal id. * [New] Added an option on the database import process to generate random colors for relationships. * [New] The model objects widget gained a filtering field that is capable to list objects by their name or internal id. -* [New] Added support to custom SQL for rules, indexes and triggers. +* [New] Added support for custom SQL for rules, indexes and triggers. * [New] Added two new sample models. * [Change] Changed the shortcut for "About pgModeler" to F4 key. * [Change] Minor update on shortcuts and tooltips of buttons on bottom control bar at main window. @@ -1208,7 +2176,7 @@ v0.8.0-alpha Codename: Faithful Elephant
Release date: July 21, 2014
-* [New] Added support to using global settings for relationships on the editing form of those objects. +* [New] Added support for using global settings for relationships on the editing form of those objects. * [New] A new section was created on settings dialog to manage global configurations for relationships. * [New] Enabled the movement of schema objects without the need to select their children. This operation does not applies to protected or system schemas like public, pg_catalog. * [New] Created a more elaborated central widget with some basic operations like create, load, load recent models and restore previous session. @@ -1296,11 +2264,11 @@ v0.7.2-alpha1 * [New] Introduced a "new object" overlay widget which gives user a quick access to actions that create objects. * [New] Added a step to fix indexes with old tag on command line interface. -* [New] Added support to item interaction on "object's dependencies and references" dialog. -* [New] Added support to generate temporary names for database, roles and tablespaces when running validation process. This will avoid errors if the original database and the other objects already exists on the server. +* [New] Added support for item interaction on "object's dependencies and references" dialog. +* [New] Added support for generate temporary names for database, roles and tablespaces when running validation process. This will avoid errors if the original database and the other objects already exists on the server. * [New] Updated the CLI to include the option to generate temporary object's names. * [New] Added suppport to save and restore the last position and zoom on the canvas. This behavior can be deactivated on general settings. -* [New] Added support to prepend SQL commands on object's definition. +* [New] Added support for prepend SQL commands on object's definition. * [New] Added zoom info popup that appears whenever the user changes the current zoom factor. * [Change] Renamed the methods setCheckExpression and getCheckExpression methods to setExpression and getExpression because the expression is used either for check and exclude constraints. * [Change] Renamed the attribute "condition" to "predicate" on index class. @@ -1343,7 +2311,7 @@ v0.7.1 Release date: April 15, 2014
* [New] Added option to invert panning mode and range selection triggers. -* [New] Added support to use relationship attributes as special primary keys. +* [New] Added support for use relationship attributes as special primary keys. * [Change] Improvement on unique name generation for columns and constraints when connecting relatioships. * [Change] Improvement on copy / paste operations. * [Change] Minor workaround in order to try to fix the crash due to thread conflict mainly on Windows system. @@ -1368,7 +2336,7 @@ v0.7.1-beta Release date: April 6, 2014
* [New] Created a small interface to pgmodeler-cli that enables the user to fix a broken model inside pgModeler GUI. -* [New] Added support to assign a sequence as default value of a column. The sequence will be converted to "nextval('seqname'::regclass) and the validation process will check if the sequence is correctly referenced by the table that owns the column. +* [New] Added support for assign a sequence as default value of a column. The sequence will be converted to "nextval('seqname'::regclass) and the validation process will check if the sequence is correctly referenced by the table that owns the column. * [Change] Changed the default behavior of left click on blank areas of canvas. Instead of create a range selection the user will move the viewport (panning mode). To enable range selection user must press SHIFT and click/move to draw the selection rectangle. * [Fix] Minor fix on connection class in order to accept empty passwords as well passwords that contains spaces. * [Fix] Fixed the column listing on constraint editing form after remove one or more columns. @@ -1407,10 +2375,10 @@ v0.7.0 * [New] Addded a catalog attribute "hide-postgres-db" in order to avoid listing "postgres" maintainance DB on import operations. * [New] Added options to hide system/extension objects on SQL tool improving the object listing performance. -* [New] Added support to custom compilation output directory through qmake variables BINDIR, LIBDIR and RESDIR. -* [New] Added support to deferrable unique, exclude and primary key constraints. -* [New] Added support to custom colors on tables and views through tag objects. -* [New] Added support to export models to png image page by page. +* [New] Added support for custom compilation output directory through qmake variables BINDIR, LIBDIR and RESDIR. +* [New] Added support for deferrable unique, exclude and primary key constraints. +* [New] Added support for custom colors on tables and views through tag objects. +* [New] Added support for export models to png image page by page. * [New] Canvas can now be moved using Control + Arrow keys. If the shift is pressed the movement factor is increased. * [New] Introduced the SQL tool that permits the execution of arbitrary SQL commands direclty on a server. * [New] Added methods getType, getTypeId to BaseType and getSQLTypeName to PgSQLType as an alternative to call operators ~, ! and *. @@ -1420,11 +2388,11 @@ v0.7.0 * [New] Added a build number on about dialog. This number is the compilation date in format yyyymmdd. * [New] Added support for materialized and recursive views (PostgreSQL 9.3 feature). * [New] Added pgModeler version information on generated sql scripts as well .dbm files for debugging purpose. -* [New] Added support to custom delete/update actions for relationship generated foreign keys. -* [New] Added support to move the canvas by positioning the mouse over corners. +* [New] Added support for custom delete/update actions for relationship generated foreign keys. +* [New] Added support for move the canvas by positioning the mouse over corners. * [New] Added a configuration parameter to control font style for any source code highlight field. * [New] Added additional PostGiS types: geomval, addbandarg, rastbandarg, raster, reclassarg, unionarg, TopoGeometry, getfaceedges_returntype, validatetopology_returntype. -* [Change] Added support to on-demand updates on sql tool object's tree. +* [Change] Added support for on-demand updates on sql tool object's tree. * [Change] Improved the tab navigation experience on editing forms. * [Change] Minor change on SQL tool to ommit binary data values. * [Change] Dropped the navigation through object using Alt + due to the difficulty to understand the order in which objects are highlighted. @@ -1674,7 +2642,7 @@ v0.5.2 * [New] Introduced an experimental code completion on fields that permits code input. * [New] User can create default sequences from serial columns. This feature does not apply to columns generated by relationships. * [New] Introduced a feature to break relationship lines in straight angles and to remove all user added points. -* [New] Added support to change font size on textboxes. +* [New] Added support for change font size on textboxes. * [Change] Removed the code "OIDs=FALSE" from table's SQL. * [Fix] Minor fix on Mac OSX deployment script. @@ -1709,7 +2677,7 @@ v0.5.1 * [New] pgModeler is now capable of associate dbm files to its executable being possible opening a model from file manager by clicking it (except for MacOSX, see MacOSX notes). * [New] Added support for loading models by calling pgModeler gui executable from terminal (e.g. pgmodeler model1.dbm model2.dbm) * [New] pgModeler logo redesign. -* [New] Added special primary keys support to one-to-one and one-to-many relationships. +* [New] Added special primary keys support for one-to-one and one-to-many relationships. * [New] Relationships now supports patterns to define generated objects names. The manual suffix and auto-suffix generation are deprecated. * [New] Columns/constraints generated by relationship can have position changed on parent table. * [New] Added smallserial built-in datatype. @@ -1738,16 +2706,16 @@ v0.5.0 * [New] Added an option to list available configured connections on pgmodeler-cli. * [New] pgModeler now alerts the user when he try to save an invalidated model. * [New] pgModeler now aborts app closing when the user wants to do a last saving on modified models. -* [New] Added support to hide relationship labels and table extended attributes on configuration dialog. +* [New] Added support for hide relationship labels and table extended attributes on configuration dialog. * [New] Added "Recent Models" menu. * [New] Introduced the Xml2Object plugin to help on develpment testings. -* [New] Added partial support to PostgreSQL Extensions objects. +* [New] Added partial support for PostgreSQL Extensions objects. * [New] Added JSON datatype. * [New] Added support for rules and trigger on views. * [New] Added support for user defined range types. * [New] Added support for collations on composite types (user defined). * [New] Added built-in range types. -* [New] Added support to INCLUDING/EXCLUDING options when dealing with copy relationships. +* [New] Added support for INCLUDING/EXCLUDING options when dealing with copy relationships. * [New] Added support for EXCLUDE constraint support * [New] Added NO INHERIT option to check constraints. * [New] Added REPLICATION option to roles. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..1369b8b314 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at raphael@pgmodeler.io. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/README.md b/README.md index 0eff748b78..8b22c7565e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,22 @@ +![pgmodeler_readme_img](https://user-images.githubusercontent.com/2205476/148689123-4ed65f6f-f3c1-49f2-95e4-33baea60e8a5.png) + +[![Linux build](https://github.com/pgmodeler/pgmodeler/workflows/Linux%20build/badge.svg)](https://github.com/pgmodeler/pgmodeler/actions?query=workflow%3A%22Linux+build%22) +[![Windows build](https://github.com/pgmodeler/pgmodeler/workflows/Windows%20build/badge.svg)](https://github.com/pgmodeler/pgmodeler/actions?query=workflow%3A%22Windows+build%22) +[![macOs build](https://github.com/pgmodeler/pgmodeler/workflows/macOs%20build/badge.svg)](https://github.com/pgmodeler/pgmodeler/actions?query=workflow%3A%22macOs+build%22) + Introduction ------------ -pgModeler - PostgreSQL Database Modeler - is an open source data modeling tool designed for PostgreSQL. No more DDL commands written by hand let pgModeler do the job for you! This software reunites the concepts of entity-relationship diagrams and the features that PostgreSQL implements as extensions of SQL standards. +pgModeler - PostgreSQL Database Modeler - is an open-source data modeling tool designed for PostgreSQL. No more typing DDL commands. Let pgModeler do the work for you! This software unites the concepts of entity-relationship diagrams and the features that PostgreSQL implements as extensions of SQL standards. It also counts with a minimalist but functional database server administration module which allows the execution of any sort of SQL commands, database objects browsing, and data handling in a simple and intuitive UI. For more details about additional features, screenshots, and other useful information, please, visit the [project's official website](https://pgmodeler.io). + +Please let me know how pgModeler is working on your system. Help improve this project, give your feedback about the software or report any bugs on the [Issues](https://github.com/pgmodeler/pgmodeler/issues) page. Additionally, follow pgModeler on [Twitter](https://twitter.com/pgmodeler) and be up-to-date with new features, fixes, and releases. + +Compiling/Installation +---------------------- -Please, let me know how the pgModeler is working on your system! Help to improve this project, give your feedback about the software or report any bug at [Issues](https://github.com/pgmodeler/pgmodeler/issues) page. Additionaly, follow the pgModeler profile on [Facebook](https://www.facebook.com/pgmodeler) or [Twitter](https://twitter.com/pgmodeler) and be up-to-date with new features, fixes and releases. +For details about the installation process from the source code, visit the [Installation](https://www.pgmodeler.io/support/installation) section. If you don't want to compile pgModeler yourself, there are binaries available for purchase on the [official website](http://www.pgmodeler.io/purchase). + +You may want to check the [official plugin repository](https://github.com/pgmodeler/plugins) as well. Licensing --------- @@ -17,35 +30,33 @@ See [LICENSE](https://github.com/pgmodeler/pgmodeler/blob/master/LICENSE) for de Donate to pgModeler ------------------- -Much effort, coffee, chocolate, time and knowledge has been devoted to this project so that a usable and constantly improved product could be delivered to the community. If you liked pgModeler and think it deserves a contribution please donate any amount (via PayPal) at [project's official site](http://pgmodeler.com.br). +Much time, effort, coffee, chocolate, and knowledge is being devoted to this project so that a reliable and constantly improved product can be delivered to the community. If you like pgModeler and think it deserves a contribution, please donate any amount on the [project's official website](https://pgmodeler.io). Developers and Reviewers wanted! -------------------------------- -pgModeler grown bigger and reached a state that its lonely developer cannot handle all the modifications and new features requests. So if you know C++ and Qt framework programming and wants to contribute with coding let me know! I'll be grateful for any help to the project! - -Compiling/Installation ----------------------- - -For details about installation process from source code visit the [Installation](http://www.pgmodeler.com.br/support/installation) section. If you don't want to compile pgModeler there are binaries available for purchase at [official site](http://www.pgmodeler.com.br/download). +pgModeler has reached a state where its developer can't handle all the modifications and new feature requests by himself anymore. So if you know C++ and Qt, and want to contribute with coding, let me know! I'll be grateful for any help with the project! Known Issues ----------- +* Due to the usage of Qt's raster engine to draw objects, the process of handling objects on the canvas tends to get slower as lots of objects are created causing constant CPU usage. A heavy performance degradation can be noticed when dealing with models with ~500+ tables and/or relationships. There're plans to improve the speed of drawing operations, for large models, in future releases. Changing the relationship connection mode and render smoothness options may help in the performance when handling big database models. +* pgModeler can't handle correctly the importing of complex CSV files (multilined cell values) in data manipulation form, or pasting CSV content of that complexity on that dialog. +* Due to the CSV importing limitations, any value copied or exported from pgModeler in CSV format will be automatically formatted in the proper way that the tool can handle (by escaping any special character like line breaks and tabulations). If you intend to use CSV files generated by the tool in other software you have to revert back that characters escaping so the file can be read properly by third party softwares. * The diff process still presents false-positive results due its limitations. Sometimes, there is the need to run the process twice to get the full changes. -* pgModeler does not fully supports the [quoted identifier notation](http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS). When using quoted identifiers only the following characters are accepted in the middle of names: a-z A-Z 0-9 _ . @ $ - / \ space. -* pgModeler is unusable in sandboxed Mac OS X installations. To workaround this issue you'll need to deactivate sandbox usage to run pgModeler properly. There is no planning to adapt this tool for sandbox feature in Mac OS X. -* pgModeler can't be compiled in Microsoft Visual Studio due to use of some gcc/clang extensions. -* Compiling the source using '-Wconversion' (disabled by Qt in its default) generates a lot of warnings. These warnings are harmless in 99% of times but we can't just ignore them but I don't plan to fix them in a near future (mail me for more details). -* pgModeler sometimes can crash during the export, import or validation process due to some threaded operations that, depending on size and arrange of the model, causes race conditions. -* Due to particularities on executing bundles on MacOSX the file association does not work correctly on this system. So it's not possible to open a model file by clicking it on Finder. - -Change Log +* pgModeler does not fully support the [quoted identifier notation](http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS). When using quoted identifiers only the following characters are accepted in the middle of names: a-z A-Z 0-9 _ . @ $ - / \ space. +* pgModeler is unusable in sandboxed macOS. To workaround this issue you'll need to deactivate sandbox usage to run pgModeler properly. There is no plan to fix pgModeler to support this kind of environment. +* pgModeler can't be compiled with Microsoft Visual Studio due to use of some gcc/clang extensions. +* Compiling the source using '-Wconversion' (disabled by Qt in its defaults) generates a lot of warnings. These warnings are 99% harmless and there's no plans to fix them in a near future. +* pgModeler can sometimes crash during the export, import or validation process due to some threaded operations that, depending on the size and the arrangement of the model, cause race conditions. +* Due to particularities on executing bundles on MacOSX, the file association does not work correctly on this system. So it's not possible to open a model file by clicking it on Finder. + +Changelog ---------- -The detailed log of changes can be seen on [CHANGELOG.md](https://github.com/pgmodeler/pgmodeler/blob/master/CHANGELOG.md) file. +The detailed changelog can be seen on [CHANGELOG.md](https://github.com/pgmodeler/pgmodeler/blob/master/CHANGELOG.md) file. Older Releases/Code ------------------- -Older releases of pgModeler can be found at [Sourceforge.net](http://sourceforge.net/projects/pgmodeler) +Older releases of pgModeler can be found on [Sourceforge.net](http://sourceforge.net/projects/pgmodeler). diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3840d69f48..95e42e085a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,50 +1,25 @@ -v0.9.1-beta1 +v0.9.4 ------ -Release date: April 6, 2018
-Changes since: v0.9.1-beta
- -Summary: finally we've reached the last beta release of the 0.9.1! This time pgModeler brings important fixes and new features requested long ago which are finally implemented in experimental stage.
- -The first new feature we have in this release is the support to multiples relationships for the same pair of tables. In previous versions, pgModeler would refuse to create a second relationship between the tables A and B. From now on, pgModeler will accept the creation of one-to-many and many-to-many relationships linking A and B more then once. For the other kinds of relationships (generalization, copy, one-to-one) the old rule is still valid: only one relationship per table pair is accepted.
- -Some missing features of PostgreSQL are present in this version too being them: row level security (RLS) and identity columns. For RLS, introduced in PostgreSQL 9.5, we have added the related options to toggle it in tables (ENABLE|FORCE RLS) as well the support to policy objects which are the main part of this new security modality. The identity columns, introduced in PostgreSQL 10, are now fully supported by pgModeler and you can make use of them from the column editing form.
- -Other new feature is the support to multiple check constraints by domains. Actually, this is more a patch than a new feature because pgModeler was unaware that domains could support more than one check constraint, so we have fixed that now.
- -Now, talking about changes, we fixed an old missinterpretation of the PostgreSQL's documentations by changing the way extensions are stored in the database model. Previously, this kind of objects were stored at schemas level but the right way to store them is at database level. So now instead of seeing extensions in the schema's subtree you'll see them in the database subtree. All validation rules, export, import and diff processes were fixed in such way to reflect the right way to treat these objects.
- -Another important change, and that one is related to an annoying behaviour of the tool, is that pgModeler will silently ignore the absence of the plugins folder and proceed with the normal startup avoiding the display of a message box regarding the missing folder and automatically disabling the plugins search mechanism.
- -In the fixes section, we've included a patch for a bug that was causing recurrent crashes on macOS when the user tried to load a second model file making almost impossible the working on two or more database models at once. Also, we've patched the reverse engineering in such way to avoid the duplication of data types related to tables, sequences and views which was causing problems in the validation process. Another fix was done in the diff process that was generating a malformed DROP command for extensions.
- -The set of changes of this release has 47 entries between new features, changes, improvements and bug fixes. Below we highlight some of them, for the complete list, please, consider reading the CHANGELOG.md.
- -* [New] Added the ability to create multiples one-to-many and many-to-many relatationships between the same pair of tables. -* [New] Added the ability to use more special ascii chars in the middle of object names. -* [New] Added support to multi line comments in UI. -* [New] Added full support to row level security (RLS), including export, import and diff of this kind of object. -* [New] Added support to bulk data editing in DataManipulationForm. -* [New] Added an option to diff process to force the generation of DROP commands for columns and constraints even if the missing objects need to be preserved. This is useful to work with partial models and the user need to remove columns/constraints and preserve the rest of objects. -* [New] Added support to identity columns (PostgreSQL 10). -* [New] Added the support to BYPASSRLS option on roles. -* [New] Added support to IS_TEMPLATE and ALLOW_CONNECTIONS options in database object. -* [New] Added the procedures to fix old style domains in CLI. -* [New] Added support to multiple check constraint in domains. -* [New] Added support to sort items alphabetically (ascending) or by oid in DatabaseExplorerWidget. -* [Change] Changed the input mode of the password field in ConnectionsConfigWidget in order to hide the passwords in the form. NOTE: the passwords are still in plain text in the config file. -* [Change] Moved extensions from schema level to database level in order to reproduce better the PostgreSQL's behavior. -* [Change] In GeneralConfigWidget when restoring default settings the default settings for syntax highlight are restored as well. -* [Change] pgModeler will not try to create the plugins path anymore. This will avoid constant error messages during startup. Now, it'll silently ignore the absence of that folder and skip the plugin loading. -* [Change] Improved the source editing in external application. The use is informed about the app running state and the contents for the source editor field are locked until the user closes the external app. -* [Fix] Fixed the query catalog for built-in types to include the types related to domains. -* [Fix] Fixed the extension creation, allowing only one instance of the named extension per database no matter the schema used to allocate its children objects. -* [Fix] Fixed a bug when dropping Functions in DatabaseExplorerWidget. -* [Fix] Fixed a bug that was causing the disabling of connections for database models created prior to 0.9.1-beta1. -* [Fix] Fixed a bug on import process that was wrongly creating types derivated from tables/sequence/views causing duplication problems during validation. -* [Fix] Fixed a crash on macOs when opening a second model. -* [Fix] Fixed an issue in diff process that was generating a malformed DROP command for extensions. -* [Fix] Fixed the diff for domains which contain multiple check constraints. -* [Fix] Fixed a bug that was not selecting the correct spatial type in the widget. -* [Fix] Fixed a conflict of shortcuts in DatabaseExplorerWidget. Now F5 updates a leaf/subtree and Alt+F5 performs quick refresh of the tree. -* [Fix] Fixed a problem with sqlexecutionwidget.ui that is not building properly in Qt 5.10. +Release date: December 17, 2021
+Changes since: v0.9.3
+ +Attention: the database model file structure has changed since the last stable 0.9.3. Models created in older releases will certainly fail to load due to incompatibilities because some attributes in the XML code don't exist anymore or have changed during the development of 0.9.4. Before loading your database models in this new release, please, make sure to have a backup of them all and follow the steps presented by the model fix tool to patch the documents' structure. Not paying attention to this situation may cause irreversible data loss! If the fix procedures aren't enough to make your database models loadable again, please, ask for help at the official support channels!
+ +Summary: it was quite a challenge to develop version 0.9.4 during the year 2021 but we finally made it, the last pgModeler of the series 0.9.x is ready! This one has a vast set of improvements over 0.9.3, being 51 new features, 104 enhancements, and 73 bug fixes that will make a big difference in the overall usage of the tool.
+ +The first improvement in 0.9.4 is the ability to put objects in multiple layers which was not possible in previous versions. The user has now the ability to set up custom colors and labels for each layer enhancing the database model visualization and semantics. Still in the database model design, one can now define a custom color for canvas, grid lines, and page delimiter lines which can help a lot those who aren't comfortable with the excessive glare produced by the default color schema.
+ +This release also improves the support for some PostgreSQL objects by bringing the configuration parameters and transform types to functions and procedures, adding the support for PARALLEL attribute on functions, and the support for included columns also known as non-key columns on indexes. It's worth mentioning that the import and diff processes were also improved to support all the mentioned improvements in those objects. Besides, the diff process is now capable of generating GRANT and REVOKE commands to set up new role memberships.
+ +The data type configuration widget received a simple improvement which adds a significant reduction in the time spent to configure a data type. Now, the user can just type the name of the desired data type to be used instead of selecting it by using the mouse. After typing the data type name just hit the tab key to jump to the next field and the data type will be automatically configured. Seems a silly fix but it adds speed when you need to repeatedly create columns in a table, for example.
+ +In the SQL tool, is now possible to drop databases quickly from the databases listing. Previously, there was the need to browse the database first and then drop it. In the database browser widget, the tree items collapse state is saved and restored after any updates requested by the user, improving the overall experience on that module. In data manipulation form, the sorting operation performed when clicking columns was adjusted. Now, the sorting will be triggered by holding the control key and clicking the desired column, and if the user only clicks a column without holding the control key will cause the entire column to be selected in the grid.
+ +Attending to some requests, pgModeler is now capable of exporting the database model in split SQL files instead of generating a single SQL file representing the entire database. In this export mode, the files are named in such a way to represent the proper order of creation, which means that running the scripts one after another will create the whole database like it was created from a single file.
+ +Due to the introduction of a new syntax highlighting configuration file (for code snippets configuration), pgModeler will, from now on, create missing configuration files at startup. This will avoid breaking the tool's execution when it detects the absence of any configuration file. Also, during the copy of these files, pgModeler will enforce the write permission over them to avoid access problems on some systems that store template settings on read-only paths.
+ +The command-line interface was patched in such a way that now doesn't crash anymore when performing a diff operation in which a database model is used as input. Another improvement to the CLI is the introduction of the option --force in the mime type handling operation. Also, a patch was made in such a way to avoid the usage of option '-platform offscreen' explicitly when calling the application.
+ +Finally, there is a bunch of other new features and bug fixes implemented in almost all parts of the tool which improves stability and reliability. I kindly invite you to read the CHANGELOG.md file of the 0.9.4 development timeline to know everything in detail.
diff --git a/apps/apps.pri b/apps/apps.pri new file mode 100644 index 0000000000..b7569002cd --- /dev/null +++ b/apps/apps.pri @@ -0,0 +1,24 @@ +# This file contains the main variables shared by executables subprojects + +include(../pgmodeler.pri) + +unix|windows: LIBS += $$LIBGUI_LIB \ + $$LIBCANVAS_LIB \ + $$LIBCONNECTOR_LIB \ + $$LIBCORE_LIB \ + $$LIBPARSERS_LIB \ + $$LIBUTILS_LIB + +INCLUDEPATH += $$LIBGUI_INC \ + $$LIBCANVAS_INC \ + $$LIBCONNECTOR_INC \ + $$LIBCORE_INC \ + $$LIBPARSERS_INC \ + $$LIBUTILS_INC + +DEPENDPATH += $$LIBGUI_ROOT \ + $$LIBCANVAS_ROOT \ + $$LIBCONNECTOR_ROOT \ + $$LIBCORE_ROOT \ + $$LIBPARSERS_ROOT \ + $$LIBUTILS_ROOT diff --git a/apps/pgmodeler-ch/pgmodeler-ch.pro b/apps/pgmodeler-ch/pgmodeler-ch.pro new file mode 100644 index 0000000000..25a13db14d --- /dev/null +++ b/apps/pgmodeler-ch/pgmodeler-ch.pro @@ -0,0 +1,16 @@ +include(../apps.pri) + +TEMPLATE = app +TARGET = pgmodeler-ch + +windows:RC_FILE=res/windows_ico.qrc +windows:RCC_DIR=src/ + +SOURCES += src/main.cpp \ + src/crashhandlerform.cpp + +HEADERS += src/crashhandlerform.h + +# Deployment settings +target.path = $$PRIVATEBINDIR +INSTALLS = target diff --git a/crashhandler/res/windows_ico.ico b/apps/pgmodeler-ch/res/windows_ico.ico similarity index 100% rename from crashhandler/res/windows_ico.ico rename to apps/pgmodeler-ch/res/windows_ico.ico diff --git a/crashhandler/res/windows_ico.qrc b/apps/pgmodeler-ch/res/windows_ico.qrc similarity index 100% rename from crashhandler/res/windows_ico.qrc rename to apps/pgmodeler-ch/res/windows_ico.qrc diff --git a/apps/pgmodeler-ch/src/crashhandlerform.cpp b/apps/pgmodeler-ch/src/crashhandlerform.cpp new file mode 100644 index 0000000000..3e571d2917 --- /dev/null +++ b/apps/pgmodeler-ch/src/crashhandlerform.cpp @@ -0,0 +1,219 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "crashhandlerform.h" +#include "messagebox.h" +#include "guiutilsns.h" +#include "utilsns.h" + +const QString CrashHandlerForm::AnalysisMode("-analysis-mode"); + +CrashHandlerForm::CrashHandlerForm(bool analysis_mode, QWidget *parent, Qt::WindowFlags f) : BugReportForm(parent, f) +{ + QFile input; + QString buf; + QWidget *wgt=new QWidget; + QHBoxLayout *layout=new QHBoxLayout; + + setWindowTitle(tr("pgModeler crash handler")); + + stack_txt=new QPlainTextEdit(this); + stack_txt->setReadOnly(true); + stack_txt->setFont(QFont("Source Code Pro")); + stack_txt->setLineWrapMode(QPlainTextEdit::NoWrap); + + layout->addWidget(stack_txt); + layout->setContentsMargins(4,4,4,4); + wgt->setLayout(layout); + + logo_lbl->setPixmap(QPixmap(QString(":/images/images/crashhandler.png"))); + report_twg->addTab(wgt, tr("Stack trace")); + + //Open for reading the stack trace file generated on the last crash + input.setFileName(GlobalAttributes::getTemporaryFilePath(GlobalAttributes::StacktraceFile)); + input.open(QFile::ReadOnly); + + if(input.isOpen()) + { + buf=input.readAll(); + input.close(); + + //Removes the stack trace file + QDir stack_file; + stack_file.remove(GlobalAttributes::getTemporaryFilePath(GlobalAttributes::StacktraceFile)); + + //Shows the stacktrace loaded on the widget + stack_txt->setPlainText(buf); + } + + //Creating an input field in order to select the input report file + input_wgt=new QWidget(this); + input_wgt->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + + layout=new QHBoxLayout(input_wgt); + layout->setContentsMargins(0, 0, 0, 0); + + input_lbl=new QLabel(input_wgt); + input_lbl->setText(tr("Input:")); + layout->addWidget(input_lbl); + + input_sel = new FileSelectorWidget(this); + input_sel->setFileDialogTitle(tr("Select bug report file")); + input_sel->setFileMode(QFileDialog::ExistingFile); + input_sel->setAcceptMode(QFileDialog::AcceptOpen); + input_sel->setNameFilters({ tr("pgModeler bug report (*.bug)"), tr("All files (*.*)") }); + input_sel->setToolTip(tr("Load report file for analysis")); + layout->addWidget(input_sel); + + save_tb=new QToolButton(input_wgt); + save_tb->setIcon(QPixmap(GuiUtilsNs::getIconPath("save"))); + save_tb->setSizePolicy(attach_tb->sizePolicy()); + save_tb->setToolButtonStyle(attach_tb->toolButtonStyle()); + save_tb->setIconSize(attach_tb->iconSize()); + save_tb->setToolTip(tr("Save the attached model file on the filesystem")); + save_tb->setEnabled(false); + attach_wgt->layout()->addWidget(save_tb); + + report_tab_grid->removeWidget(details_gb); + report_tab_grid->removeWidget(output_wgt); + report_tab_grid->removeWidget(message_frm); + + report_tab_grid->addWidget(input_wgt); + report_tab_grid->addWidget(details_gb); + report_tab_grid->addWidget(output_wgt); + report_tab_grid->addWidget(message_frm); + + setAnalysisMode(analysis_mode); + + connect(input_sel, SIGNAL(s_fileSelected(QString)), this, SLOT(loadReport(QString))); + connect(input_sel, SIGNAL(s_selectorCleared()), model_txt, SLOT(clear())); + connect(input_sel, SIGNAL(s_selectorCleared()), details_txt, SLOT(clear())); + connect(input_sel, SIGNAL(s_selectorCleared()), stack_txt, SLOT(clear())); + connect(save_tb, SIGNAL(clicked()), this, SLOT(saveModel())); + + connect(model_txt, &QPlainTextEdit::textChanged, [&](){ + save_tb->setEnabled(!model_txt->toPlainText().isEmpty()); + }); +} + +void CrashHandlerForm::loadReport(QString filename) +{ + QFile input; + QFileInfo fi; + char *buf=nullptr; + Messagebox msgbox; + + fi.setFile(filename); + input.setFileName(filename); + input.open(QFile::ReadOnly); + + //Raises an error if the file could not be opened + if(!input.isOpen()) + msgbox.show(Exception::getErrorMessage(ErrorCode::FileDirectoryNotAccessed).arg(filename), Messagebox::ErrorIcon); + else + { + QByteArray uncomp_buf; + QString buf_aux, str_aux; + int i, idx; + QPlainTextEdit *txt_widgets[]={ details_txt, model_txt , stack_txt}; + + //Creates a text buffer + buf=new char[fi.size()]; + + //Reads the file storing it on the buffer + input.read(buf, fi.size()); + input.close(); + + //Uncompress the buffer + uncomp_buf.append(buf, fi.size()); + uncomp_buf=qUncompress(uncomp_buf); + + delete[](buf); + buf=nullptr; + + buf_aux=QString(uncomp_buf.data()); + i=idx=0; + + //Showing the sections of the uncompressed buffer on the respective widgets + while(i < buf_aux.size() && idx <= 2) + { + if(buf_aux.at(i).toLatin1()!=CharDelimiter) + str_aux.append(buf_aux.at(i)); + else + { + txt_widgets[idx++]->setPlainText(str_aux); + str_aux.clear(); + } + i++; + } + } +} + +void CrashHandlerForm::saveModel() +{ + QFileDialog file_dlg; + + try + { + file_dlg.setDefaultSuffix(QString("dbm")); + file_dlg.setWindowTitle(tr("Save model")); + file_dlg.setNameFilter(tr("Database model (*.dbm);;All files (*.*)")); + file_dlg.setFileMode(QFileDialog::AnyFile); + file_dlg.setAcceptMode(QFileDialog::AcceptSave); + file_dlg.setModal(true); + + if(file_dlg.exec()==QFileDialog::Accepted) + UtilsNs::saveFile(file_dlg.selectedFiles().at(0), model_txt->toPlainText().toUtf8()); + } + catch(Exception &e) + { + Messagebox msgbox; + msgbox.show(e); + } +} + +void CrashHandlerForm::setAnalysisMode(bool value) +{ + output_wgt->setEnabled(!value); + attach_tb->setEnabled(!value); + attach_mod_chk->setEnabled(!value); + save_tb->setVisible(value); + + create_btn->setVisible(!value); + input_wgt->setVisible(value); + + if(value) + { + title_lbl->setText(tr("pgModeler crash handler")); + msg_lbl->setText(tr("Bug report analysis mode activated.")); + } + else + { + title_lbl->setText(tr("Oops! pgModeler just crashed!")); + msg_lbl->setText(tr("We apologize for what happened! It is clear that a nasty bug caused that. Please fill out the form below describing your actions before pgModeler quit unexpectedly. This will help on bug extermination and improve the software.")); + } +} + +QByteArray CrashHandlerForm::generateReportBuffer() +{ + QByteArray buf=BugReportForm::generateReportBuffer(); + buf.append(stack_txt->toPlainText().toUtf8()); + buf.append(CharDelimiter); + + return buf; +} diff --git a/crashhandler/src/crashhandlerform.h b/apps/pgmodeler-ch/src/crashhandlerform.h similarity index 75% rename from crashhandler/src/crashhandlerform.h rename to apps/pgmodeler-ch/src/crashhandlerform.h index c30f913798..b15a76634d 100644 --- a/crashhandler/src/crashhandlerform.h +++ b/apps/pgmodeler-ch/src/crashhandlerform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2018 - Raphael Araújo e Silva +# Copyright 2006-2021 - Raphael Araújo e Silva # # 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 @@ -17,8 +17,8 @@ */ /** -\ingroup crashhandler -\class CrashHandler +\ingroup pgmodeler-ch +\class CrashHandlerForm \brief Implements the pgModeler's crash handler enabling the generation an analysis of crash report files. */ @@ -26,7 +26,7 @@ #define CRASH_HANDLER_H #include -#include "bugreportform.h" +#include "tools/bugreportform.h" class CrashHandlerForm: public BugReportForm { private: @@ -40,32 +40,27 @@ class CrashHandlerForm: public BugReportForm { QLabel *input_lbl; - //! \brief Display the path to input report file - QLineEdit *input_edt; + FileSelectorWidget *input_sel; //! \brief Triggers the model saving to filesystem - QToolButton *save_tb, - - //! \brief Triggers the report file loading - *load_tb; - - //! \brief Load a report file showing its contents on the form - void loadReport(const QString &filename); + QToolButton *save_tb; void setAnalysisMode(bool value); //! \brief Generates a report buffer containing the issue details, model and stacktrace - QByteArray generateReportBuffer(void); + QByteArray generateReportBuffer(); public: //! \brief Analysis mode argument - const static QString ANALYSIS_MODE; + static const QString AnalysisMode; - CrashHandlerForm(bool analysis_mode=false, QWidget * parent = 0, Qt::WindowFlags f = 0); + CrashHandlerForm(bool analysis_mode=false, QWidget * parent = nullptr, Qt::WindowFlags f = Qt::Widget); private slots: - void loadReport(void); - void saveModel(void); + //! \brief Load a report file showing its contents on the form + void loadReport(QString filename); + + void saveModel(); }; #endif diff --git a/apps/pgmodeler-ch/src/main.cpp b/apps/pgmodeler-ch/src/main.cpp new file mode 100644 index 0000000000..52bb85057e --- /dev/null +++ b/apps/pgmodeler-ch/src/main.cpp @@ -0,0 +1,51 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "crashhandlerform.h" +#include "application.h" +#include +#include "guiutilsns.h" + +int main(int argc, char **argv) +{ + try + { + Application::setAttribute(Qt::AA_UseHighDpiPixmaps); + Application::setAttribute(Qt::AA_EnableHighDpiScaling); + Application app(argc,argv); + QStringList args = app.arguments(); + QTranslator translator; + + //Loads the ui translation for crashhandler + translator.load(QLocale::system().name(), GlobalAttributes::getLanguagesDir()); + app.installTranslator(&translator); + + CrashHandlerForm crashhandler(args.size() > 1 && args[1]==CrashHandlerForm::AnalysisMode); + GuiUtilsNs::resizeDialog(&crashhandler); + crashhandler.show(); + app.exec(); + + return 0; + } + catch(Exception &e) + { + QTextStream out(stdout); + out << e.getExceptionsText(); + return enum_cast(e.getErrorCode()); + } +} diff --git a/apps/pgmodeler-cli/pgmodeler-cli.pro b/apps/pgmodeler-cli/pgmodeler-cli.pro new file mode 100644 index 0000000000..7a6f320f9a --- /dev/null +++ b/apps/pgmodeler-cli/pgmodeler-cli.pro @@ -0,0 +1,18 @@ +include(../apps.pri) + +CONFIG += console +TEMPLATE = app +TARGET = pgmodeler-cli + +windows:RC_FILE = res/windows_ico.qrc +windows: RCC_DIR = src/ +windows: DESTDIR = $$PWD + +SOURCES += src/main.cpp \ + src/pgmodelercliapp.cpp + +HEADERS += src/pgmodelercliapp.h + +# Deployment settings +target.path = $$BINDIR +INSTALLS = target diff --git a/apps/pgmodeler-cli/res/windows_ico.ico b/apps/pgmodeler-cli/res/windows_ico.ico new file mode 100644 index 0000000000..29aae2f243 Binary files /dev/null and b/apps/pgmodeler-cli/res/windows_ico.ico differ diff --git a/apps/pgmodeler-cli/res/windows_ico.qrc b/apps/pgmodeler-cli/res/windows_ico.qrc new file mode 100644 index 0000000000..3eb8997455 --- /dev/null +++ b/apps/pgmodeler-cli/res/windows_ico.qrc @@ -0,0 +1 @@ + IDI_ICON1 ICON DISCARDABLE "windows_ico.ico" diff --git a/apps/pgmodeler-cli/src/main.cpp b/apps/pgmodeler-cli/src/main.cpp new file mode 100644 index 0000000000..6af2c10ea5 --- /dev/null +++ b/apps/pgmodeler-cli/src/main.cpp @@ -0,0 +1,67 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include +#include "pgmodelercliapp.h" +#include "qtcompat/qtextstreamcompat.h" + +int main(int argc, char **argv) +{ + QTextStream out(stdout); + +#ifdef DEMO_VERSION + out << QtCompat::endl; + out << QString("pgModeler ") << GlobalAttributes::PgModelerVersion << QT_TR_NOOP(" command line interface.") << QtCompat::endl; + out << QT_TR_NOOP("PostgreSQL Database Modeler Project - pgmodeler.io") << QtCompat::endl; + out << QT_TR_NOOP("Copyright 2006-2020 Raphael A. Silva ") << QtCompat::endl; + out << QT_TR_NOOP("\n** CLI disabled in demonstration version! **") << QtCompat::endl << QtCompat::endl; +#else + try + { + #ifdef Q_OS_LINUX + /* Workaround to make the CLI work on Linux systems without graphical interface. + * In that case, we just check if there's a DISPLAY env var defined. If not defined + * we force the usage of the "offscreen" plugin via QT_QPA_PLATFORM so the portions of + * the application that contains GUI elements can work properly. + * + * Details at https://github.com/pgmodeler/pgmodeler/issues/1604 */ + if(qgetenv("DISPLAY").isEmpty()) + qputenv("QT_QPA_PLATFORM", "offscreen"); + #endif + + PgModelerCliApp pgmodeler_cli(argc, argv); + QTranslator translator(&pgmodeler_cli); + + //Tries to load the ui translation according to the system's locale + translator.load(QLocale::system().name(), GlobalAttributes::getLanguagesDir()); + + //Installs the translator on the application + pgmodeler_cli.installTranslator(&translator); + + //Executes the cli + return pgmodeler_cli.exec(); + } + catch(Exception &e) + { + out << QtCompat::endl; + out << e.getExceptionsText(); + out << QString("** pgmodeler-cli aborted due to critical error(s). **") << QtCompat::endl << QtCompat::endl; + return (e.getErrorCode()==ErrorCode::Custom ? -1 : enum_cast(e.getErrorCode())); + } +#endif +} diff --git a/apps/pgmodeler-cli/src/pgmodelercliapp.cpp b/apps/pgmodeler-cli/src/pgmodelercliapp.cpp new file mode 100644 index 0000000000..a856af7d84 --- /dev/null +++ b/apps/pgmodeler-cli/src/pgmodelercliapp.cpp @@ -0,0 +1,2320 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "pgmodelercliapp.h" +#include "qtcompat/qtextstreamcompat.h" +#include "qtcompat/splitbehaviorcompat.h" +#include "utilsns.h" + +QTextStream PgModelerCliApp::out(stdout); + +const QRegExp PgModelerCliApp::PasswordRegExp=QRegExp("(password)(=)(.)*( )"); +const QString PgModelerCliApp::PasswordPlaceholder("password=******"); + +const QString PgModelerCliApp::AllChildren("all"); +const QString PgModelerCliApp::Input("--input"); +const QString PgModelerCliApp::Output("--output"); +const QString PgModelerCliApp::InputDb("--input-db"); +const QString PgModelerCliApp::ExportToFile("--export-to-file"); +const QString PgModelerCliApp::ExportToPng("--export-to-png"); +const QString PgModelerCliApp::ExportToSvg("--export-to-svg"); +const QString PgModelerCliApp::ExportToDbms("--export-to-dbms"); +const QString PgModelerCliApp::ExportToDict("--export-to-dict"); +const QString PgModelerCliApp::ImportDb("--import-db"); +const QString PgModelerCliApp::NoIndex("--no-index"); +const QString PgModelerCliApp::Split("--split"); +const QString PgModelerCliApp::Diff("--diff"); +const QString PgModelerCliApp::DropDatabase("--drop-database"); +const QString PgModelerCliApp::DropObjects("--drop-objects"); +const QString PgModelerCliApp::PgSqlVer("--pgsql-ver"); +const QString PgModelerCliApp::Help("--help"); +const QString PgModelerCliApp::ShowGrid("--show-grid"); +const QString PgModelerCliApp::ShowDelimiters("--show-delimiters"); +const QString PgModelerCliApp::PageByPage("--page-by-page"); +const QString PgModelerCliApp::IgnoreDuplicates("--ignore-duplicates"); +const QString PgModelerCliApp::IgnoreErrorCodes("--ignore-error-codes"); +const QString PgModelerCliApp::ConnAlias("--conn-alias"); +const QString PgModelerCliApp::Host("--host"); +const QString PgModelerCliApp::Port("--port"); +const QString PgModelerCliApp::User("--user"); +const QString PgModelerCliApp::Passwd("--passwd"); +const QString PgModelerCliApp::InitialDb("--initial-db"); +const QString PgModelerCliApp::Silent("--silent"); +const QString PgModelerCliApp::ListConns("--list-conns"); +const QString PgModelerCliApp::Simulate("--simulate"); +const QString PgModelerCliApp::FixModel("--fix-model"); +const QString PgModelerCliApp::FixTries("--fix-tries"); +const QString PgModelerCliApp::ZoomFactor("--zoom"); +const QString PgModelerCliApp::UseTmpNames("--use-tmp-names"); +const QString PgModelerCliApp::DbmMimeType("--dbm-mime-type"); +const QString PgModelerCliApp::Install("install"); +const QString PgModelerCliApp::Uninstall("uninstall"); +const QString PgModelerCliApp::SystemWide("--system-wide"); +const QString PgModelerCliApp::IgnoreImportErrors("--ignore-errors"); +const QString PgModelerCliApp::ImportSystemObjs("--import-sys-objs"); +const QString PgModelerCliApp::ImportExtensionObjs("--import-ext-objs"); +const QString PgModelerCliApp::DebugMode("--debug-mode"); +const QString PgModelerCliApp::FilterObjects("--filter-objects"); +const QString PgModelerCliApp::MatchByName("--match-by-name"); +const QString PgModelerCliApp::ForceChildren("--force-children"); +const QString PgModelerCliApp::OnlyMatching("--only-matching"); +const QString PgModelerCliApp::PartialDiff("--partial"); +const QString PgModelerCliApp::Force("--force"); +const QString PgModelerCliApp::StartDate("--start-date"); +const QString PgModelerCliApp::EndDate("--end-date"); +const QString PgModelerCliApp::CompareTo("--compare-to"); +const QString PgModelerCliApp::SaveDiff("--save"); +const QString PgModelerCliApp::ApplyDiff("--apply"); +const QString PgModelerCliApp::NoDiffPreview("--no-preview"); +const QString PgModelerCliApp::DropClusterObjs("--drop-cluster-objs"); +const QString PgModelerCliApp::RevokePermissions("--revoke-perms"); +const QString PgModelerCliApp::DropMissingObjs("--drop-missing"); +const QString PgModelerCliApp::ForceDropColsConstrs("--force-drop-cols"); +const QString PgModelerCliApp::RenameDb("--rename-db"); +const QString PgModelerCliApp::NoSequenceReuse("--no-sequence-reuse"); +const QString PgModelerCliApp::NoCascadeDrop("--no-cascade"); +const QString PgModelerCliApp::ForceRecreateObjs("--force-recreate-objs"); +const QString PgModelerCliApp::OnlyUnmodifiable("--only-unmodifiable"); +const QString PgModelerCliApp::CreateConfigs("--create-configs"); +const QString PgModelerCliApp::MissingOnly("--missing-only"); + +const QString PgModelerCliApp::TagExpr("<%1"); +const QString PgModelerCliApp::EndTagExpr(" PgModelerCliApp::long_opts = { + { Input, true }, { Output, true }, { InputDb, true }, + { ExportToFile, false }, { ExportToPng, false }, { ExportToSvg, false }, + { ExportToDbms, false }, { ImportDb, false }, { Diff, false }, + { DropDatabase, false }, { DropObjects, false }, { PgSqlVer, true }, + { Help, false }, { ShowGrid, false }, { ShowDelimiters, false }, + { PageByPage, false }, { IgnoreDuplicates, false }, { IgnoreErrorCodes, true }, + { ConnAlias, true }, { Host, true }, { Port, true }, + { User, true }, { Passwd, true }, { InitialDb, true }, + { ListConns, false }, { Simulate, false }, { FixModel, false }, + { FixTries, true }, { ZoomFactor, true }, { UseTmpNames, false }, + { DbmMimeType, true }, { IgnoreImportErrors, false }, { ImportSystemObjs, false }, + { ImportExtensionObjs, false }, { FilterObjects, true }, { ForceChildren, true }, + { OnlyMatching, false }, { MatchByName, false }, { DebugMode, false }, + { PartialDiff, false }, { StartDate, true }, { EndDate, true }, + { CompareTo, true }, { SaveDiff, false }, { ApplyDiff, false }, + { NoDiffPreview, false }, { DropClusterObjs, false }, { RevokePermissions, false }, + { DropMissingObjs, false }, { ForceDropColsConstrs, false }, { RenameDb, false }, + { NoSequenceReuse, false }, { NoCascadeDrop, false }, + { ForceRecreateObjs, false }, { OnlyUnmodifiable, false }, { ExportToDict, false }, + { NoIndex, false }, { Split, false }, { SystemWide, false }, + { CreateConfigs, false }, { Force, false }, { MissingOnly, false } +}; + +map PgModelerCliApp::accepted_opts = { + {{ Attributes::Connection }, { ConnAlias, Host, Port, User, Passwd, InitialDb }}, + {{ ExportToFile }, { Input, Output, PgSqlVer, Split }}, + {{ ExportToPng }, { Input, Output, ShowGrid, ShowDelimiters, PageByPage, ZoomFactor }}, + {{ ExportToSvg }, { Input, Output, ShowGrid, ShowDelimiters }}, + {{ ExportToDict }, { Input, Output, Split, NoIndex }}, + + {{ ExportToDbms }, { Input, PgSqlVer, IgnoreDuplicates, IgnoreErrorCodes, + DropDatabase, DropObjects, Simulate, UseTmpNames }}, + + {{ ImportDb }, { InputDb, Output, IgnoreImportErrors, ImportSystemObjs, ImportExtensionObjs, + FilterObjects, OnlyMatching, MatchByName, ForceChildren, DebugMode, ConnAlias, + Host, Port, User, Passwd, InitialDb }}, + + {{ Diff }, { Input, PgSqlVer, IgnoreDuplicates, IgnoreErrorCodes, CompareTo, PartialDiff, Force, + StartDate, EndDate, SaveDiff, ApplyDiff, NoDiffPreview, DropClusterObjs, RevokePermissions, + DropMissingObjs, ForceDropColsConstrs, RenameDb, NoCascadeDrop, + NoSequenceReuse, ForceRecreateObjs, OnlyUnmodifiable }}, + + {{ DbmMimeType }, { SystemWide, Force }}, + {{ FixModel }, { Input, Output, FixTries }}, + {{ ListConns }, {}}, + {{ CreateConfigs }, {MissingOnly, Force}} +}; + +PgModelerCliApp::PgModelerCliApp(int argc, char **argv) : Application(argc, argv) +{ + try + { + QString op, value, orig_op; + bool accepts_val=false; + attribs_map opts; + QStringList args = arguments(); + + model=nullptr; + scene=nullptr; + xmlparser=nullptr; + zoom=1; + + export_hlp = nullptr; + import_hlp = nullptr; + diff_hlp = nullptr; + conn_conf = nullptr; + rel_conf = nullptr; + general_conf = nullptr; + + // We extract the options values only if the help option is not present + if(args.size() > 1 && !args.contains(Help) && !args.contains(short_opts[Help])) + { + for(int i=1; i < argc; i++) + { + op = orig_op = argv[i]; + + //If the retrieved option starts with - it will be treated as a command option + if(op[0]=='-') + { + value.clear(); + + if(i < argc-1 && argv[i+1][0]!='-') + { + //If the next option does not starts with '-', is considered a value + value=argv[++i]; + } + + //Raises an error if the option is not recognized + if(!isOptionRecognized(op, accepts_val)) + throw Exception(tr("Unrecognized option `%1'.").arg(orig_op), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + //Raises an error if the value is empty and the option accepts a value + if(accepts_val && value.isEmpty()) + throw Exception(tr("Value not specified for option `%1'.").arg(orig_op), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + else if(!accepts_val && !value.isEmpty()) + throw Exception(tr("Option `%1' does not accept values.").arg(orig_op), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + /* If we find a filter object parameter we append its parameter index so + * its value is not replaced by the next filter parameter found */ + if(op == FilterObjects) + opts[QString("%1%2").arg(op).arg(i)] = value; + + opts[op] = value; + } + } + } + + //Validates and executes the options + parseOptions(opts); + + if(!parsed_opts.empty()) + { + model=new DatabaseModel; + xmlparser=model->getXMLParser(); + silent_mode=(parsed_opts.count(Silent)); + + //If the export is to png or svg loads additional configurations + if(parsed_opts.count(ExportToPng) || parsed_opts.count(ExportToSvg) || parsed_opts.count(ImportDb)) + { + connect(model, SIGNAL(s_objectAdded(BaseObject *)), this, SLOT(handleObjectAddition(BaseObject *))); + connect(model, SIGNAL(s_objectRemoved(BaseObject *)), this, SLOT(handleObjectRemoval(BaseObject *))); + + //Load the general configuration including grid and delimiter options + GeneralConfigWidget conf_wgt; + conf_wgt.loadConfiguration(); + + //Load the objects styles + BaseObjectView::loadObjectsStyle(); + + scene=new ObjectsScene; + scene->setParent(this); + scene->setSceneRect(QRectF(0,0,2000,2000)); + } + + if(parsed_opts.count(ExportToDbms) || parsed_opts.count(ImportDb) || parsed_opts.count(Diff)) + { + configureConnection(false); + + //Replacing the initial db parameter for the input database when reverse engineering + if((parsed_opts.count(ImportDb) || parsed_opts.count(Diff)) && !parsed_opts[InputDb].isEmpty()) + connection.setConnectionParam(Connection::ParamDbName, parsed_opts[InputDb]); + } + + if(parsed_opts.count(Diff)) + { + configureConnection(true); + + if(!extra_connection.isConfigured()) + extra_connection = connection; + + extra_connection.setConnectionParam(Connection::ParamDbName, parsed_opts[CompareTo]); + } + + if(!silent_mode && export_hlp && import_hlp && diff_hlp) + { + connect(export_hlp, SIGNAL(s_progressUpdated(int,QString)), this, SLOT(updateProgress(int,QString))); + connect(export_hlp, SIGNAL(s_errorIgnored(QString,QString,QString)), this, SLOT(printIgnoredError(QString,QString,QString))); + connect(import_hlp, SIGNAL(s_progressUpdated(int,QString,ObjectType)), this, SLOT(updateProgress(int,QString))); + connect(diff_hlp, SIGNAL(s_progressUpdated(int,QString,ObjectType)), this, SLOT(updateProgress(int,QString))); + } + } + } + catch(Exception &e) + { + throw e; + } +} + +PgModelerCliApp::~PgModelerCliApp() +{ + if(scene) + delete scene; + + delete model; + + if(export_hlp) + delete export_hlp; + + if(import_hlp) + delete import_hlp; + + if(diff_hlp) + delete diff_hlp; + + if(conn_conf) + delete conn_conf; + + if(rel_conf) + delete rel_conf; + + if(general_conf) + delete general_conf; +} + +void PgModelerCliApp::printText(const QString &txt) +{ + out << txt << QtCompat::endl; +} + +void PgModelerCliApp::printMessage(const QString &txt) +{ + if(!silent_mode) + printText(txt); +} + +void PgModelerCliApp::configureConnection(bool extra_conn) +{ + QString chr = (extra_conn ? "1" : ""); + Connection *conn = (extra_conn ? &extra_connection : &connection); + + //Getting the connection using its alias + if(parsed_opts.count(ConnAlias + chr)) + { + if(!connections.count(parsed_opts[ConnAlias + chr])) + throw Exception(tr("Connection aliased as '%1' was not found in the configuration file.").arg(parsed_opts[ConnAlias + chr]), + ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + //Make a copy of the named connection + *conn = (*connections[parsed_opts[ConnAlias + chr]]); + } + else + { + conn->setConnectionParam(Connection::ParamServerFqdn, parsed_opts[Host + chr]); + conn->setConnectionParam(Connection::ParamUser, parsed_opts[User + chr]); + conn->setConnectionParam(Connection::ParamPort, parsed_opts[Port + chr]); + conn->setConnectionParam(Connection::ParamPassword, parsed_opts[Passwd + chr]); + conn->setConnectionParam(Connection::ParamDbName, parsed_opts[InitialDb + chr]); + } +} + +bool PgModelerCliApp::isOptionRecognized(QString &op, bool &accepts_val) +{ + bool found=false, append_chr = false; + + if(op.endsWith('1')) + { + op.chop(1); + append_chr = true; + } + + for(auto &itr : short_opts) + { + found=(op==itr.first || op==itr.second); + accepts_val=(found && long_opts[itr.first]); + + if(found) + { + op = itr.first; + break; + } + } + + if(append_chr) op += '1'; + return found; +} + +void PgModelerCliApp::showVersionInfo() +{ + printMessage(); + printMessage(tr("pgModeler command line interface.") ); + printMessage(tr("Version ") + GlobalAttributes::PgModelerVersion + QString(" - %1 Qt %2").arg(GlobalAttributes::PgModelerBuildNumber).arg(QT_VERSION_STR)); + printMessage(tr("PostgreSQL Database Modeler Project - pgmodeler.io") ); + printMessage(tr("Copyright 2006-%1 Raphael Araújo e Silva ").arg(QDate::currentDate().year())); + printMessage(); +} + +void PgModelerCliApp::showMenu() +{ + showVersionInfo(); + + printText(tr("Usage: pgmodeler-cli [OPTIONS]")); + printText(tr("This CLI tool provides several operations over models and databases without the need to perform them\nin pgModeler's graphical interface. All available options are described below.")); + printText(); + + printText(tr("Operation mode options: ")); + printText(tr(" %1, %2\t\t Export the input model to sql script file(s).").arg(short_opts[ExportToFile]).arg(ExportToFile)); + printText(tr(" %1, %2\t\t Export the input model to a png image.").arg(short_opts[ExportToPng]).arg(ExportToPng) ); + printText(tr(" %1, %2\t\t Export the input model to a svg file.").arg(short_opts[ExportToSvg]).arg(ExportToSvg) ); + printText(tr(" %1, %2\t\t Export the input model to a data directory in HTML format.").arg(short_opts[ExportToDict]).arg(ExportToDict)); + printText(tr(" %1, %2\t\t Export the input model directly to a PostgreSQL server.").arg(short_opts[ExportToDbms]).arg(ExportToDbms)); + printText(tr(" %1, %2\t\t List available connections in file %3.").arg(short_opts[ListConns]).arg(ListConns).arg(GlobalAttributes::ConnectionsConf + GlobalAttributes::ConfigurationExt)); + printText(tr(" %1, %2\t\t Import a database to an output file.").arg(short_opts[ImportDb]).arg(ImportDb)); + printText(tr(" %1, %2\t\t\t Compares a model and a database or two databases generating the SQL script to sync the latter in relation to the first.").arg(short_opts[Diff]).arg(Diff)); + printText(tr(" %1, %2\t\t Try to fix the structure of the input model file in order to make it loadable again.").arg(short_opts[FixModel]).arg(FixModel)); + printText(tr(" %1, %2\t\t Create the pgModeler's configuration folder and files in the user's local storage.").arg(short_opts[CreateConfigs]).arg(CreateConfigs)); +#ifndef Q_OS_MAC + printText(tr(" %1, %2 [ACTION]\t Handles the file association to .dbm files. The ACTION can be [%3 | %4].").arg(short_opts[DbmMimeType]).arg(DbmMimeType).arg(Install).arg(Uninstall)); +#endif + printText(tr(" %1, %2\t\t\t Show this help menu.").arg(short_opts[Help]).arg(Help)); + printText(); + + printText(tr("General options: ")); + printText(tr(" %1, %2 [FILE]\t\t Input model file (.dbm). This is mandatory for export and fix operations.").arg(short_opts[Input]).arg(Input)); + printText(tr(" %1, %2 [DBNAME]\t Input database name. This is mandatory for import operation.").arg(short_opts[InputDb]).arg(InputDb)); + printText(tr(" %1, %2 [FILE|DIRECTORY] Output file or directory. This is mandatory for fixing model or exporting to file, png or svg.").arg(short_opts[Output]).arg(Output)); + printText(tr(" %1, %2\t\t Force the PostgreSQL syntax to the specified version when generating SQL code. The version string must be in form major.minor.").arg(short_opts[PgSqlVer]).arg(PgSqlVer)); + printText(tr(" %1, %2\t\t\t Silent execution. Only critical messages and errors are shown during process.").arg(short_opts[Silent]).arg(Silent)); + printText(); + + printText(tr("SQL file export options: ")); + printText(tr(" %1, %2\t\t\t The SQL file is generated per object. The files will be named in such a way to reflect the correct creation order of the objects.").arg(short_opts[Split]).arg(Split)); + printText(); + + printText(tr("PNG and SVG export options: ")); + printText(tr(" %1, %2\t\t Draws the grid in the exported image.").arg(short_opts[ShowGrid]).arg(ShowGrid)); + printText(tr(" %1, %2\t Draws the page delimiters in the exported image.").arg(short_opts[ShowDelimiters]).arg(ShowDelimiters)); + printText(tr(" %1, %2\t\t Each page will be exported in a separated png image. (Only for PNG images)").arg(short_opts[PageByPage]).arg(PageByPage)); + printText(tr(" %1, %2 [FACTOR]\t\t Applies a zoom (in percent) before export to png image. Accepted zoom interval: %3-%4 (Only for PNG images)").arg(short_opts[ZoomFactor]).arg(ZoomFactor).arg(ModelWidget::MinimumZoom*100).arg(ModelWidget::MaximumZoom*100)); + printText(); + + printText(tr("Data dictionary export options: ")); + printText(tr(" %1, %2\t\t\t The data dictionaries are generated in separated files inside the selected output directory.").arg(short_opts[Split]).arg(Split)); + printText(tr(" %1, %2\t\t Avoids the generation of the index that is used to help navigating through the data dictionary.").arg(short_opts[NoIndex]).arg(NoIndex)); + printText(); + + printText(tr("Connection options: ")); + printText(tr(" %1, %2 [ALIAS]\t Connection configuration alias to be used.").arg(short_opts[ConnAlias]).arg(ConnAlias)); + printText(tr(" %1, %2 [HOST]\t\t PostgreSQL host in which a task will operate.").arg(short_opts[Host]).arg(Host)); + printText(tr(" %1, %2 [PORT]\t\t PostgreSQL host listening port.").arg(short_opts[Port]).arg(Port)); + printText(tr(" %1, %2 [USER]\t\t PostgreSQL username.").arg(short_opts[User]).arg(User)); + printText(tr(" %1, %2 [PASSWORD]\t PostgreSQL user password.").arg(short_opts[Passwd]).arg(Passwd)); + printText(tr(" %1, %2 [DBNAME]\t Connection's initial database.").arg(short_opts[InitialDb]).arg(InitialDb)); + printText(); + + printText(tr("DBMS export options: ")); + printText(tr(" %1, %2\t Ignores errors related to duplicated objects that eventually exist in the server.").arg(short_opts[IgnoreDuplicates]).arg(IgnoreDuplicates)); + printText(tr(" %1, %2 [CODES] Ignores additional errors by their codes. A comma-separated list of alphanumeric codes should be provided.").arg(short_opts[IgnoreErrorCodes]).arg(IgnoreErrorCodes)); + printText(tr(" %1, %2\t\t Drop the database before execute a export process.").arg(short_opts[DropDatabase]).arg(DropDatabase)); + printText(tr(" %1, %2\t\t Runs the DROP commands attached to SQL-enabled objects.").arg(short_opts[DropObjects]).arg(DropObjects)); + printText(tr(" %1, %2\t\t Simulates an export process by executing all steps but undoing any modification in the end.").arg(short_opts[Simulate]).arg(Simulate)); + printText(tr(" %1, %2\t\t Generates temporary names for database, roles and tablespaces when in simulation mode.").arg(short_opts[UseTmpNames]).arg(UseTmpNames)); + printText(); + + printText(tr("Database import options: ")); + printText(tr(" %1, %2\t\t Ignore all errors and try to create as many as possible objects.").arg(short_opts[IgnoreImportErrors]).arg(IgnoreImportErrors)); + printText(tr(" %1, %2\t Import system built-in objects. This option causes the model bloating due to the importing of unneeded objects.").arg(short_opts[ImportSystemObjs]).arg(ImportSystemObjs)); + printText(tr(" %1, %2\t Import extension objects. This option causes the model bloating due to the importing of unneeded objects.").arg(short_opts[ImportExtensionObjs]).arg(ImportExtensionObjs)); + printText(tr(" %1, %2 [FILTER] Causes the import process to import only those objects matching the filter(s). The FILTER should be in the form type:pattern:mode.").arg(short_opts[FilterObjects]).arg(FilterObjects)); + printText(tr(" %1, %2\t\t Causes only objects matching the provided filter(s) to be imported. Those not matching filter(s) are discarded.").arg(short_opts[OnlyMatching]).arg(OnlyMatching)); + printText(tr(" %1, %2\t\t Causes the objects matching to be performed over their names instead of their signature ([schema].[name]).").arg(short_opts[MatchByName]).arg(MatchByName)); + printText(tr(" %1, %2 [OBJECTS] Forces the importing of children objects related to tables/views/foreign tables matched by the filter(s). The OBJECTS is a comma separated list types.").arg(short_opts[ForceChildren]).arg(ForceChildren)); + printText(tr(" %1, %2\t\t Run import in debug mode printing all queries executed in the server.").arg(short_opts[DebugMode]).arg(DebugMode)); + printText(); + + printText(tr("Diff options: ")); + printText(tr(" %1, %2 [DBNAME]\t The database used in the comparison. All the SQL code generated is applied to it.").arg(short_opts[CompareTo]).arg(CompareTo)); + printText(tr(" %1, %2\t\t Toggles the partial diff operation. A set of objects filters should be provided using the import option %3.").arg(short_opts[PartialDiff]).arg(PartialDiff).arg(FilterObjects)); + printText(tr(" %1, %2\t\t\t Forces a full diff if the provided filters were not able to retrieve objects for a partial diff operation.").arg(short_opts[Force]).arg(Force)); + printText(tr(" %1, %2\t\t Matches all database model objects in which modification date starts in the specified date. (Only for partial diff)").arg(short_opts[StartDate]).arg(StartDate)); + printText(tr(" %1, %2\t\t Matches all database model objects in which modification date ends in the specified date. (Only for partial diff)").arg(short_opts[EndDate]).arg(EndDate)); + printText(tr(" %1, %2\t\t\t Save the generated diff code to output file.").arg(short_opts[SaveDiff]).arg(SaveDiff)); + printText(tr(" %1, %2\t\t\t Apply the generated diff code on the database server.").arg(short_opts[ApplyDiff]).arg(ApplyDiff)); + printText(tr(" %1, %2\t\t Don't preview the generated diff code when applying it to the server.").arg(short_opts[NoDiffPreview]).arg(NoDiffPreview)); + printText(tr(" %1, %2\t Drop cluster level objects like roles and tablespaces.").arg(short_opts[DropClusterObjs]).arg(DropClusterObjs)); + printText(tr(" %1, %2\t\t Revoke permissions already set on the database. New permissions configured in the input model are still applied.").arg(short_opts[RevokePermissions]).arg(RevokePermissions)); + printText(tr(" %1, %2\t\t Drop missing objects. Generates DROP commands for objects that are present in the input model but not in the compared database.").arg(short_opts[DropMissingObjs]).arg(DropMissingObjs)); + printText(tr(" %1, %2\t Force the drop of missing columns and constraints. Causes only columns and constraints to be dropped, other missing objects aren't removed.").arg(short_opts[ForceDropColsConstrs]).arg(ForceDropColsConstrs)); + printText(tr(" %1, %2\t\t Rename the destination database when the names of the involved databases are different.").arg(short_opts[RenameDb]).arg(RenameDb)); + printText(tr(" %1, %2\t\t Don't drop objects in cascade mode.").arg(short_opts[NoCascadeDrop]).arg(NoCascadeDrop)); + printText(tr(" %1, %2\t Don't reuse sequences on serial columns. Drop the old sequence assigned to a serial column and creates a new one.").arg(short_opts[NoSequenceReuse]).arg(NoSequenceReuse)); + printText(tr(" %1, %2\t Force the recreating of objects. Instead of an ALTER command a DROP and CREATE commands are used to create a new version of the objects.").arg(short_opts[ForceRecreateObjs]).arg(ForceRecreateObjs)); + printText(tr(" %1, %2\t Recreate only the unmodifiable objects. These objects are the ones which can't be changed via ALTER command.").arg(short_opts[OnlyUnmodifiable]).arg(OnlyUnmodifiable)); + printText(); + + printText(tr("Model fix options: ") ); + printText(tr(" %1, %2 [NUMBER]\t Model fix tries. When reaching the maximum count the invalid objects will be discarded.").arg(short_opts[FixTries]).arg(FixTries)); + printText(); + +#ifndef Q_OS_MAC + printText(tr("File association options: ")); + printText(tr(" %1, %2\t\t The file association to .dbm files will be applied in a system wide level instead of to the current user.").arg(short_opts[SystemWide]).arg(SystemWide)); + printText(tr(" %1, %2 \t\t\t Forces the mime type install or uninstall. ").arg(short_opts[Force]).arg(Force)); + printText(); +#endif + + printText(tr("Config files creation options: ")); + printText(tr(" %1, %2 \t\t Copy only missing configuration files to the user's local storage.").arg(short_opts[MissingOnly]).arg(MissingOnly)); + printText(tr(" %1, %2 \t\t\t Forces the recreation of all configuration files. This option implies the backup of the current settings.").arg(short_opts[Force]).arg(Force)); + printText(); + + printText(); + printText(tr("** The FILTER value in %1 option has the form type:pattern:mode. ").arg(FilterObjects)); + printText(tr(" * The `type' is the type of object to be filtered and accepts the following values (invalid types ignored): ")); + + QStringList list; + QString child_list; + + for(auto &type : BaseObject::getChildObjectTypes(ObjectType::Table)) + { + if(type == ObjectType::Column) + continue; + + list.append(BaseObject::getSchemaName(type)); + } + + list.sort(); + child_list = list.join(", "); + + QStringList fmt_types, lines, type_list = Catalog::getFilterableObjectNames(); + int i = 0; + + for(auto &type : type_list) + { + fmt_types.append(type); + i++; + if(i % 8 == 0 || i == type_list.size() - 1) + { + lines.append(QString(" > ") + fmt_types.join(", ")); + fmt_types.clear(); + } + } + printText(lines.join('\n')); + + printText(); + printText(tr(" * The `pattern' is the text pattern which is matched against the objects names.")); + printText(); + printText(tr(" * The `mode' is the way the pattern is matched. This one accepts two values: ")); + printText(tr(" > `%1' causes the pattern to be used as a wildcard string while matching objects names.").arg(UtilsNs::FilterWildcard)); + printText(tr(" > `%1' causes the pattern to be treated as a POSIX regular expression while matching objects names.").arg(UtilsNs::FilterRegExp)); + printText(); + printText(tr(" * The option %1 has effect only when used with %2 and will avoid discarding children of matched tables.").arg(ForceChildren).arg(OnlyMatching)); + printText(tr(" Other tables eventually imported which are dependencies of the matched objects will have their children discarded.")); + printText(tr(" The comma separated list of table children objects accepts the values:")); + printText(tr(" > %1").arg(child_list) ); + printText(tr(" > Use the special keyword `%1' to force all children objects.").arg(AllChildren) ); + printText(); + printText(tr(" * NOTES: all comparisons during filtering process are case insensitive.")); + printText(tr(" Using the filtering options may cause the importing of additional objects due to the automatic dependency resolution.")); + printText(); + printText(tr("** The diff process allows the usage all options related to the import operation.")); + printText(tr(" It also accepts the following export operation options: `%1', `%2'").arg(IgnoreDuplicates).arg(IgnoreErrorCodes)); + printText(); + printText(tr("** The partial diff operation will always force the options %1 and %2 = %3 for more reliable results.").arg(OnlyMatching).arg(ForceChildren).arg(AllChildren)); + printText(tr(" * The options %1 and %2 accepts the ISO8601 date/time format: yyyy-MM-dd hh:mm:ss").arg(StartDate).arg(EndDate)); + printText(); + printText(tr("** When running the diff using two databases (%1 and %2) there's the option to specify two separated connections/aliases.").arg(InputDb).arg(CompareTo)); + printText(tr(" If only one connection is set then it will be used to import the input database as well to retrieve the database used in the comparison.")); + printText(tr(" A second connection can be specified by appending a 1 to any connection configuration parameter listed above.")); + printText(tr(" This causes the connection to be associated to %1 exclusively.").arg(CompareTo)); + printText(); +} + +void PgModelerCliApp::listConnections() +{ + map::iterator itr=connections.begin(); + + if(connections.empty()) + printText(tr("There are no connections configured.")); + else + { + unsigned id=0; + + printText(tr("Available connections (alias : connection string)")); + + while(itr != connections.end()) + { + printText(QString("[") + QString::number(id++) + QString("] ") + itr->first + QString(" : ") + + itr->second->getConnectionString().replace(PasswordRegExp, PasswordPlaceholder)); + itr++; + } + + printText(); + } +} + +void PgModelerCliApp::parseOptions(attribs_map &opts) +{ + //Loading connections + if(opts.count(ListConns) || opts.count(ExportToDbms) || opts.count(ImportDb) || opts.count(Diff)) + { + conn_conf = new ConnectionsConfigWidget; + conn_conf->loadConfiguration(); + conn_conf->getConnections(connections, false); + } + //Loading general and relationship settings when exporting to image formats + else if(opts.count(ExportToPng) || opts.count(ExportToSvg)) + { + general_conf = new GeneralConfigWidget; + rel_conf = new RelationshipConfigWidget; + + general_conf->loadConfiguration(); + rel_conf->loadConfiguration(); + } + + //Creating the export/import/diff helpers when one of the operations are specified + if(opts.count(ExportToDbms) || opts.count(ExportToFile) || + opts.count(ExportToPng) || opts.count(ExportToSvg) || + opts.count(ExportToDict) || opts.count(ImportDb) || + opts.count(Diff)) + { + export_hlp = new ModelExportHelper; + import_hlp = new DatabaseImportHelper; + diff_hlp = new ModelsDiffHelper; + } + + if(opts.empty() || opts.count(Help)) + showMenu(); + else + { + QString curr_op_mode; + int exp_mode_cnt = 0, other_modes_cnt = 0; + bool fix_model = (opts.count(FixModel) > 0), + upd_mime = (opts.count(DbmMimeType) > 0), + import_db = (opts.count(ImportDb) > 0), + diff = (opts.count(Diff) > 0), + create_configs= (opts.count(CreateConfigs) > 0), + list_conns = (opts.count(ListConns) > 0), + export_dbms = (opts.count(ExportToDbms) > 0); + + for(auto &itr : accepted_opts) + { + if(itr.first == Attributes::Connection) + continue; + + if(opts.count(itr.first)) + { + curr_op_mode = itr.first; + + if(itr.first == ExportToFile || itr.first == ExportToPng || + itr.first == ExportToSvg || itr.first == ExportToDbms || + itr.first == ExportToDict) + exp_mode_cnt++; + else + other_modes_cnt++; + } + } + + if(opts.count(ZoomFactor)) + zoom=opts[ZoomFactor].toDouble()/static_cast(100); + + if(other_modes_cnt==0 && exp_mode_cnt==0) + throw Exception(tr("No operation mode was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if((exp_mode_cnt > 0 && (fix_model || upd_mime || import_db || diff || create_configs || list_conns)) || (exp_mode_cnt==0 && other_modes_cnt > 1)) + throw Exception(tr("Multiple operation modes were specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!fix_model && !upd_mime && exp_mode_cnt > 1) + throw Exception(tr("Multiple export mode was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!list_conns && !upd_mime && !import_db && !diff && !create_configs && !opts.count(Input)) + throw Exception(tr("No input file was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(import_db && !opts.count(InputDb)) + throw Exception(tr("No input database was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(ExportToDbms) && !upd_mime && !list_conns && !diff && !create_configs && !opts.count(Output)) + throw Exception(tr("No output file was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(ExportToDbms) && !upd_mime && !import_db && !list_conns && !create_configs && + opts.count(Input) && opts.count(Output) && + QFileInfo(opts[Input]).absoluteFilePath() == QFileInfo(opts[Output]).absoluteFilePath()) + throw Exception(tr("Input file must be different from output!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(ExportToDbms) && !opts.count(ConnAlias) && + (!opts.count(Host) || !opts.count(User) || !opts.count(Passwd) || !opts.count(InitialDb)) ) + throw Exception(tr("Incomplete connection information!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(ExportToPng) && (zoom < ModelWidget::MinimumZoom || zoom > ModelWidget::MaximumZoom)) + throw Exception(tr("Invalid zoom specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(upd_mime && opts[DbmMimeType]!=Install && opts[DbmMimeType]!=Uninstall) + throw Exception(tr("Invalid action specified to update mime option!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(create_configs && opts.count(Force) && opts.count(MissingOnly)) + throw Exception(tr("The options `%1' and `%2' can't be used together when handling configuration files!").arg(Force).arg(MissingOnly), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(diff) + { + if(!opts.count(Input) && !opts.count(InputDb)) + throw Exception(tr("No input file or database was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(Input) && opts.count(InputDb)) + throw Exception(tr("The input file and database can't be used at the same time!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(CompareTo)) + throw Exception(tr("No database to be compared was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(SaveDiff) && !opts.count(ApplyDiff)) + throw Exception(tr("No diff action (save or apply) was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(SaveDiff) && opts[Output].isEmpty()) + throw Exception(tr("No output file for the diff code was specified!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(PartialDiff) && !opts[Input].count() && (opts.count(StartDate) || opts.count(EndDate))) + throw Exception(tr("Date filters are allowed only on partial diff using an input model!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(PartialDiff) && opts.count(FilterObjects) && (opts.count(StartDate) || opts.count(EndDate))) + throw Exception(tr("Date filters and object filters can't be used together!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(PartialDiff) && !opts.count(FilterObjects) && !opts.count(StartDate) && !opts.count(EndDate)) + throw Exception(tr("Partial diff enabled but no object filter was provided!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + // For partial diff we force the --only-matching option and --force-children = all + if(opts.count(PartialDiff)) + { + opts[ForceChildren] = AllChildren; + opts[OnlyMatching] = ""; + } + + // Validating the date formats in the provided start/end dates + QDateTime *dates[2] = { &start_date, &end_date }; + QStringList dt_params = { StartDate, EndDate }; + + for(int idx = 0; idx < 2; idx++) + { + if(opts.count(dt_params[idx])) + { + *dates[idx] = QDateTime::fromString(opts[dt_params[idx]], Qt::ISODate); + + if(!dates[idx]->isValid()) + throw Exception(tr("Invalid date format `%1' in option `%2'!").arg(opts[dt_params[idx]]).arg(dt_params[idx]), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + } + + /* If any of the dates are correctly parsed we need to force + * the signature name matching, the forced filtering of all table children objects + * and the only-matching option, so the objects can be correctly retrieved from + * the destination database */ + if(start_date.isValid() || end_date.isValid()) + { + parsed_opts.erase(MatchByName); + parsed_opts[ForceChildren] = AllChildren; + parsed_opts[OnlyMatching] = ""; + } + } + + //Converting input and output files to absolute paths to avoid that they are read/written on the app's working dir + if(opts.count(Input)) + opts[Input]=QFileInfo(opts[Input]).absoluteFilePath(); + + if(opts.count(Output)) + opts[Output]=QFileInfo(opts[Output]).absoluteFilePath(); + + /* Special treatment for filter parameters: + * Since it can be specified several filter parameter we need to join + * everything in a single string list so it can be passed to the import helper correctly */ + if(opts.count(FilterObjects)) + { + opts.erase(FilterObjects); + + for(auto &op : opts) + { + if(op.first.contains(FilterObjects)) + obj_filters.append(op.second); + } + } + + /* Performing a final validation on the parsed options which consists + * in check if all provided options are compatible with the operation mode selected */ + QStringList acc_opts = accepted_opts[curr_op_mode]; + QString long_opt; + + // Diff, import and export (to DBMS) share the same connection options + if(diff || import_db || export_dbms) + acc_opts.append(accepted_opts[Attributes::Connection]); + + // Diff also accepts all import parameters + if(diff) + acc_opts.append(accepted_opts[ImportDb]); + + for(auto &itr : opts) + { + long_opt = itr.first; + + if(long_opt == curr_op_mode || long_opt == Silent) + continue; + + /* Before validate the option we need to remove any appended number to the option name + * This happens for options related to objects filters and connections */ + long_opt.remove(QRegExp("[0-9]+$")); + + if(!acc_opts.contains(long_opt)) + throw Exception(tr("The option `%1' is not accepted by the operation mode `%2'!").arg(long_opt).arg(curr_op_mode), + ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + + parsed_opts = opts; + } +} + +int PgModelerCliApp::exec() +{ + try + { + if(!parsed_opts.empty()) + { + showVersionInfo(); + + if(parsed_opts.count(ListConns)) + listConnections(); + else if(parsed_opts.count(FixModel)) + fixModel(); + else if(parsed_opts.count(DbmMimeType)) + updateMimeType(); + else if(parsed_opts.count(CreateConfigs)) + createConfigurations(); + else if(parsed_opts.count(ImportDb)) + importDatabase(); + else if(parsed_opts.count(Diff)) + diffModelDatabase(); + else + exportModel(); + } + + return 0; + } + catch(Exception &e) + { + throw e; + } +} + +void PgModelerCliApp::updateProgress(int progress, QString msg, ObjectType) +{ + if(progress > 0) + printMessage(QString("[%1%] ").arg(progress > 100 ? 100 : progress) + msg); + else + printMessage(msg); +} + +void PgModelerCliApp::printIgnoredError(QString err_cod, QString err_msg, QString cmd) +{ + printText(); + printText(tr("** Error code `%1' found and ignored. Proceeding with export.").arg(err_cod)); + printText(tr("** Command: %1").arg(cmd)); + printText(err_msg); + printText(); +} + +void PgModelerCliApp::handleObjectAddition(BaseObject *object) +{ + BaseGraphicObject *graph_obj=dynamic_cast(object); + + if(graph_obj) + { + ObjectType obj_type=graph_obj->getObjectType(); + QGraphicsItem *item=nullptr; + + switch(obj_type) + { + case ObjectType::Table: + item=new TableView(dynamic_cast(graph_obj)); + break; + + case ObjectType::ForeignTable: + item=new TableView(dynamic_cast(graph_obj)); + break; + + case ObjectType::View: + item=new GraphicalView(dynamic_cast(graph_obj)); + break; + + case ObjectType::Relationship: + case ObjectType::BaseRelationship: + item=new RelationshipView(dynamic_cast(graph_obj)); + break; + + case ObjectType::Schema: + item=new SchemaView(dynamic_cast(graph_obj)); + break; + + default: + item=new StyledTextboxView(dynamic_cast(graph_obj)); + break; + } + + scene->addItem(item); + + if(BaseTable::isBaseTable(obj_type)) + dynamic_cast(graph_obj->getSchema())->setModified(true); + } +} + + +void PgModelerCliApp::handleObjectRemoval(BaseObject *object) +{ + BaseGraphicObject *graph_obj=dynamic_cast(object); + + if(graph_obj) + { + scene->removeItem(dynamic_cast(graph_obj->getOverlyingObject())); + + //Updates the parent schema if the removed object were a table or view + if(graph_obj->getSchema() && BaseTable::isBaseTable(graph_obj->getObjectType())) + dynamic_cast(graph_obj->getSchema())->setModified(true); + } +} + + +void PgModelerCliApp::extractObjectXML() +{ + QString buf, lin, def_xml, end_tag, pgmodeler_ver; + QTextStream ts; + QRegExp regexp(QString("^(\\<\\?xml)(.)*(\\<%1)( )*").arg(Attributes::DbModel)), + + //[schema].[func_name](...OUT [type]...) + func_signature=QRegExp(QString("(\")(.)+(\\.)(.)+(\\()(.)*(OUT )(.)+(\\))(\")")), + + //[,]OUT [schema].[type] + out_param=QRegExp(QString("(,)?(OUT )([a-z]|[0-9]|(\\.)|(\\_)|(\\-)|( )|(\\[)|(\\])|("))+((\\()([0-9])+(\\)))?")); + int start=-1, end=-1; + bool open_tag=false, close_tag=false, is_rel=false, short_tag=false, end_extract_rel=false, is_change_log=false; + + printMessage(tr("Extracting objects' XML...")); + + buf.append(UtilsNs::loadFile(parsed_opts[Input])); + + // Extracting pgModeler version from input model + QRegExp ver_expr(AttributeExpr.arg(Attributes::PgModelerVersion)); + start = ver_expr.indexIn(buf); + model_version = buf.mid(start, ver_expr.matchedLength()); + model_version.remove(Attributes::PgModelerVersion); + model_version.remove(QRegExp("(\\\"|\\=| )+")); + + if(!model_version.contains(QRegExp("(\\d\\.\\d\\.\\d)((\\-)(alpha|beta)(\\d))?"))) + { + printMessage(tr("** WARNING: Could't determine the pgModeler version in which the input model was created!")); + printMessage(tr(" Some fix actions that depend on the model version will not be applied!")); + model_version.clear(); + } + + //Check if the file contains a valid header (for .dbm file) + start=regexp.indexIn(buf); + + if(start < 0) + throw Exception(tr("Invalid input file! It seems that is not a pgModeler generated model or the file is corrupted!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + else + { + //Extracting layers informations from the tag + QRegExp dbm_regexp = QRegExp(TagExpr.arg(Attributes::DbModel)), + db_end_regexp = QRegExp(EndTagExpr.arg(Attributes::Database)); + int attr_start =-1, attr_end = -1, dbm_start = dbm_regexp.indexIn(buf); + QString aux_buf = buf.mid(dbm_start, buf.indexOf(db_end_regexp) - dbm_start), + layers, active_layers, attr_expr = QString("(%1)( )*(=)(\")"); + QList act_layers_ids; + + //Layers names + attr_start = aux_buf.indexOf(Attributes::Layers); + attr_end = aux_buf.indexOf(Attributes::ActiveLayers); + layers = aux_buf.mid(attr_start, attr_end - attr_start); + layers.remove(QRegExp(attr_expr.arg(Attributes::Layers))); + layers.remove('"'); + model->setLayers(layers.trimmed().split(',', QtCompat::SkipEmptyParts)); + + //Active layers + attr_start = attr_end; + attr_end = aux_buf.indexOf('>', attr_start); + active_layers = aux_buf.mid(attr_start, attr_end - attr_start); + active_layers.remove(QRegExp(attr_expr.arg(Attributes::ActiveLayers))); + active_layers.remove('"'); + + for(auto id : active_layers.trimmed().split(';', QtCompat::SkipEmptyParts)) + act_layers_ids.push_back(id.toUInt()); + + model->setActiveLayers(act_layers_ids); + + //Remove the header entry from buffer + buf.remove(start, regexp.matchedLength()+1); + + //Checking if the header ends on a role declaration + QRegExp role_regexp = QRegExp(QString("(<%1)(.)*(<\\/%2>)").arg(Attributes::Role).arg(Attributes::Role)); + end = buf.indexOf(role_regexp); + + // If we found role declarations we clear the header until there + if(end >= 0) + buf.remove(0, end); + else + // Instead, we clear the header until the starting of database declaration + buf.remove(0, buf.indexOf(QString("<%1").arg(Attributes::Database))); + + buf.remove(QString("<\\%1>").arg(Attributes::DbModel)); + ts.setString(&buf); + + //Extracts the objects xml line by line + while(!ts.atEnd()) + { + lin=ts.readLine(); + + /* Collecting changelog entries if present and storing in a separated buffer + * so it can be restored in the fixed model during objects' reconstruction */ + if(!is_change_log && lin.contains(TagExpr.arg(Attributes::Changelog))) + is_change_log = true; + + if(is_change_log) + { + changelog.append(lin); + + if(lin.contains(EndTagExpr.arg(Attributes::Changelog))) + is_change_log = false; + else + continue; + } + + /* Special case for empty tags like , they will be converted to + in order to be correctly extracted further. Currently only language has this + behaviour, so additional object may be added in the future. */ + if(lin.contains(QString("<%1").arg(BaseObject::getSchemaName(ObjectType::Language)))) + { + lin=lin.simplified(); + + if(lin.contains(QString("/>"))) + lin.replace(QString("/>"), QString(">").arg(BaseObject::getSchemaName(ObjectType::Language))); + } + /* Special case for function signatures. In previous releases, the function's signature was wrongly + including OUT parameters and according to docs they are not part of the signature, so it is needed + to remove them if the current line contains a valid signature with parameters. */ + else if(lin.contains(func_signature)) + lin.remove(out_param); + + if(is_rel && (((short_tag && lin.contains(QString("/>"))) || + (lin.contains(QString("[a-z]+")) && !containsRelAttributes(lin))))) + open_tag=close_tag=true; + else + { + //If the line contains an objects open tag + if(lin.contains(QRegExp("^(((\n)|(\t))*(<))")) && !open_tag) + { + //Check the flag indicating an open tag + open_tag=true; + + start=lin.indexOf('<'); + end=lin.indexOf(' '); + if(end < 0) end=lin.indexOf('>'); + + //Configures the end tag with the same word extracted from open tag + end_tag=lin.mid(start, end-start+1).trimmed(); + end_tag.replace(QString("<"),QString("')) + end_tag+=QString(">"); + + /* Checking if the line start a relationship. Relationships are treated + a little different because they can be empty or + contain open and close tags */ + is_rel=lin.contains(Attributes::Relationship); + + if(is_rel) + { + end_extract_rel=short_tag=false; + + while(!end_extract_rel && !ts.atEnd()) + { + def_xml+=lin + QString("\n"); + lin=lin.trimmed(); + + //Checking if the current line is the end of a short-tag relationship + if(!short_tag && !lin.startsWith('<') && lin.endsWith(QString("/>"))) + short_tag=true; + + end_extract_rel=((!short_tag && lin.contains(end_tag)) || short_tag); + + if(!end_extract_rel) + lin=ts.readLine(); + } + + close_tag=true; + } + else + close_tag=lin.contains(end_tag); + } + else if(open_tag && lin.contains(end_tag)) + close_tag=true; + } + + if(!is_rel && !lin.isEmpty()) + def_xml+=lin + QString("\n"); + else if(lin.isEmpty()) + def_xml+=QString("\n"); + + //If the iteration reached the end of the object's definition + if(open_tag && close_tag) + { + //Pushes the extracted definition to the list (only if not empty) + if(def_xml!=QString("\n")) + objs_xml.push_back(def_xml); + + def_xml.clear(); + open_tag=close_tag=is_rel=false; + } + } + } +} + +void PgModelerCliApp::recreateObjects() +{ + QStringList fail_objs, constr, list; + QString xml_def, aux_def, start_tag = "<%1", end_tag = "", aux_tag, type_tag = " types={ ObjectType::Index, ObjectType::Trigger, ObjectType::Rule }; + attribs_map attribs, fmt_ext_names; + bool use_fail_obj=false; + unsigned tries=0, max_tries=parsed_opts[FixTries].toUInt(); + int start_pos=-1, end_pos=-1, len=0, obj_id = 0, obj_cnt = objs_xml.count(); + + printMessage(tr("Recreating objects...")); + + if(max_tries==0) + max_tries=1; + + model->createSystemObjects(false); + + while(!objs_xml.isEmpty()) + { + //If there are failed objects and the flag is set + if(use_fail_obj && !fail_objs.isEmpty()) + { + xml_def=fail_objs.front(); + fail_objs.pop_front(); + use_fail_obj=false; + } + else + { + xml_def=objs_xml.front(); + objs_xml.pop_front(); + fixObjectAttributes(xml_def); + } + + /* Replacing the tags [restartParser(); + xmlparser->loadXMLBuffer(xml_def); + obj_type=BaseObject::getObjectType(xmlparser->getElementName()); + + xmlparser->getElementAttributes(attribs); + + if(obj_type==ObjectType::Database) + model->configureDatabase(attribs); + else + { + if(obj_type==ObjectType::Table) + { + //Before create a table extract it's foreign keys + list=extractForeignKeys(xml_def); + + /* If fks were extracted insert them on the main constraints list + * and restarts the XMLParser with the modified buffer */ + if(!list.isEmpty()) + { + constr.append(list); + xmlparser->restartParser(); + xmlparser->loadXMLBuffer(xml_def); + } + } + + //Discarding fk relationships + if(obj_type!=ObjectType::Relationship || + (obj_type==ObjectType::Relationship && !xml_def.contains(QString("\"%1\"").arg(Attributes::RelationshipFk)))) + { + object=model->createObject(obj_type); + + if(object) + { + if(!dynamic_cast(object) && obj_type!=ObjectType::Relationship && obj_type!=ObjectType::BaseRelationship) + model->addObject(object); + + printMessage(QString("[%1%] %2") + .arg(static_cast((++obj_id/static_cast(obj_cnt)) * 100)) + .arg(tr("Object recreated: `%1' (%2)").arg(object->getName(true), object->getTypeName()))); + + /* Special case for extensions: + * Before pgModeler 0.9.4-alpha1 the types handled by extension (for example hstore, ltree, etc) were + * registered in the PgSqlType as user-defined data type without their schemas names prepended. This + * was causing lot of troubles importing databases in which extension data types were being used. The + * solution was to adjust the extension type names in such a way to prepend schema names. So here we + * store the schema-qualified extension name in a special map where the key is the name of the extension + * without the schema name, this way search the tags [getObjectType() == ObjectType::Extension && dynamic_cast(object)->handlesType()) + fmt_ext_names[object->getName()] = object->getName(true, true); + } + + //For each sucessful created object the method will try to create a failed one + use_fail_obj=(!fail_objs.isEmpty()); + } + + /* Additional step to extract indexes/triggers/rules from within tables/views + * and putting their xml on the list of object to be created */ + if(BaseTable::isBaseTable(obj_type) && xml_def.contains(QRegExp("(<)(index|trigger|rule)"))) + { + for(ObjectType type : types) + { + do + { + //Checking where the object starts and ends + aux_tag=start_tag.arg(BaseObject::getSchemaName(type)); + start_pos=xml_def.indexOf(aux_tag); + end_pos=(start_pos >=0 ? xml_def.indexOf(end_tag.arg(BaseObject::getSchemaName(type))) : -1); + + if(start_pos >=0 && end_pos >= 0) + { + //Extracts the xml code + len=(end_pos - start_pos) + end_tag.arg(BaseObject::getSchemaName(type)).length() + 1; + aux_def=xml_def.mid(start_pos, len); + + //Remove the code from original table's definition + xml_def.remove(start_pos, len); + + //If the extract object doesn't contains the 'table=' attribute it'll be added. + if(!aux_def.contains("table=")) + { + aux_def.replace(aux_tag, QString("%1 table=\"%2\"").arg(aux_tag).arg(object->getName(true))); + aux_def=XmlParser::convertCharsToXMLEntities(aux_def); + } + + objs_xml.push_back(aux_def); + } + } + while(start_pos >= 0); + } + } + } + } + catch(Exception &e) + { + if(obj_type!=ObjectType::Database) + { + fail_objs.push_back(xml_def); + printText(tr("** WARNING: Failed to recreate an object!")); + } + else + throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } + + if(objs_xml.isEmpty() && (!fail_objs.isEmpty() || !constr.isEmpty())) + { + tries++; + + //If the maximum creation tries reaches the maximum value + if(tries > max_tries) + { + //Outputs the code of the objects that wasn't created + printText(); + printText(tr("** Object(s) that couldn't fixed: ")); + + while(!fail_objs.isEmpty()) + { + printText(fail_objs.front()); + fail_objs.pop_front(); + } + + break; + } + else + { + printMessage(tr("** WARNING: There are objects that maybe can't be fixed. Trying again... (tries %1/%2)").arg(tries).arg(max_tries)); + model->validateRelationships(); + objs_xml=fail_objs; + objs_xml.append(constr); + fail_objs.clear(); + constr.clear(); + } + } + } + + // Fixing the roles memberships. + Role *role = nullptr, *mem_role = nullptr; + bool member_fixed = false; + + for(auto &rl : member_roles) + { + role = model->getRole(rl.first); + + if(!role) + { + printMessage(tr("** WARNING: Could not find the role `%1'! Ignoring it...").arg(rl.first)); + continue; + } + + for(auto &name : rl.second) + { + mem_role = model->getRole(name); + + if(!mem_role) + { + printMessage(tr("** WARNING: Could not find the role `%1' of `%2`! Igorning it...").arg(name, rl.first)); + continue; + } + + role->addRole(Role::MemberRole, mem_role); + member_fixed = true; + } + } + + if(member_fixed) + { + printMessage(tr("** WARNING: Roles memberships were fixed but their creation order is not guaranteed!")); + printMessage(tr(" It may be necessary to run the fix tool again but now on the file `%1'.").arg(parsed_opts[Output])); + } + + // Reconstructing the persisted change log if present + if(!changelog.isEmpty()) + { + model->setPersistedChangelog(true); + xmlparser->loadXMLBuffer(changelog); + + if(xmlparser->accessElement(XmlParser::ChildElement)) + { + do + { + xmlparser->getElementAttributes(attribs); + model->addChangelogEntry(attribs[Attributes::Signature], attribs[Attributes::Type], + attribs[Attributes::Action], attribs[Attributes::Date]); + } + while(xmlparser->accessElement(XmlParser::NextElement)); + } + } +} + +void PgModelerCliApp::fixObjectAttributes(QString &obj_xml) +{ + //Placing objects , , outside of
+ if(!obj_xml.startsWith(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Tablespace))) && + obj_xml.startsWith(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Table)))) + { + int start_idx=-1, end_idx=-1, len=0; + ObjectType obj_types[3]={ ObjectType::Rule, ObjectType::Trigger, ObjectType::Index }; + QString curr_tag, curr_end_tag, def, tab_name, sch_name, + name_attr=QString("name=\""), + sch_name_attr=TagExpr.arg(BaseObject::getSchemaName(ObjectType::Schema)) + QString(" ") + name_attr; + + //Extracting the table's name + start_idx=obj_xml.indexOf(name_attr); + end_idx=obj_xml.indexOf("\"", start_idx + name_attr.size()); + tab_name=obj_xml.mid(start_idx, end_idx - start_idx).remove(name_attr); + + //Extracting the table's schema name + start_idx=obj_xml.indexOf(sch_name_attr); + end_idx=obj_xml.indexOf('"', start_idx + sch_name_attr.size()); + sch_name=obj_xml.mid(start_idx, end_idx - start_idx).remove(sch_name_attr); + + //Configuring the table=[name] attribute to be included on rule objects + tab_name=QString("table=\"%1.%2\"").arg(sch_name).arg(tab_name); + + for(unsigned idx=0; idx < 3; idx++) + { + curr_tag=TagExpr.arg(BaseObject::getSchemaName(obj_types[idx])); + curr_end_tag=EndTagExpr.arg(BaseObject::getSchemaName(obj_types[idx])) + QString(">"); + start_idx=obj_xml.indexOf(curr_tag); + + while(start_idx >=0) + { + end_idx=obj_xml.indexOf(curr_end_tag); + len=(end_idx - start_idx) + curr_end_tag.size(); + def=obj_xml.mid(start_idx, len) + QString("\n\n"); + obj_xml.remove(start_idx, len); + + //If the object is a rule include the table attribute + if(def.startsWith(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Rule)))) + { + start_idx=def.indexOf('>'); + def.replace(start_idx, 1, QString(" ") + tab_name + QString(">")); + } + + start_idx=obj_xml.indexOf(curr_tag); + + if(!def.isEmpty()) + //Puts the object's defintion to the list in order to be evaluated in the main process + objs_xml.push_back(def); + } + } + } + + //Remove recheck attribute from tags. + if(obj_xml.contains(TagExpr.arg(Attributes::Element))) + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("recheck")))); + + //Remove values greater-op, less-op, sort-op or sort2-op from ref-type attribute from tags. + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Operator)))) + { + obj_xml.remove(QString("greater-op")); + obj_xml.remove(QString("less-op")); + obj_xml.remove(QString("sort-op")); + obj_xml.remove(QString("sort2-op")); + } + + //Replacing attribute owner by onwer-col for sequences + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Sequence)))) + obj_xml.replace(QRegExp(QString("(%1)( )*(=)(\")").arg(Attributes::Owner)), QString("%1 = \"").arg(Attributes::OwnerColumn)); + + /* Remove sysid attribute from tags and storing the referenced roles (ref-roles) + * for later re-assignment. */ + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Role)))) + { + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("sysid")))); + + QRegExp ref_roles_expr = QRegExp(QString("(\\<%1)(.)+(%2)( )*(=)(\")(%3)(\")(.)+(\\/\\>)").arg(Attributes::Roles, Attributes::RoleType, Attributes::Refer)); + int pos = ref_roles_expr.indexIn(obj_xml); + + if(pos >= 0) + { + QString buf = obj_xml.mid(pos, ref_roles_expr.matchedLength()), + name_attr = QString("name=\""), role_name; + int start_idx = 0, end_idx = 0; + + // Extracting the role name + start_idx = obj_xml.indexOf(name_attr); + end_idx = obj_xml.indexOf("\"", start_idx + name_attr.size()); + role_name = obj_xml.mid(start_idx, end_idx - start_idx).remove(name_attr); + + // Removing the element + obj_xml.remove(pos, ref_roles_expr.matchedLength()); + + // Retrieve the name of the ref-roles + buf.remove(QRegExp("^(.)+(names=\")")); + buf.remove(buf.indexOf("\""), buf.size()); + + /* Storing the association between the current role and the ref-roles + * in a map for further processing */ + for(auto &rl_name : buf.split(',', QtCompat::SkipEmptyParts)) + member_roles[rl_name].append(role_name); + } + } + + //Replace tag by on tags. + if(obj_xml.contains(TagExpr.arg(QString("usertype")))) + { + obj_xml.replace(TagExpr.arg(Attributes::Parameter), TagExpr.arg(Attributes::TypeAttribute)); + obj_xml.replace(EndTagExpr.arg(Attributes::Parameter), EndTagExpr.arg(Attributes::TypeAttribute)); + + // Fixing the enumeration type labels + if(!model_version.isEmpty() && model_version <= "0.9.4-beta1") + { + /* Until pgModeler 0.9.3, enum labels separators where commas. + * In pgModeler 0.9.4, enum labels separators where UtilsNs::DataSeparator */ + QString sep = (model_version == "0.9.4-beta1" ? UtilsNs::DataSeparator : ","), + values, labels; + QRegExp enum_start_expr("(" + TagExpr.arg(Attributes::EnumType) + ")( )*(values)( )*(=)( )*(\\\")"), + enum_end_expr("(\\\")( )*(\\/>)"), + enum_tag_expr("(" + TagExpr.arg(Attributes::EnumType) + ")(.)+(/>)"); + int start = -1, end = -1; + + // Extracting the values of the tag + start = enum_start_expr.indexIn(obj_xml) + enum_start_expr.matchedLength(); + end = enum_end_expr.indexIn(obj_xml, start); + values = obj_xml.mid(start, end - start); + + if(!values.isEmpty()) + { + // Converting each value extract into a separated tag + for(auto &label : values.split(sep, QtCompat::SkipEmptyParts)) + labels.append(QString("\t<%1 label=\"%2\"/>\n").arg(Attributes::EnumType, label)); + + obj_xml.replace(enum_tag_expr, labels); + } + } + } + + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Relationship)))) + { + //Remove auto-sufix, src-sufix, dst-sufix, col-indexes, constr-indexes, attrib-indexes from tags. + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("auto-sufix")))); + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("src-sufix")))); + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("dst-sufix")))); + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("col-indexes")))); + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("constr-indexes")))); + obj_xml.remove(QRegExp(AttributeExpr.arg(QString("attrib-indexes")))); + + obj_xml.replace(QString("line-color"), Attributes::CustomColor); + } + + //Renaming the tag to on indexes + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Index)))) + { + obj_xml.replace(TagExpr.arg(Attributes::Condition), TagExpr.arg(Attributes::Predicate)); + obj_xml.replace(EndTagExpr.arg(Attributes::Condition), EndTagExpr.arg(Attributes::Predicate)); + } + + //Renaming the attribute default to default-value on domain + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Domain)))) + obj_xml.replace(Attributes::Default, Attributes::DefaultValue); + + //Renaming the tag to + if(obj_xml.contains(TagExpr.arg(QString("grant")))) + { + obj_xml.replace(TagExpr.arg(QString("grant")), TagExpr.arg(BaseObject::getSchemaName(ObjectType::Permission))); + obj_xml.replace(EndTagExpr.arg(QString("grant")), EndTagExpr.arg(BaseObject::getSchemaName(ObjectType::Permission))); + } + + //Replace the constraint attribute and tag expression by constraint tag in . + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Domain))) && + obj_xml.contains(TagExpr.arg(Attributes::Expression))) + { + int start_idx=-1, end_idx=-1; + QRegExp regexp = QRegExp(AttributeExpr.arg(Attributes::Constraint)); + QString constr_name; + + regexp.indexIn(obj_xml); + constr_name = regexp.capturedTexts().at(0); + constr_name.remove(QString("%1=\"").arg(Attributes::Constraint)); + constr_name.remove(constr_name.length() - 1, 1); + + obj_xml.remove(QRegExp(AttributeExpr.arg(Attributes::Constraint))); + + start_idx = obj_xml.indexOf(TagExpr.arg(Attributes::Expression)); + obj_xml.insert(start_idx, QString("\n\t\n\t\t").arg(constr_name)); + + end_idx = obj_xml.indexOf(EndTagExpr.arg(Attributes::Expression)); + obj_xml.insert(end_idx + EndTagExpr.arg(Attributes::Expression).length() + 1, QString("\n\t\n")); + } + + //Replace the deprecated attribute hide-ext-attribs="false|true" from
and by collapse-mode="0|1" + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Table))) || + obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::View)))) + { + obj_xml.replace(QString("%1=\"false\"").arg(Attributes::HideExtAttribs), QString("%1=\"0\"").arg(Attributes::CollapseMode)); + obj_xml.replace(QString("%1=\"true\"").arg(Attributes::HideExtAttribs), QString("%1=\"1\"").arg(Attributes::CollapseMode)); + } + + //Remove the usage of IN keyword in functions' signatures since it is the default if absent + QRegExp regexp = QRegExp(AttributeExpr.arg(Attributes::Signature)); + int sig_idx = regexp.indexIn(obj_xml), len = 0; + QString signature, in_keyw = QString("IN "); + + while(sig_idx >= 0) + { + signature = obj_xml.mid(sig_idx, regexp.matchedLength()); + len = signature.length(); + + if(!signature.contains(in_keyw)) + { + sig_idx = regexp.indexIn(obj_xml, sig_idx + len); + continue; + } + + signature.remove(in_keyw); + obj_xml.remove(sig_idx, len); + obj_xml.insert(sig_idx, signature); + sig_idx = regexp.indexIn(obj_xml, sig_idx + len); + } + + //Rename the attribute layer to layers + if(obj_xml.contains(QRegExp("(layer)( )*(=)"))) + obj_xml.replace("layer", Attributes::Layers); + + //Fix the references to op. classes and families if needed + fixOpClassesFamiliesReferences(obj_xml); +} + +void PgModelerCliApp::fixOpClassesFamiliesReferences(QString &obj_xml) +{ + ObjectType ref_obj_type; + + if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Index))) || + obj_xml.contains(QRegExp(QString("(%1)(.)+(type=)(\")(%2)(\")") + .arg(TagExpr.arg(BaseObject::getSchemaName(ObjectType::Constraint))) + .arg(Attributes::ExConstr)))) + ref_obj_type=ObjectType::OpClass; + else if(obj_xml.contains(TagExpr.arg(BaseObject::getSchemaName(ObjectType::OpClass)))) + ref_obj_type=ObjectType::OpFamily; + else + return; + + QString ref_obj_name=BaseObject::getSchemaName(ref_obj_type); + if(!obj_xml.contains(TagExpr.arg(ref_obj_name))) + return; + + QString obj_name, aux_obj_name, signature=QString("%1 USING %2"); + QRegExp sign_regexp=QRegExp(AttributeExpr.arg(QString("signature"))); + QStringList index_types; + int pos=0; + + obj_xml.replace(TagExpr.arg(ref_obj_name) + QString(" name="), + TagExpr.arg(ref_obj_name) + QString(" signature=")); + + index_types = IndexingType::getTypes(); + + do + { + pos=sign_regexp.indexIn(obj_xml, pos); + + if(pos >= 0) + { + //Extracting the signature attribute + obj_name=obj_xml.mid(pos, sign_regexp.matchedLength()); + + //Removing useless portions signature=" in order to retrive only the object's name + obj_name.remove(QRegExp("(signature)( )*(=)")); + obj_name.remove('"'); + + //Transforming xml entity for quote into the char + obj_name.replace(XmlParser::CharQuot, QString("\"")); + + for(auto &idx_type : index_types) + { + //Building a name by appe + aux_obj_name=signature.arg(obj_name).arg(idx_type); + + if(model->getObjectIndex(aux_obj_name, ref_obj_type) >= 0) + { + //Replacing the old signature with the corrected form + aux_obj_name.replace(QString("\""), XmlParser::CharQuot); + obj_xml.replace(pos, sign_regexp.matchedLength(), QString("signature=\"%1\"").arg(aux_obj_name)); + break; + } + } + + pos+=sign_regexp.matchedLength(); + } + } + while(pos >= 0); +} + +void PgModelerCliApp::fixModel() +{ + printMessage(tr("Starting model fixing...")); + printMessage(tr("Loading input file: %1").arg(parsed_opts[Input])); + printMessage(tr("Fixed model file: %1").arg(parsed_opts[Output])); + + extractObjectXML(); + recreateObjects(); + + printMessage(tr("Updating relationships...")); + model->updateTablesFKRelationships(); + + printMessage(tr("Saving fixed output model...")); + model->saveModel(parsed_opts[Output], SchemaParser::XmlDefinition); + + printMessage(tr("Model successfully fixed!")); +} + +void PgModelerCliApp::loadModel() +{ + //Create the systems objects on model before loading it + model->createSystemObjects(false); + + //Load the model file + model->loadModel(parsed_opts[Input]); + + /* The scene object is created only when some options are used + * so we need to check it if is not null to avoid segfaults */ + if(scene) + { + scene->blockSignals(true); + + scene->addLayers(model->getLayers(), false); + scene->setActiveLayers(model->getActiveLayers()); + scene->setLayerColors(ObjectsScene::LayerNameColor, model->getLayerNameColors()); + scene->setLayerColors(ObjectsScene::LayerRectColor, model->getLayerRectColors()); + scene->setLayerNamesVisible(model->isLayerNamesVisible()); + scene->setLayerRectsVisible(model->isLayerRectsVisible()); + + if(model->isLayerRectsVisible()) + model->setObjectsModified({ ObjectType::Schema }); + + scene->blockSignals(false); + } +} + +void PgModelerCliApp::exportModel() +{ + printMessage(tr("Starting model export...")); + printMessage(tr("Loading input file: %1").arg(parsed_opts[Input])); + + loadModel(); + + //Export to PNG + if(parsed_opts.count(ExportToPng)) + { + printMessage(tr("Export to PNG image: %1").arg(parsed_opts[Output])); + + export_hlp->exportToPNG(scene, parsed_opts[Output], zoom, + parsed_opts.count(ShowGrid) > 0, + parsed_opts.count(ShowDelimiters) > 0, + parsed_opts.count(PageByPage) > 0); + } + //Export to SVG + else if(parsed_opts.count(ExportToSvg)) + { + printMessage(tr("Export to SVG file: %1").arg(parsed_opts[Output])); + + export_hlp->exportToSVG(scene, parsed_opts[Output], + parsed_opts.count(ShowGrid) > 0, + parsed_opts.count(ShowDelimiters) > 0); + } + //Export to SQL file + else if(parsed_opts.count(ExportToFile)) + { + printMessage(tr("Export to SQL script file: %1").arg(parsed_opts[Output])); + export_hlp->exportToSQL(model, parsed_opts[Output], parsed_opts[PgSqlVer], parsed_opts.count(Split) > 0); + } + //Export data dictionary + else if(parsed_opts.count(ExportToDict)) + { + printMessage(tr("Export to data dictionary: %1").arg(parsed_opts[Output])); + export_hlp->exportToDataDict(model, parsed_opts[Output], + parsed_opts.count(NoIndex) == 0, + parsed_opts.count(Split) > 0); + } + //Export to DBMS + else + { + printMessage(tr("Export to DBMS: %1").arg(connection.getConnectionString().replace(PasswordRegExp, PasswordPlaceholder))); + + if(parsed_opts.count(IgnoreErrorCodes)) + export_hlp->setIgnoredErrors(parsed_opts[IgnoreErrorCodes].split(',')); + + export_hlp->exportToDBMS(model, connection, parsed_opts[PgSqlVer], + parsed_opts.count(IgnoreDuplicates) > 0, + parsed_opts.count(DropDatabase) > 0, + parsed_opts.count(DropObjects) > 0, + parsed_opts.count(Simulate) > 0, + parsed_opts.count(UseTmpNames) > 0); + } + + printMessage(tr("Export successfully ended!\n")); +} + +void PgModelerCliApp::importDatabase() +{ + printMessage(tr("Starting database import...")); + printMessage(tr("Input database: %1").arg(connection.getConnectionId(true, true))); + + ModelWidget *model_wgt = new ModelWidget; + + importDatabase(model_wgt->getDatabaseModel(), connection); + model_wgt->rearrangeSchemasInGrid(); + + printMessage(tr("Saving the imported database to file...")); + + model_wgt->getDatabaseModel()->saveModel(parsed_opts[Output], SchemaParser::XmlDefinition); + + printMessage(tr("Import successfully ended!\n")); + + delete model_wgt; +} + +void PgModelerCliApp::importDatabase(DatabaseModel *model, Connection conn) +{ + try + { + map> obj_oids; + map> col_oids; + Catalog catalog; + QString db_oid; + QStringList force_tab_objs; + bool imp_sys_objs = (parsed_opts.count(ImportSystemObjs) > 0), + imp_ext_objs = (parsed_opts.count(ImportExtensionObjs) > 0); + + if(parsed_opts[ForceChildren] == AllChildren) + { + for(auto &type : BaseObject::getChildObjectTypes(ObjectType::Table)) + { + if(type == ObjectType::Column) + continue; + + force_tab_objs.append(BaseObject::getSchemaName(type)); + } + } + else + force_tab_objs = parsed_opts[ForceChildren].split(',', QtCompat::SkipEmptyParts); + + catalog.setConnection(conn); + catalog.setQueryFilter(Catalog::ListAllObjects | Catalog::ExclBuiltinArrayTypes | + (!imp_ext_objs ? Catalog::ExclExtensionObjs : 0) | + (!imp_sys_objs ? Catalog::ExclSystemObjs : 0)); + + catalog.setObjectFilters(obj_filters, parsed_opts.count(OnlyMatching) > 0, + parsed_opts.count(MatchByName) == 0, force_tab_objs); + catalog.getObjectsOIDs(obj_oids, col_oids, {{Attributes::FilterTableTypes, Attributes::True}}); + + db_oid = catalog.getObjectOID(conn.getConnectionParam(Connection::ParamDbName), ObjectType::Database); + obj_oids[ObjectType::Database].push_back(db_oid.toUInt()); + catalog.closeConnection(); + + import_hlp->setConnection(conn); + import_hlp->setImportOptions(imp_sys_objs, + imp_ext_objs, + true, + parsed_opts.count(IgnoreImportErrors) > 0, + parsed_opts.count(DebugMode) > 0, + !parsed_opts.count(Diff), !parsed_opts.count(Diff)); + + model->createSystemObjects(true); + import_hlp->setSelectedOIDs(model, obj_oids, col_oids); + import_hlp->importDatabase(); + import_hlp->closeConnection(); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} + +void PgModelerCliApp::diffModelDatabase() +{ + DatabaseModel *model_aux = new DatabaseModel(); + QString dbname; + vector filtered_objs; + + printMessage(tr("Starting diff process...")); + + if(!parsed_opts[Input].isEmpty()) + printMessage(tr("Input model: %1").arg(parsed_opts[Input])); + else + printMessage(tr("Input database: %1").arg(connection.getConnectionId(true, true))); + + dbname = extra_connection.getConnectionId(true, true); + printMessage(tr("Compare to: %1").arg(dbname)); + + if(!parsed_opts[Input].isEmpty()) + { + printMessage(tr("Loading input model...")); + loadModel(); + + if(parsed_opts.count(PartialDiff)) + { + QString search_attr = parsed_opts.count(MatchByName) ? Attributes::Name : Attributes::Signature; + + // Filtering by modification date always forces the signature matching + if(start_date.isValid() || end_date.isValid()) + obj_filters.append(model->getFiltersFromChangelog(start_date, end_date)); + + filtered_objs = model->findObjects(obj_filters, search_attr); + + /* We need to finish the diff if no object was found based on the filters + * this will avoid the diff between an empty database model and a full database model + * which may produce unexpected results like try to recreate all objects from the database + * model that contains objects */ + if(filtered_objs.empty()) + { + printMessage(tr("No object was retrieved using the provided filter(s).")); + + if(!parsed_opts.count(Force)) + { + printMessage(tr("Use the option `%1' to force a full diff in this case.").arg(Force)); + printMessage(tr("The diff process will not continue!\n")); + return; + } + else + printMessage(tr("Switching to full diff...")); + } + else + { + /* Special case: when performing a partial diff between a model and a database + * and in the set of filtered model objects we have one or more many-to-many, inheritance or partitioning + * relationships we need to inject filters to force the retrieval of the all involved tables in those relationships + * from the destination database,this way we avoid the diff try to create everytime all tables + * in the those relationships. */ + obj_filters.append(ModelsDiffHelper::getRelationshipFilters(filtered_objs, search_attr == Attributes::Signature)); + } + } + } + else + { + printMessage(tr("Importing the database `%1'...").arg(connection.getConnectionId(true, true))); + importDatabase(model, connection); + } + + printMessage(tr("Importing the database `%1'...").arg(dbname)); + importDatabase(model_aux, extra_connection); + + diff_hlp->setModels(model, model_aux); + diff_hlp->setFilteredObjects(filtered_objs); + diff_hlp->setDiffOption(ModelsDiffHelper::OptKeepClusterObjs, !parsed_opts.count(DropClusterObjs)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptCascadeMode, !parsed_opts.count(NoCascadeDrop)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptForceRecreation, parsed_opts.count(ForceRecreateObjs)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptRecreateUnmodifiable, parsed_opts.count(OnlyUnmodifiable)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptKeepObjectPerms, !parsed_opts.count(RevokePermissions)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptReuseSequences, !parsed_opts.count(NoSequenceReuse)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptPreserveDbName, !parsed_opts.count(RenameDb)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptDontDropMissingObjs, !parsed_opts.count(DropMissingObjs)); + diff_hlp->setDiffOption(ModelsDiffHelper::OptDropMissingColsConstr, !parsed_opts.count(ForceDropColsConstrs)); + + if(!parsed_opts[PgSqlVer].isEmpty()) + diff_hlp->setPgSQLVersion(parsed_opts[PgSqlVer]); + else + { + extra_connection.connect(); + diff_hlp->setPgSQLVersion(extra_connection.getPgSQLVersion(true)); + extra_connection.close(); + } + + printMessage(tr("Comparing the generated models...")); + diff_hlp->diffModels(); + + if(diff_hlp->getDiffDefinition().isEmpty()) + printMessage(tr("No differences were detected.")); + else + { + if(parsed_opts.count(SaveDiff)) + { + printMessage(tr("Saving diff to file `%1'").arg(parsed_opts[Output])); + UtilsNs::saveFile(parsed_opts[Output], diff_hlp->getDiffDefinition().toUtf8()); + } + else + { + bool apply_diff = true; + + if(!parsed_opts.count(NoDiffPreview)) + { + QString res, buff, line; + QTextStream in(stdin), preview; + + buff += "\n** Press ENTER to scroll the preview **\n"; + buff += "\n### DIFF PREVIEW ###\n\n"; + buff += diff_hlp->getDiffDefinition(); + buff += "\n### END OF PREVIEW ###\n\n"; + + preview.setString(&buff, QIODevice::ReadOnly); + + while(!preview.atEnd()) + { + line = preview.readLine(); + res.append(line + '\n'); + + if(res.count(QChar('\n')) >= 30 || preview.atEnd()) + { + out << res; + out.flush(); + res.clear(); + + if(!preview.atEnd()) + in.readLine(); + } + } + + out << QtCompat::endl; + out << tr("** WARNING: You are about to apply the generated diff code to the server. Data can be lost in the process!") << QtCompat::endl; + + do + { + out << tr("** Proceed with the diff applying? (yes/no) > "); + out.flush(); + + in.skipWhiteSpace(); + res = in.readLine(); + } + while(res.toLower() != tr("yes") && res.toLower() != tr("no")); + + if(res.toLower() == tr("no")) + { + apply_diff = false; + printMessage(tr("Diff code not applied to the server.")); + } + } + + if(apply_diff) + { + printMessage(tr("Applying diff to the database `%1'...").arg(dbname)); + export_hlp->setExportToDBMSParams(diff_hlp->getDiffDefinition(), + &extra_connection, + parsed_opts[CompareTo], parsed_opts.count(IgnoreDuplicates)); + + if(parsed_opts.count(IgnoreErrorCodes)) + export_hlp->setIgnoredErrors(parsed_opts[IgnoreErrorCodes].split(',')); + + export_hlp->exportToDBMS(); + } + } + } + + printMessage(tr("Diff successfully ended!\n")); +} + +void PgModelerCliApp::updateMimeType() +{ +#ifndef Q_OS_MAC + try + { + printMessage(tr("Starting mime update...")); + + handleMimeDatabase(parsed_opts[DbmMimeType]==Uninstall, parsed_opts.count(SystemWide) != 0, parsed_opts.count(Force) != 0); + + printMessage(tr("Mime database successfully updated!\n")); + } + catch (Exception &e) + { + throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); + } +#endif +} + +QStringList PgModelerCliApp::extractForeignKeys(QString &obj_xml) +{ + QStringList constr_lst; + int start=0, end=0, pos=0, count=0; + QString start_tag=QString("<%1").arg(Attributes::Constraint), + end_tag=QString(" 0 && end > 0) + { + count=(end - start) + end_tag.size() + 1; + constr=obj_xml.mid(start, count); + + if(constr.contains(Attributes::FkConstr)) + { + obj_xml.remove(start, count); + constr_lst.push_back(constr); + pos=0; + } + else + pos=end; + } + else + break; + } + while(pos >= 0 && pos < obj_xml.size()); + + return constr_lst; +} + +bool PgModelerCliApp::containsRelAttributes(const QString &str) +{ + bool found=false; + static vector attribs={ Attributes::Relationship, + Attributes::Type, Attributes::SrcRequired, Attributes::DstRequired, + Attributes::SrcTable, Attributes::DstTable, Attributes::Points, + Attributes::Columns, Attributes::Column, Attributes::Constraint, + Attributes::Label, Attributes::Line, Attributes::Position, + Attributes::Identifier, Attributes::Deferrable, Attributes::DeferType, + Attributes::TableName, Attributes::SpecialPkCols, Attributes::Table, + Attributes::AncestorTable, Attributes::CopyOptions, Attributes::CopyMode, + Attributes::SrcColPattern, Attributes::DstColPattern, Attributes::PkPattern, + Attributes::UqPattern, Attributes::SrcFkPattern, Attributes::DstFkPattern }; + + for(unsigned i=0; i < attribs.size() && !found; i++) + found=str.contains(attribs[i]); + + return found; +} + +void PgModelerCliApp::handleMimeDatabase(bool uninstall, bool system_wide, bool force) +{ + printMessage(tr("Mime database operation: %1").arg(uninstall ? QString("uninstall") : QString("install"))); + + #ifdef Q_OS_LINUX + handleLinuxMimeDatabase(uninstall, system_wide, force); + #else + #ifdef Q_OS_WIN + handleWindowsMimeDatabase(uninstall, system_wide, force); + #endif + #endif +} + +void PgModelerCliApp::handleLinuxMimeDatabase(bool uninstall, bool system_wide, bool force) +{ + SchemaParser schparser; + attribs_map attribs; + QString str_aux, + + share_path = !system_wide ? QDir::homePath() + QString("/.local/share") : QString("/usr/share"), + + //Configures the path to the application logo + exec_icon=GlobalAttributes::getTmplConfigurationFilePath("", "pgmodeler_logo.png"), + + //Configures the path to the document logo + dbm_icon=GlobalAttributes::getTmplConfigurationFilePath("", "pgmodeler_dbm.png"), + + sch_icon=GlobalAttributes::getTmplConfigurationFilePath("", "pgmodeler_sch.png"), + + //Path to directory that register mime types + mime_db_dir=QString("%1/mime").arg(share_path), + + //Path to the file that associates apps to mimetypes + mimeapps=QString("%1/applications/mimeapps.list").arg(share_path); + + //Files generated after update file association (application-dbm.xml and pgModeler.desktop) + QStringList files = { QString("%1/applications/pgModeler.desktop").arg(share_path), + QString("%1/applications/pgModelerSchEditor.desktop").arg(share_path), + mime_db_dir + QString("/packages/application-dbm.xml"), + mime_db_dir + QString("/packages/application-sch.xml")}, + + schemas = { GlobalAttributes::getTmplConfigurationFilePath(GlobalAttributes::SchemasDir, QString("desktop") + GlobalAttributes::SchemaExt), + GlobalAttributes::getTmplConfigurationFilePath(GlobalAttributes::SchemasDir, QString("desktop-sch") + GlobalAttributes::SchemaExt), + GlobalAttributes::getTmplConfigurationFilePath(GlobalAttributes::SchemasDir, QString("application-dbm") + GlobalAttributes::SchemaExt), + GlobalAttributes::getTmplConfigurationFilePath(GlobalAttributes::SchemasDir, QString("application-sch") + GlobalAttributes::SchemaExt) }, + + icons = { exec_icon, sch_icon, dbm_icon, sch_icon }; + + QByteArray buf, buf_aux; + QFile out; + + for(unsigned i=0; i < 4; i++) + { + //When installing, check if the necessary file exists. If exists, raises an error and abort. + if(!uninstall && QFileInfo(files[i]).exists() && !force) + throw Exception(MsgFileAssociated, ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(uninstall && !QFileInfo(files[i]).exists() && !force) + throw Exception(MsgNoFileAssociation, ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + + if(!uninstall && !system_wide) + attribs[Attributes::WorkingDir]=QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + else + attribs[Attributes::WorkingDir]=""; + + try + { + for(unsigned i=0; i < 4; i++) + { + if(uninstall) + { + if(!QFile(files[i]).remove() && !force) + { + throw Exception(tr("Can't erase the file %1! Check if the current user has permissions to delete it and if the file exists.").arg(files[i]), + ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + } + else + { + attribs[Attributes::Application]=(i == 0 ? GlobalAttributes::getPgModelerAppPath() : GlobalAttributes::getPgModelerSchemaEditorPath()); + attribs[Attributes::Icon] = icons[i]; + + schparser.loadFile(schemas[i]); + schparser.ignoreEmptyAttributes(true); + buf.append(schparser.getCodeDefinition(attribs).toUtf8()); + QDir(QString(".")).mkpath(QFileInfo(files[i]).absolutePath()); + + UtilsNs::saveFile(files[i], buf); + buf.clear(); + } + } + + out.setFileName(mimeapps); + + //If the file mimeapps.list doesn't exists (generally in Ubuntu) creates a new one + if(!uninstall && !QFileInfo(mimeapps).exists()) + { + out.open(QFile::WriteOnly); + out.write(QByteArray("[Added Associations]\napplication/dbm=pgModeler.desktop;\n")); + out.write(QByteArray("\n[Default Applications]\napplication/dbm=pgModeler.desktop;\n")); + out.write(QByteArray("\n[Added Associations]\napplication/sch=pgModelerStxEditor.desktop;\n")); + out.write(QByteArray("\n[Default Applications]\napplication/sch=pgModelerStxEditor.desktop;\n")); + out.close(); + } + else + { + out.open(QFile::ReadOnly); + + if(!out.isOpen()) + throw Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotWritten).arg(mimeapps), + ErrorCode::FileDirectoryNotWritten,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + //Opens the mimeapps.list to add a entry linking pgModeler to .dbm files + buf=out.readAll(); + out.close(); + + QTextStream ts(&buf); + while(!ts.atEnd()) + { + //Remove any reference to application/dbm mime from file + str_aux=ts.readLine(); + str_aux.replace(QRegExp(QString("application/dbm*"),Qt::CaseSensitive,QRegExp::Wildcard),""); + + if(!str_aux.isEmpty()) + { + //Updates the application/dbm mime association + if(!uninstall && (str_aux.contains(QString("[Added Associations]")) || + str_aux.contains(QString("[Default Applications]")))) + str_aux.append(QString("\napplication/dbm=pgModeler.desktop;\n")); + else + str_aux+=QString("\n"); + + if(str_aux.startsWith("[") && !str_aux.contains("Added Associations")) + str_aux=QString("\n") + str_aux; + + buf_aux.append(str_aux.toUtf8()); + } + } + + //Write a new copy of the mimeapps.list file + out.open(QFile::Truncate | QFile::WriteOnly); + out.write(buf_aux.data(), buf_aux.size()); + out.close(); + } + + //Update the mime database + printMessage(tr("Running update-mime-database command...")); + + QProcess::execute(QString("update-mime-database"), QStringList { mime_db_dir }); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); + } +} + +void PgModelerCliApp::handleWindowsMimeDatabase(bool uninstall, bool system_wide, bool force) +{ + SchemaParser schparser; + QString base_reg_key = system_wide ? QString("HKEY_LOCAL_MACHINE\\SOFTWARE") : QString("HKEY_CURRENT_USER\\Software"); + + //Checking if the .dbm registry key exists + QSettings dbm_ext(QString("%1\\Classes\\.dbm").arg(base_reg_key), QSettings::NativeFormat), + sch_ext(QString("%1\\Classes\\.sch").arg(base_reg_key), QSettings::NativeFormat); + QString exe_path=QDir::toNativeSeparators(GlobalAttributes::getPgModelerAppPath()), + sc_exe_path=QDir::toNativeSeparators(GlobalAttributes::getPgModelerSchemaEditorPath()); + + //If there is no value assigned to (.dbm | .sch)/Default key and the user wants to uninstall file association, raises an error + if(uninstall && !force && + (dbm_ext.value(QString("Default")).toString().isEmpty() || + sch_ext.value(QString("Default")).toString().isEmpty())) + throw Exception(MsgNoFileAssociation, ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!uninstall && !force && + (!dbm_ext.value(QString("Default")).toString().isEmpty() || + !sch_ext.value(QString("Default")).toString().isEmpty())) + throw Exception(MsgFileAssociated, ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!uninstall) + { + //Write the default value for .dbm registry key + dbm_ext.setValue(QString("Default"), QString("dbm_auto_file")); + sch_ext.setValue(QString("Default"), QString("sch_auto_file")); + } + else + { + dbm_ext.remove(""); + sch_ext.remove(""); + } + + dbm_ext.sync(); + sch_ext.sync(); + + //Other registry keys values + map confs = { + { QString("\\%1\\Classes\\dbm_auto_file").arg(base_reg_key), { QString("FriendlyTypeName") , QString("pgModeler Database Model") } }, + { QString("\\%1\\Classes\\dbm_auto_file\\DefaultIcon").arg(base_reg_key), { QString("Default") , QString("%1,1").arg(exe_path) } }, + { QString("\\%1\\Classes\\dbm_auto_file\\shell\\open\\command").arg(base_reg_key), { QString("Default") , QString("\"%1\" \"%2\"").arg(exe_path).arg("%1") } }, + { QString("\\%1\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.dbm").arg(base_reg_key), { QString("OpenWithList/a"), QString("pgmodeler.exe"), QString("OpenWithList/MRUList"), QString("a")} }, + { QString("\\%1\\Classes\\sch_auto_file").arg(base_reg_key), { QString("FriendlyTypeName") , QString("pgModeler Schema File") } }, + { QString("\\%1\\Classes\\sch_auto_file\\DefaultIcon").arg(base_reg_key), { QString("Default") , QString("%1,1").arg(sc_exe_path) } }, + { QString("\\%1\\Classes\\sch_auto_file\\shell\\open\\command").arg(base_reg_key), { QString("Default") , QString("\"%1\" \"%2\"").arg(sc_exe_path).arg("%1") } }, + { QString("\\%1\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.sch").arg(base_reg_key), { QString("OpenWithList/a"), QString("pgmodeler-sc.exe"), QString("OpenWithList/MRUList"), QString("a")} } + }; + + map::iterator itr; + itr=confs.begin(); + + //Iterates over the configuration map writing the other keys on registry + while(itr!=confs.end()) + { + QSettings s(itr->first, QSettings::NativeFormat); + + if(uninstall) + s.remove(""); + else + { + for(int i=0; i < itr->second.size(); i+=2) + s.setValue(itr->second[i], itr->second[i+1]); + } + + s.sync(); + itr++; + } +} + +void PgModelerCliApp::createConfigurations() +{ + QString conf_dir = GlobalAttributes::getConfigurationsDir(); + + printMessage(tr("Creating configuration files...")); + printMessage(tr("Destination path: %1").arg(conf_dir)); + + bool missing_only = parsed_opts.count(MissingOnly) > 0, + force = parsed_opts.count(Force) > 0; + + if(!missing_only && !force && QDir(GlobalAttributes::getConfigurationsDir()).exists()) + throw Exception(tr("Configuration files already exist!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + try + { + if(force) + { + QDir dir; + QString bkp_conf_dir = conf_dir + QDateTime::currentDateTime().toString("_yyyyMMd_hhmmss"); + + printMessage(tr("Configuration files already exist! Creating a backup...")); + + if(!dir.rename(conf_dir, bkp_conf_dir)) + throw Exception(tr("Failed to create a backup of the configuration files!"), ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + + createUserConfiguration(missing_only); + printMessage(tr("Configuration files successfully created!\n")); + } + catch (Exception &e) + { + throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); + } +} diff --git a/apps/pgmodeler-cli/src/pgmodelercliapp.h b/apps/pgmodeler-cli/src/pgmodelercliapp.h new file mode 100644 index 0000000000..e73d8eda28 --- /dev/null +++ b/apps/pgmodeler-cli/src/pgmodelercliapp.h @@ -0,0 +1,278 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +/** +\ingroup pgmodeler-cli +\class PgModelerCliApp +\brief Implements the operations export models whitout use the graphical interface +*/ + +#ifndef PGMODELER_CLI_APP_H +#define PGMODELER_CLI_APP_H + +#include "application.h" +#include +#include +#include +#include "exception.h" +#include "globalattributes.h" +#include "widgets/modelwidget.h" +#include "tools/modelexporthelper.h" +#include "settings/generalconfigwidget.h" +#include "settings/connectionsconfigwidget.h" +#include "settings/relationshipconfigwidget.h" +#include "settings/generalconfigwidget.h" +#include "tools/databaseimporthelper.h" +#include "tools/modelsdiffhelper.h" + +class PgModelerCliApp: public Application { + private: + Q_OBJECT + + XmlParser *xmlparser; + + //! \brief Holds the pgModeler version in which the model was construted (used by the fix operation) + QString model_version; + + //! \brief Export helper object + ModelExportHelper *export_hlp; + + //! \brief Import helper object + DatabaseImportHelper *import_hlp; + + //! \brief Diff helper object + ModelsDiffHelper *diff_hlp; + + //! \brief Reference database model + DatabaseModel *model; + + //! \brief Graphical scene used to export the model to png + ObjectsScene *scene; + + //! \brief Stores the configured connection + Connection connection, + + //! \brief Stores the extra configured connection (only for diff) + extra_connection; + + //! \brief Loaded connections + map connections; + + //! \brief Connection configuration widget used to load available connections from file + ConnectionsConfigWidget *conn_conf; + + //! \brief Relationship configuration widget used to load custom relationship settings + RelationshipConfigWidget *rel_conf; + + GeneralConfigWidget *general_conf; + + //! \brief Creates an standard out to handles QStrings + static QTextStream out; + + //! \brief Stores the long option names. The boolean indicates if the option accepts a value + static map long_opts; + + //! \brief Stores the short option names. + static attribs_map short_opts; + + //! \brief Stores the accepted options by the different operations + static map accepted_opts; + + //! \brief Stores the parsed options names and values. + attribs_map parsed_opts; + + //! \brief Indicates if the cli must run in silent mode + bool silent_mode; + + //! \brief Stores the xml code for the objects being fixed + QStringList objs_xml, + + //! \brief Stores the object filters for reverse engineering + obj_filters; + + //! \brief Zoom to be applied onto the png export + double zoom; + + //! \brief Start date used for filter changelog of the input database model (partial diff) + QDateTime start_date, + + //! \brief End date used for filter changelog of the input database model (partial diff) + end_date; + + /*! \brief Stores the member of role names that appear in deprecated tags + * This map is used to reconfigure the role memberships after all objects are created */ + map member_roles; + + //! \brief Stores the changelog of the model that is being fixed to reproduce it in the output model + QString changelog; + + static const QRegExp PasswordRegExp; + static const QString PasswordPlaceholder; + + //! \brief Option names constants + static const QString Input, + Output, + InputDb, + ExportToFile, + ExportToPng, + ExportToSvg, + ExportToDbms, + ExportToDict, + ImportDb, + Diff, + DropDatabase, + DropObjects, + PgSqlVer, + Help, + ShowGrid, + ShowDelimiters, + PageByPage, + IgnoreDuplicates, + IgnoreErrorCodes, + ConnAlias, + Host, + Port, + User, + Passwd, + InitialDb, + Silent, + ListConns, + Simulate, + FixModel, + FixTries, + ZoomFactor, + UseTmpNames, + DbmMimeType, + Install, + Uninstall, + SystemWide, + NoIndex, + Split, + + IgnoreImportErrors, + ImportSystemObjs, + ImportExtensionObjs, + DebugMode, + FilterObjects, + OnlyMatching, + MatchByName, + ForceChildren, + AllChildren, + + PartialDiff, + Force, + StartDate, + EndDate, + CompareTo, + SaveDiff, + ApplyDiff, + NoDiffPreview, + DropClusterObjs, + RevokePermissions, + DropMissingObjs, + ForceDropColsConstrs, + RenameDb, + NoSequenceReuse, + NoCascadeDrop, + ForceRecreateObjs, + OnlyUnmodifiable, + + CreateConfigs, + MissingOnly, + + TagExpr, + EndTagExpr, + AttributeExpr, + + MsgFileAssociated, + MsgNoFileAssociation; + + //! \brief Parsers the options and executes the action specified by them + void parseOptions(attribs_map &parsed_opts); + + //! \brief Shows the options menu + void showMenu(); + + //! \brief Shows the version info + void showVersionInfo(); + + //! \brief Returns if the specified options exists on short options map + bool isOptionRecognized(QString &op, bool &accepts_val); + + //! \brief Loads the input model and perform all tasks needed to configure the graphical objects + void loadModel(); + + /*! \brief Extracts the xml defintions from the input model and store them on obj_xml list + in order to be parsed by the recreateObjects() method */ + void extractObjectXML(); + + //! \brief Recreates the objects from the obj_xml list fixing the creation order for them + void recreateObjects(); + + //! \brief Fix some xml attributes and remove unused tags + void fixObjectAttributes(QString &obj_xml); + + /*! \brief Extracts the foreign key code for the specified table xml. The foreign keys + are recreated after all the other objects */ + QStringList extractForeignKeys(QString &obj_xml); + + //! \brief Returns if the specified string contains some of relationship attributes + bool containsRelAttributes(const QString &str); + + /*! \brief Install the .dbm file association in the mime database (default behaviour). + The paramenter 'uninstall' is used to clean up any file association done previously. */ + void handleMimeDatabase(bool uninstall, bool system_wide, bool force); + + /*! \brief Fixes the references to opertor classes and families by replacing tags like + by . This method operates + only over operator classes, indexes and constraints */ + void fixOpClassesFamiliesReferences(QString &obj_xml); + + void fixModel(); + void exportModel(); + void importDatabase(); + void diffModelDatabase(); + void updateMimeType(); + void configureConnection(bool extra_conn); + void importDatabase(DatabaseModel *model, Connection conn); + + /*! \brief Prints to the stdout the provided text appending a \n on the string + * even if the silent mode is active. */ + void printText(const QString &txt = ""); + + //! \brief Prints to the stdout only if the silent mode is not active + void printMessage(const QString &txt = ""); + + void handleLinuxMimeDatabase(bool uninstall, bool system_wide, bool force); + void handleWindowsMimeDatabase(bool uninstall, bool system_wide, bool force); + void createConfigurations(); + void listConnections(); + + public: + PgModelerCliApp(int argc, char **argv); + virtual ~PgModelerCliApp(); + int exec(); + + private slots: + void handleObjectAddition(BaseObject *); + void updateProgress(int progress, QString msg, ObjectType = ObjectType::BaseObject); + void printIgnoredError(QString err_cod, QString err_msg, QString cmd); + void handleObjectRemoval(BaseObject *object); +}; + +#endif diff --git a/apps/pgmodeler-se/pgmodeler-se.pro b/apps/pgmodeler-se/pgmodeler-se.pro new file mode 100644 index 0000000000..b730d758d7 --- /dev/null +++ b/apps/pgmodeler-se/pgmodeler-se.pro @@ -0,0 +1,32 @@ +include(../apps.pri) + +TEMPLATE = app +TARGET = pgmodeler-se + +windows:RC_FILE=res/windows_ico.qrc +windows:RCC_DIR=src/ + +SOURCES += src/main.cpp \ + src/aboutwidget.cpp \ + src/schemaeditorform.cpp \ + src/sourceeditorwidget.cpp \ + ../pgmodeler/src/pgmodelerapp.cpp \ + +FORMS += ui/aboutwidget.ui \ + ui/schemaeditorform.ui \ + ui/sourceeditorwidget.ui + +HEADERS += src/aboutwidget.h \ + src/schemaeditorform.h \ + src/sourceeditorwidget.h + +INCLUDEPATH += ../pgmodeler/src + +DEPENDPATH += ../pgmodeler + +# Deployment settings +target.path = $$PRIVATEBINDIR +INSTALLS = target + +# Print the current build settins (see pgmodeler.pri) +printBuildDetails() diff --git a/apps/pgmodeler-se/res/windows_ico.ico b/apps/pgmodeler-se/res/windows_ico.ico new file mode 100644 index 0000000000..e692ebd5ce Binary files /dev/null and b/apps/pgmodeler-se/res/windows_ico.ico differ diff --git a/apps/pgmodeler-se/res/windows_ico.qrc b/apps/pgmodeler-se/res/windows_ico.qrc new file mode 100644 index 0000000000..33cce51734 --- /dev/null +++ b/apps/pgmodeler-se/res/windows_ico.qrc @@ -0,0 +1 @@ + IDI_ICON1 ICON DISCARDABLE "windows_ico.ico" \ No newline at end of file diff --git a/apps/pgmodeler-se/src/aboutwidget.cpp b/apps/pgmodeler-se/src/aboutwidget.cpp new file mode 100644 index 0000000000..8c68da1899 --- /dev/null +++ b/apps/pgmodeler-se/src/aboutwidget.cpp @@ -0,0 +1,33 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "aboutwidget.h" +#include "guiutilsns.h" +#include "baseobjectview.h" + +AboutWidget::AboutWidget(QWidget *parent) : QWidget(parent) +{ + setupUi(this); + + GuiUtilsNs::configureWidgetFont(title_lbl, GuiUtilsNs::HugeFontFactor); + GuiUtilsNs::configureWidgetFont(pgmodeler_ver_lbl, GuiUtilsNs::HugeFontFactor); + GuiUtilsNs::configureWidgetFont(build_num_lbl, GuiUtilsNs::BigFontFactor); + + pgmodeler_ver_lbl->setText(QString("v%1 ").arg(GlobalAttributes::PgModelerVersion)); + build_num_lbl->setText(QString("%1 Qt %2").arg(GlobalAttributes::PgModelerBuildNumber).arg(QT_VERSION_STR)); +} diff --git a/apps/pgmodeler-se/src/aboutwidget.h b/apps/pgmodeler-se/src/aboutwidget.h new file mode 100644 index 0000000000..c9c0e47667 --- /dev/null +++ b/apps/pgmodeler-se/src/aboutwidget.h @@ -0,0 +1,40 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +/** +\ingroup pgmodeler-sc +\class AboutForm +\brief Form that contains information about software authoring and licensing. +*/ + +#ifndef ABOUT_WIDGET_H +#define ABOUT_WIDGET_H + +#include +#include "ui_aboutwidget.h" +#include "globalattributes.h" + +class AboutWidget: public QWidget, public Ui::AboutWidget { + private: + Q_OBJECT + + public: + AboutWidget(QWidget *parent = nullptr); +}; + +#endif diff --git a/apps/pgmodeler-se/src/main.cpp b/apps/pgmodeler-se/src/main.cpp new file mode 100644 index 0000000000..57fe97e726 --- /dev/null +++ b/apps/pgmodeler-se/src/main.cpp @@ -0,0 +1,48 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "application.h" +#include +#include "guiutilsns.h" +#include "schemaeditorform.h" +#include "pgmodelerapp.h" + +int main(int argc, char **argv) +{ + try + { + PgModelerApp::setAttribute(Qt::AA_UseHighDpiPixmaps); + PgModelerApp::setAttribute(Qt::AA_EnableHighDpiScaling); + PgModelerApp app(argc,argv); + QStringList args = app.arguments(); + + SchemaEditorForm syntaxchk; + args.pop_front(); + syntaxchk.loadFiles(args); + syntaxchk.showMaximized(); + app.exec(); + + return 0; + } + catch(Exception &e) + { + QTextStream out(stdout); + out << e.getExceptionsText(); + return enum_cast(e.getErrorCode()); + } +} diff --git a/apps/pgmodeler-se/src/schemaeditorform.cpp b/apps/pgmodeler-se/src/schemaeditorform.cpp new file mode 100644 index 0000000000..53edc5f4e3 --- /dev/null +++ b/apps/pgmodeler-se/src/schemaeditorform.cpp @@ -0,0 +1,545 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "schemaeditorform.h" +#include "guiutilsns.h" +#include "globalattributes.h" +#include "settings/generalconfigwidget.h" +#include "guiutilsns.h" +#include "sourceeditorwidget.h" +#include "aboutwidget.h" +#include "baseform.h" +#include "utilsns.h" + +const QString SchemaEditorForm::UntitledFile = QT_TR_NOOP("(untitled)"); + +SchemaEditorForm::SchemaEditorForm(QWidget *parent) : QWidget(parent) +{ + QToolButton *btn = nullptr; + QFont fnt; + + setupUi(this); + setWindowTitle(windowTitle() + " " + GlobalAttributes::PgModelerVersion); + + for(auto &obj : bnts_parent_wgt->children()) + { + btn = dynamic_cast(obj); + if(!btn) continue; + + fnt = btn->font(); + fnt.setBold(true); + btn->setFont(fnt); + GuiUtilsNs::createDropShadow(btn); + GuiUtilsNs::configureWidgetFont(btn, GuiUtilsNs::SmallFontFactor); + + if(!btn->toolTip().isEmpty() && !btn->shortcut().toString().isEmpty()) + btn->setToolTip(btn->toolTip() + QString(" (%1)").arg(btn->shortcut().toString())); + } + + GeneralConfigWidget general_conf_wgt; + general_conf_wgt.loadConfiguration(); + + alert_frm->setVisible(false); + + syntax_txt = GuiUtilsNs::createNumberedTextEditor(syntax_wgt); + syntax_hl = new SyntaxHighlighter(syntax_txt); + syntax_hl->loadConfiguration(GlobalAttributes::getXMLHighlightConfPath()); + + dtd_txt = GuiUtilsNs::createNumberedTextEditor(dtd_wgt); + dtd_txt->setReadOnly(true); + dtd_hl = new SyntaxHighlighter(dtd_txt); + dtd_hl->loadConfiguration(GlobalAttributes::getXMLHighlightConfPath()); + + SourceEditorWidget::setDefaultEditorPalette(syntax_txt->palette()); + + syntax_conf_sel = new FileSelectorWidget(syntax_conf_wgt); + syntax_conf_sel->setReadOnly(true); + + QVBoxLayout *vbox = new QVBoxLayout(syntax_conf_wgt); + vbox->addWidget(syntax_conf_sel); + vbox->setContentsMargins(0, 0, 0, 0); + + syntax_conf_sel->setNameFilters({ tr("Syntax highlight config file (*.conf)") }); + + QAction *act = nullptr; + stx_action_grp = new QActionGroup(&syntax_cfg_menu); + + act = syntax_cfg_menu.addAction("Schema file", this, SLOT(loadSyntaxConfig())); + stx_action_grp->addAction(act); + act->setCheckable(true); + act->setChecked(true); + act->setData(GlobalAttributes::SchHighlightConf); + + act = syntax_cfg_menu.addAction("XML script", this, SLOT(loadSyntaxConfig())); + stx_action_grp->addAction(act); + act->setCheckable(true); + act->setChecked(false); + act->setData(GlobalAttributes::XMLHighlightConf); + + act = syntax_cfg_menu.addAction("SQL script", this, SLOT(loadSyntaxConfig())); + stx_action_grp->addAction(act); + act->setData(GlobalAttributes::SQLHighlightConf); + act->setCheckable(true); + act->setChecked(false); + + syntax_tb->setMenu(&syntax_cfg_menu); + syntax_tb->setStyleSheet("QToolButton::menu-indicator { \ +image: url(':/styles/styles/h_menu_indicator.png'); \ +subcontrol-position: right center; }"); + + syntax_cfg_menu.installEventFilter(this); + + connect(apply_conf_tb, SIGNAL(clicked(bool)), this, SLOT(applySyntaxConfig())); + connect(save_conf_tb, SIGNAL(clicked(bool)), this, SLOT(saveSyntaxConfig())); + connect(reload_conf_tb, SIGNAL(clicked(bool)), this, SLOT(loadSyntaxConfig())); + connect(new_tb, SIGNAL(clicked(bool)), this, SLOT(addEditorTab())); + connect(load_tb, SIGNAL(clicked(bool)), this, SLOT(loadFile())); + connect(exit_tb, SIGNAL(clicked(bool)), this, SLOT(close())); + connect(save_tb, SIGNAL(clicked(bool)), this, SLOT(saveFile())); + connect(editors_tbw, SIGNAL(tabCloseRequested(int)), this, SLOT(closeEditorTab(int))); + connect(editors_tbw, SIGNAL(currentChanged(int)), this, SLOT(loadSyntaxFromCurrentTab())); + connect(use_tmpl_file_chk, SIGNAL(toggled(bool)), this, SLOT(loadSyntaxConfig())); + connect(indent_all_tb, SIGNAL(clicked(bool)), this, SLOT(indentAll())); + connect(save_all_tb, SIGNAL(clicked(bool)), this, SLOT(saveAll())); + connect(close_all_tb, SIGNAL(clicked(bool)), this, SLOT(closeAll())); + + connect(syntax_txt, &NumberedTextEditor::textChanged, [&](){ + alert_frm->setVisible(true); + }); + + connect(save_as_tb, &QToolButton::clicked, [&](){ + saveFile(true); + }); + + connect(about_tb, &QToolButton::clicked, [&](){ + AboutWidget *info_wgt = new AboutWidget; + BaseForm base_frm; + base_frm.setMainWidget(info_wgt); + base_frm.exec(); + }); +} + +void SchemaEditorForm::showEvent(QShowEvent *) +{ + h_splitter->setSizes({ width(), width()/2}); +} + +bool SchemaEditorForm::hasModifiedEditors() +{ + bool editors_modified = false; + SourceEditorWidget *editor = nullptr; + + for(int tab = 0; tab < editors_tbw->count(); tab++) + { + editor = dynamic_cast(editors_tbw->widget(tab)); + + if(editor->isModified()) + { + editors_modified = true; + break; + } + } + + return editors_modified; +} + +void SchemaEditorForm::closeEvent(QCloseEvent *event) +{ + if(alert_frm->isVisible() || hasModifiedEditors()) + { + Messagebox msgbox; + + msgbox.show(tr("There are modified files! Do you want to exit without saving them?"), Messagebox::ConfirmIcon, Messagebox::YesNoButtons); + + if(msgbox.result() == QDialog::Rejected) + event->ignore(); + } +} + +bool SchemaEditorForm::eventFilter(QObject *object, QEvent *event) +{ + if(object == &syntax_cfg_menu && event->type() == QEvent::Show) + { + syntax_cfg_menu.move(mapToGlobal(syntax_tb->pos() + QPoint(syntax_tb->width(), 0))); + syntax_cfg_menu.show(); + return true; + } + + return QWidget::eventFilter(object, event); +} + +void SchemaEditorForm::loadSyntaxFromCurrentTab() +{ + SourceEditorWidget *editor = dynamic_cast(editors_tbw->currentWidget()); + + if(!editor) + return; + + stx_action_grp->blockSignals(true); + + for(auto &act : stx_action_grp->actions()) + { + if(act->data().toString() == editor->getCurrentSyntaxConfig()) + { + act->setChecked(true); + loadSyntaxConfig(); + break; + } + } + + stx_action_grp->blockSignals(true); +} + +void SchemaEditorForm::loadSyntaxConfig() +{ + QAction *act = stx_action_grp->checkedAction(); + QFile input; + QString filename; + + if(!act) + filename = GlobalAttributes::getSchHighlightConfPath(); + else + { + if(!use_tmpl_file_chk->isChecked()) + filename = GlobalAttributes::getConfigurationFilePath(act->data().toString()); + else + filename = GlobalAttributes::getTmplConfigurationFilePath("", act->data().toString() + GlobalAttributes::ConfigurationExt); + } + + try + { + syntax_txt->setPlainText(UtilsNs::loadFile(filename)); + syntax_conf_sel->setSelectedFile(filename); + + if(dtd_txt->toPlainText().isEmpty()) + { + filename = GlobalAttributes::getTmplConfigurationFilePath(GlobalAttributes::ObjectDTDDir, + GlobalAttributes::CodeHighlightConf + + GlobalAttributes::ObjectDTDExt); + + dtd_txt->setPlainText(UtilsNs::loadFile(filename)); + } + + save_conf_tb->setEnabled(true); + apply_conf_tb->setEnabled(true); + reload_conf_tb->setEnabled(true); + alert_frm->setVisible(false); + applySyntaxConfig(false); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); + } +} + +void SchemaEditorForm::applySyntaxConfig(bool from_temp_file) +{ + QTemporaryFile tmp_file; + QString filename; + + /* When applying the syntax on-the-fly we save the syntax conf code to a temporary file + * and use it as configuration for in the open editors */ + if(from_temp_file) + { + tmp_file.setAutoRemove(false); + tmp_file.setFileTemplate(GlobalAttributes::getTemporaryFilePath("temp_XXXXXX.conf")); + tmp_file.open(); + filename = tmp_file.fileName(); + + if(!tmp_file.isOpen()) + { + throw Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotAccessed).arg(filename), + ErrorCode::FileDirectoryNotAccessed, __PRETTY_FUNCTION__, __FILE__, __LINE__); + } + + tmp_file.write(syntax_txt->toPlainText().toUtf8()); + tmp_file.close(); + } + else if(stx_action_grp->checkedAction()) + { + if(!use_tmpl_file_chk->isChecked()) + filename = GlobalAttributes::getConfigurationFilePath(stx_action_grp->checkedAction()->data().toString()); + else + filename = GlobalAttributes::getTmplConfigurationFilePath("", stx_action_grp->checkedAction()->data().toString() + GlobalAttributes::ConfigurationExt); + } + + try + { + /* Testing the temp file contents against a dummy syntax highlighter before + * applying to the open editors */ + QPlainTextEdit dummy_txt; + SyntaxHighlighter stx_hl(&dummy_txt); + stx_hl.loadConfiguration(filename); + + SourceEditorWidget *editor = dynamic_cast(editors_tbw->currentWidget()); + + if(editor) + editor->loadSyntaxConfig(filename); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); + } + + if(from_temp_file) + tmp_file.remove(); +} + +void SchemaEditorForm::saveSyntaxConfig() +{ + UtilsNs::saveFile(syntax_conf_sel->getSelectedFile(), syntax_txt->toPlainText().toUtf8()); + alert_frm->setVisible(false); + applySyntaxConfig(true); +} + +void SchemaEditorForm::saveFile(bool save_as) +{ + SourceEditorWidget *editor = dynamic_cast(editors_tbw->widget(editors_tbw->currentIndex())); + QString filename = editor->getFilename(); + + if(save_as || filename.isEmpty()) + { + QStringList files = showFileDialog(true); + + if(files.isEmpty()) + return; + + filename = files.at(0); + } + + editor->saveFile(filename); + editor->setModified(false); + QFileInfo fi(filename); + editors_tbw->setTabText(editors_tbw->currentIndex(), fi.fileName()); + editors_tbw->setTabToolTip(editors_tbw->currentIndex(), fi.absoluteFilePath()); +} + +void SchemaEditorForm::setTabModified(bool modified) +{ + SourceEditorWidget *editor = dynamic_cast(sender()); + int idx = editors_tbw->indexOf(editor); + QString tab_text = editors_tbw->tabText(idx); + + if(modified && !tab_text.endsWith('*')) + tab_text += '*'; + else if(!modified) + tab_text.remove('*'); + + editors_tbw->setTabText(idx, tab_text); +} + +void SchemaEditorForm::indentAll() +{ + SourceEditorWidget *editor = nullptr; + + QApplication::setOverrideCursor(Qt::WaitCursor); + + for(int tab = 0; tab < editors_tbw->count(); tab++) + { + editor = dynamic_cast(editors_tbw->widget(tab)); + editor->indent_tb->click(); + } + + QApplication::restoreOverrideCursor(); +} + +void SchemaEditorForm::saveAll() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + + for(int tab = 0; tab < editors_tbw->count(); tab++) + { + editors_tbw->setCurrentIndex(tab); + + try + { + saveFile(); + } + catch(Exception &e) + { + Messagebox msgbox; + msgbox.show(e); + break; + } + } + + QApplication::restoreOverrideCursor(); +} + +void SchemaEditorForm::closeAll() +{ + Messagebox msgbox; + + if(hasModifiedEditors()) + { + msgbox.show(tr("There are modified files! Do you want to close them without save?"), Messagebox::ConfirmIcon, Messagebox::YesNoButtons); + + if(msgbox.result() == QDialog::Rejected) + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + + while(editors_tbw->count() > 0) + closeEditorTab(0, false); + + QApplication::restoreOverrideCursor(); +} + +QStringList SchemaEditorForm::showFileDialog(bool save_mode) +{ + QFileDialog file_dlg; + QStringList files, filters= { + tr("Schema file (*.sch)"), + tr("Database model file (*.dbm)"), + tr("pgModeler config file (*.conf)"), + tr("Objects metadata file (*.omf)"), + tr("SQL script file (*.sql)"), + tr("XML file (*.xml)"), + tr("DTD file (*.dtd)"), + tr("All files (*.*)") + }; + + if(!save_mode) + filters.prepend(tr("All supported files (*.sch *.dbm *.conf *.omf *.sql *.xml *.dtd)")); + + file_dlg.setNameFilters(filters); + + file_dlg.setWindowTitle(save_mode ? tr("Save file") : tr("Load file")); + file_dlg.setFileMode(save_mode ? QFileDialog::AnyFile : QFileDialog::ExistingFiles); + file_dlg.setAcceptMode(save_mode ? QFileDialog::AcceptSave : QFileDialog::AcceptOpen); + + if(save_mode) + { + file_dlg.setDefaultSuffix(".sch"); + connect(&file_dlg, &QFileDialog::filterSelected, [&](QString filter){ + filter.remove(QRegExp("(.)+(\\*)")); + filter.remove(")"); + file_dlg.setDefaultSuffix(filter); + }); + } + + if(file_dlg.exec() == QFileDialog::Accepted) + files = file_dlg.selectedFiles(); + + return files; +} + +void SchemaEditorForm::loadFile() +{ + try + { + QStringList files = showFileDialog(false); + + if(!files.isEmpty()) + loadFiles(files); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); + } +} + +void SchemaEditorForm::loadFiles(const QStringList &filenames) +{ + try + { + QApplication::setOverrideCursor(Qt::WaitCursor); + + for(auto &file : filenames) + addEditorTab(file); + + QApplication::restoreOverrideCursor(); + } + catch(Exception &e) + { + QApplication::restoreOverrideCursor(); + throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); + } +} + +void SchemaEditorForm::addEditorTab(const QString &filename) +{ + SourceEditorWidget *editor_wgt = nullptr; + QFileInfo fi(filename); + + try + { + editor_wgt = new SourceEditorWidget; + + if(!filename.isEmpty()) + editor_wgt->loadFile(filename); + + connect(editor_wgt, SIGNAL(s_editorModified(bool)), this, SLOT(setTabModified(bool))); + } + catch(Exception &e) + { + delete editor_wgt; + throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); + } + + editors_tbw->addTab(editor_wgt, filename.isEmpty() ? UntitledFile : fi.fileName()); + editors_tbw->setTabToolTip(editors_tbw->count() - 1, filename.isEmpty() ? "" : fi.absoluteFilePath()); + editors_tbw->setCurrentIndex(editors_tbw->count() - 1); + save_as_tb->setEnabled(true); + save_tb->setEnabled(true); + indent_all_tb->setEnabled(true); + save_all_tb->setEnabled(true); + close_all_tb->setEnabled(true); + syntax_cfg_edit_frm->setEnabled(true); + syntax_tb->setEnabled(true); +} + +void SchemaEditorForm::closeEditorTab(int idx, bool confirm_close) +{ + SourceEditorWidget *editor_wgt = dynamic_cast(editors_tbw->widget(idx)); + Messagebox msgbox; + + if(editor_wgt->isModified() && confirm_close) + { + msgbox.show(tr("The source code was modified! Do you really want to close it without save?"), Messagebox::ConfirmIcon, Messagebox::YesNoButtons); + + if(msgbox.result() == QDialog::Rejected) + return; + } + + editors_tbw->removeTab(idx); + delete(editor_wgt); + + bool enable = editors_tbw->count() > 0; + save_as_tb->setEnabled(enable); + save_tb->setEnabled(enable); + indent_all_tb->setEnabled(enable); + save_all_tb->setEnabled(enable); + close_all_tb->setEnabled(enable); + syntax_cfg_edit_frm->setEnabled(enable); + syntax_tb->setEnabled(enable); + + if(!enable) + { + syntax_txt->blockSignals(true); + syntax_conf_sel->blockSignals(true); + + syntax_txt->clear(); + syntax_conf_sel->clearSelector(); + alert_frm->setVisible(false); + + syntax_txt->blockSignals(false); + syntax_conf_sel->blockSignals(false); + } +} diff --git a/apps/pgmodeler-se/src/schemaeditorform.h b/apps/pgmodeler-se/src/schemaeditorform.h new file mode 100644 index 0000000000..5ce94f54f0 --- /dev/null +++ b/apps/pgmodeler-se/src/schemaeditorform.h @@ -0,0 +1,80 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +/** +\ingroup pgmodeler-se +\class SchemaEditorForm +\brief Implements the pgModeler's schema files editor and syntax checker. +*/ + +#ifndef SCHEMA_EDITOR_FORM_H +#define SCHEMA_EDITOR_FORM_H + +#include +#include +#include "ui_schemaeditorform.h" +#include "widgets/numberedtexteditor.h" +#include "utils/syntaxhighlighter.h" +#include "widgets/fileselectorwidget.h" +#include "widgets/findreplacewidget.h" + +class SchemaEditorForm: public QWidget, public Ui::SchemaEditorForm { + private: + Q_OBJECT + + static const QString UntitledFile; + + NumberedTextEditor *syntax_txt, *dtd_txt; + + SyntaxHighlighter *syntax_hl, *dtd_hl; + + FileSelectorWidget *syntax_conf_sel; + + QActionGroup *stx_action_grp; + + QMenu syntax_cfg_menu; + + void showEvent(QShowEvent *) override; + + void closeEvent(QCloseEvent *event) override; + + bool eventFilter(QObject *object, QEvent *event) override; + + QStringList showFileDialog(bool save_mode); + + public: + explicit SchemaEditorForm(QWidget *parent = nullptr); + void loadFiles(const QStringList &filenames); + bool hasModifiedEditors(); + + private slots: + void loadSyntaxConfig(); + void applySyntaxConfig(bool from_temp_file = true); + void saveSyntaxConfig(); + void addEditorTab(const QString &filename = ""); + void closeEditorTab(int idx, bool confirm_close = true); + void loadFile(); + void saveFile(bool save_as = false); + void setTabModified(bool modified); + void indentAll(); + void saveAll(); + void closeAll(); + void loadSyntaxFromCurrentTab(); +}; + +#endif diff --git a/apps/pgmodeler-se/src/sourceeditorwidget.cpp b/apps/pgmodeler-se/src/sourceeditorwidget.cpp new file mode 100644 index 0000000000..196134bbee --- /dev/null +++ b/apps/pgmodeler-se/src/sourceeditorwidget.cpp @@ -0,0 +1,340 @@ +#include "sourceeditorwidget.h" +#include "messagebox.h" +#include "guiutilsns.h" +#include "qtcompat/splitbehaviorcompat.h" +#include "utilsns.h" + +QPalette SourceEditorWidget::def_editor_pal; + +attribs_map SourceEditorWidget::snippets = { + {"ifend", "%if {} %then\n\n%end\n"}, + {"ifelseend", "%if {} %then\n\n%else\n\n%end\n"}, + {"ifexpr", "%if ({}) %then\n\n%end\n"}, + {"ifexprelse", "%if ({}) %then\n\n%else\n\n%end\n"}, + {"setattrstr", "%set {} \"\"\n"}, + {"setattrtxt", "%set {} [ ]\n"}, + {"unsetattr", "%unset {}\n"}, + {"unsetattr", "%unset {}\n"}, +}; + +SourceEditorWidget::SourceEditorWidget(QWidget *parent) : QWidget(parent) +{ + setupUi(this); + + is_modified = false; + curr_sytax_cfg = GlobalAttributes::SchHighlightConf; + + editor_txt = GuiUtilsNs::createNumberedTextEditor(editor_parent); + def_editor_pal = editor_txt->palette(); + + editor_hl = new SyntaxHighlighter(editor_txt); + find_wgt = new FindReplaceWidget(editor_txt, find_parent); + find_parent->setVisible(false); + + code_compl_wgt = new CodeCompletionWidget(editor_txt); + code_compl_wgt->configureCompletion(nullptr, editor_hl); + + source_file_sel = new FileSelectorWidget(source_file_parent); + source_file_sel->setReadOnly(true); + source_file_parent->setVisible(false); + + QVBoxLayout *vbox = new QVBoxLayout(source_file_parent); + vbox->setContentsMargins(0, 0, 0, 0); + vbox->addWidget(source_file_sel); + + QStringList snippets_id; + + for(auto &itr : snippets) + code_compl_wgt->insertCustomItem(itr.first, itr.second, QPixmap(GuiUtilsNs::getIconPath("codesnippet"))); + + vbox = new QVBoxLayout(find_parent); + vbox->setContentsMargins(0, 0, 0, 4); + vbox->addWidget(find_wgt); + + indent_tb->setMenu(&indent_opts_menu); + act_break_inline_ifs = indent_opts_menu.addAction(tr("Break inline ifs")); + act_break_inline_ifs->setCheckable(true); + act_break_inline_ifs->setChecked(false); + + connect(code_compl_wgt, SIGNAL(s_wordSelected(QString)), this, SLOT(handleSelectedSnippet(QString))); + connect(find_wgt, SIGNAL(s_hideRequested()), find_tb, SLOT(toggle())); + connect(validate_tb, SIGNAL(clicked(bool)), this, SLOT(validateSyntax())); + connect(indent_tb, SIGNAL(clicked(bool)), this, SLOT( applyIndentation())); + connect(editor_txt, SIGNAL(modificationChanged(bool)), this, SLOT(restoreEditorPalette())); + connect(editor_txt, SIGNAL(undoAvailable(bool)), this, SLOT(setModified(bool))); + connect(editor_txt, SIGNAL(cursorPositionChanged()), this, SLOT(restoreEditorPalette())); + connect(find_tb, SIGNAL(toggled(bool)), find_parent, SLOT(setVisible(bool))); +} + +void SourceEditorWidget::saveFile(const QString &filename) +{ + UtilsNs::saveFile(filename, editor_txt->toPlainText().toUtf8()); + + QFileInfo fi(filename); + validate_tb->setEnabled(filename.endsWith(GlobalAttributes::SchemaExt)); + indent_tb->setEnabled(filename.endsWith(GlobalAttributes::SchemaExt)); + this->filename = filename; + source_file_sel->setSelectedFile(filename); + source_file_parent->setVisible(true); +} + +void SourceEditorWidget::loadSyntaxConfig(const QString &filename) +{ + try + { + editor_hl->loadConfiguration(filename); + editor_hl->rehighlight(); + curr_sytax_cfg = QFileInfo(filename).baseName(); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); + } +} + +void SourceEditorWidget::handleSelectedSnippet(const QString &snippet) +{ + QTextCursor tc = editor_txt->textCursor(); + tc.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); + tc.removeSelectedText(); + tc.insertText(snippets[snippet]); +} + +QString SourceEditorWidget::getCurrentSyntaxConfig() +{ + return curr_sytax_cfg; +} + +void SourceEditorWidget::loadFile(const QString &filename) +{ + if(filename.isEmpty()) + return; + + bool enable = filename.endsWith(GlobalAttributes::SchemaExt); + + editor_txt->setPlainText(UtilsNs::loadFile(filename)); + validate_tb->setEnabled(enable); + indent_tb->setEnabled(enable); + code_compl_wgt->setEnabled(enable); + this->filename = filename; + source_file_sel->setSelectedFile(filename); + source_file_parent->setVisible(true); + + QString ext = QFileInfo(filename).suffix(); + + if(ext == "dbm" || ext == "xml" || ext == "conf" || ext == "omf") + curr_sytax_cfg = GlobalAttributes::XMLHighlightConf; + else if(ext == "sql") + curr_sytax_cfg = GlobalAttributes::SQLHighlightConf; + else + curr_sytax_cfg = GlobalAttributes::SchHighlightConf; +} + +void SourceEditorWidget::validateSyntax() +{ + SchemaParser schparser; + Messagebox msgbox; + + try + { + editor_txt->setPalette(def_editor_pal); + schparser.ignoreEmptyAttributes(true); + schparser.ignoreUnkownAttributes(true); + schparser.loadBuffer(editor_txt->toPlainText()); + schparser.getCodeDefinition({}); + + msgbox.show(tr("No lexical or sytactical errors found."), Messagebox::InfoIcon); + } + catch(Exception &e) + { + // When founding an error we try to highlight the exact portion of the document where to problem is + QTextCursor cursor(editor_txt->document()->findBlockByLineNumber(schparser.getCurrentLine() - 1)); + cursor.movePosition(QTextCursor::StartOfLine); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, schparser.getCurrentColumn()); + + editor_txt->blockSignals(true); + editor_txt->setTextCursor(cursor); + editor_txt->blockSignals(false); + + // Changing the text selection color so the user can see where the problem is + QPalette pal = editor_txt->palette(); + pal.setColor(QPalette::Highlight, QColor("#f00000")); + pal.setColor(QPalette::HighlightedText, QColor("#ffffff")); + editor_txt->setPalette(pal); + + msgbox.show(e); + } +} + +void SourceEditorWidget::restoreEditorPalette() +{ + editor_txt->setPalette(def_editor_pal); +} + +void SourceEditorWidget::applyIndentation() +{ + QStringList buffer = editor_txt->toPlainText().split(QChar::LineFeed); + int if_level = 0, comment_pos = -1, line_count = buffer.size(); + bool found_cond = false, found_if = false, inline_ifend = false; + QString cond_pattern = QString("^(( )|(\\t))*(%1)"), line, + tk_if = SchemaParser::CharStartConditional + SchemaParser::TokenIf, + tk_then = SchemaParser::CharStartConditional + SchemaParser::TokenThen, + tk_else = SchemaParser::CharStartConditional + SchemaParser::TokenElse, + tk_end = SchemaParser::CharStartConditional + SchemaParser::TokenEnd; + QRegExp inline_if_regexp(QString("(%1)(.)+(%2)").arg(tk_if).arg(tk_end)); + + for(int ln_idx = 0; ln_idx < line_count; ln_idx++) + { + line = buffer[ln_idx]; + comment_pos = line.indexOf(SchemaParser::CharComment); + inline_ifend = line.contains(inline_if_regexp); + + if(line.contains(QRegExp(cond_pattern.arg(tk_if))) && !inline_ifend) + { + if_level++; + found_if = found_cond = true; + } + else if(line.contains(QRegExp(cond_pattern.arg(tk_else))) || + line.contains(QRegExp(cond_pattern.arg(tk_end)))) + found_cond = true; + + // If the current line is an inline if: %if ... %then ... %end, we break it + if(act_break_inline_ifs->isChecked() && inline_ifend) + { + line.replace(tk_if, QChar::LineFeed + tk_if); + line.replace(tk_then, tk_then + QChar::LineFeed); + line.replace(tk_else, QChar::LineFeed + tk_else + QChar::LineFeed); + line.replace(tk_end, QChar::LineFeed + tk_end + QChar::LineFeed ); + + /* If the line was broke ( presence of \n) we split the resulting string + * and insert the new lines in the buffer and restart the indentation process */ + if(line.contains(QChar::LineFeed)) + { + QStringList buf_aux = line.split(QChar::LineFeed, QtCompat::SkipEmptyParts); + buffer.removeAt(ln_idx); + + for(auto itr = buf_aux.rbegin(); itr != buf_aux.rend(); itr++) + buffer.insert(ln_idx, *itr); + + ln_idx = 0; + found_cond = found_if = false; + if_level = 0; + line_count = buffer.size(); + continue; + } + } + + line = line.simplified(); + + if(!line.isEmpty()) + { + line = line.rightJustified(line.size() + if_level + (found_cond ? -1 : 0), QChar::Tabulation); + + if(!inline_ifend) + if_level -= line.mid(0, comment_pos).count(QString("%1%2").arg(SchemaParser::CharStartConditional).arg(SchemaParser::TokenEnd)); + } + + buffer[ln_idx] = line; + found_cond = found_if = false; + } + + QRegExp cond_tk_regexp(QString("^(( )|(\\t))*(%1)[a-z]+").arg(SchemaParser::CharStartConditional)); + QString prev_line, next_line, next_next_line, + tk_set = SchemaParser::CharStartConditional + SchemaParser::TokenSet, + tk_unset = SchemaParser::CharStartConditional + SchemaParser::TokenUnset; + + for(int ln_idx = 0; ln_idx < buffer.count() - 1; ln_idx++) + { + line = buffer[ln_idx].mid(0, buffer[ln_idx].indexOf(SchemaParser::CharComment)); + + // Ignoring the line if it contains a inline if + if(line.contains(inline_if_regexp)) + continue; + + // Capturing the previous, next lines without comment portion + prev_line = ln_idx > 0 ? buffer[ln_idx - 1].mid(0, buffer[ln_idx - 1].indexOf(SchemaParser::CharComment)) : ""; + next_line = ln_idx < buffer.count() - 1 ? buffer[ln_idx + 1].mid(0, buffer[ln_idx + 1].indexOf(SchemaParser::CharComment)) : ""; + next_next_line = ln_idx < buffer.count() - 2 ? buffer[ln_idx + 2].mid(0, buffer[ln_idx + 2].indexOf(SchemaParser::CharComment)) : ""; + + /* Removing the empty line in the following cases: + * 1) Between a two %end tokens + * 2) Between an %end and %else + * 3) Between an two %if tokens + * 4) Between an %else and %if | %set | %unset */ + if(next_line.isEmpty() && !next_next_line.isEmpty() && + ((line.contains(QRegExp(cond_pattern.arg(tk_end))) && + (next_next_line.contains(QRegExp(cond_pattern.arg(tk_else))) || + next_next_line.contains(QRegExp(cond_pattern.arg(tk_end))))) || + + ((line.contains(QRegExp(cond_pattern.arg(tk_if))) || + line.contains(QRegExp(cond_pattern.arg(tk_else)))) && + (next_next_line.contains(QRegExp(cond_pattern.arg(tk_if))) || + next_next_line.contains(QRegExp(cond_pattern.arg(tk_set))) || + next_next_line.contains(QRegExp(cond_pattern.arg(tk_unset))))))) + { + buffer.removeAt(ln_idx + 1); + ln_idx--; + continue; + } + + // Separating an end token from any conditional token in the next line + if(line.contains(QRegExp(cond_pattern.arg(tk_end))) && + !next_line.isEmpty() && + !next_line.contains(cond_tk_regexp)) + buffer[ln_idx].append(QChar::LineFeed); + + // Separating an closed plain text from the next line + else if(line.endsWith(SchemaParser::CharEndPlainText) && + !next_line.isEmpty() && + !next_line.contains(cond_tk_regexp)) + buffer[ln_idx].append(QChar::LineFeed); + + // If the current line has an %if and the previous is not a conditional instruction % + else if(line.contains(QRegExp(cond_pattern.arg(tk_if))) && + !prev_line.isEmpty() && + !prev_line.contains(cond_tk_regexp)) + buffer[ln_idx].prepend(QChar::LineFeed); + + // Separating an if token from previous end, set and unset + else if(line.contains(QRegExp(cond_pattern.arg(tk_if))) && + (prev_line.contains(tk_end) || + prev_line.contains(tk_set) || + prev_line.contains(tk_unset))) + buffer[ln_idx].prepend(QChar::LineFeed); + } + + /* Replacing the current code with the formatted one in such a way to preserve + * the undo/redo stack. This is achieved by selecting the whole text document + * and inserting the new text using the cursor. Using QPlainTextEdit::setPlainText + * will clear the stack. */ + editor_txt->blockSignals(true); + QTextCursor cursor = editor_txt->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); + cursor.insertText(buffer.join(QChar::LineFeed)); + cursor = editor_txt->textCursor(); + editor_txt->moveCursor(QTextCursor::Start); + editor_txt->blockSignals(false); + setModified(true); +} + +void SourceEditorWidget::setModified(bool value) +{ + is_modified = value; + emit s_editorModified(value); +} + +void SourceEditorWidget::setDefaultEditorPalette(const QPalette &pal) +{ + def_editor_pal = pal; +} + +QString SourceEditorWidget::getFilename() +{ + return filename; +} + +bool SourceEditorWidget::isModified() +{ + return is_modified; +} diff --git a/apps/pgmodeler-se/src/sourceeditorwidget.h b/apps/pgmodeler-se/src/sourceeditorwidget.h new file mode 100644 index 0000000000..69d1ae627f --- /dev/null +++ b/apps/pgmodeler-se/src/sourceeditorwidget.h @@ -0,0 +1,102 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +/** +\ingroup pgmodeler-sc +\class SourceEditorWidget +\brief Implements the basic source code editor with minimal code completion for schema files. +*/ + +#ifndef SOURCE_EDITOR_WIDGET_H +#define SOURCE_EDITOR_WIDGET_H + +#include +#include "ui_sourceeditorwidget.h" +#include "widgets/numberedtexteditor.h" +#include "utils/syntaxhighlighter.h" +#include "widgets/findreplacewidget.h" +#include "widgets/codecompletionwidget.h" +#include "widgets/fileselectorwidget.h" + +class SourceEditorWidget: public QWidget, public Ui::SourceEditorWidget { + private: + Q_OBJECT + + static attribs_map snippets; + + static QPalette def_editor_pal; + + CodeCompletionWidget *code_compl_wgt; + + FileSelectorWidget *source_file_sel; + + NumberedTextEditor *editor_txt; + + SyntaxHighlighter *editor_hl; + + FindReplaceWidget *find_wgt; + + QString filename, curr_sytax_cfg; + + QAction *act_break_inline_ifs; + + QMenu indent_opts_menu; + + bool is_modified; + + public: + explicit SourceEditorWidget(QWidget *parent = nullptr); + + /*! \brief Defines the default pallete for text editor. + * This is used to restore the colors of the editor after an error is raised + * during syntax validation and the text selection color is changed to point the + * error location */ + static void setDefaultEditorPalette(const QPalette &pal); + + //! \brief Returns the file being handled by the editor + QString getFilename(); + + //! \brief Returns the current modification status of the editor + bool isModified(); + + QString getCurrentSyntaxConfig(); + + private slots: + //! \brief Validates the syntax of the editor's content (only for schema micro-language code) + void validateSyntax(); + + //! \brief Restores the editor default colors after highlighting an syntax error in a portion of the text + void restoreEditorPalette(); + + //! \brief Applies a custom identation on the editor's content (only for schema micro-language code) + void applyIndentation(); + + //! \brief Insert the selected snippet into the editors (only for schema micro-language code) + void handleSelectedSnippet(const QString &snippet); + + public slots: + void setModified(bool value); + void loadFile(const QString &filename); + void saveFile(const QString &filename); + void loadSyntaxConfig(const QString &filename); + + signals: + void s_editorModified(bool value); +}; + +#endif diff --git a/apps/pgmodeler-se/ui/aboutwidget.ui b/apps/pgmodeler-se/ui/aboutwidget.ui new file mode 100644 index 0000000000..e80183b949 --- /dev/null +++ b/apps/pgmodeler-se/ui/aboutwidget.ui @@ -0,0 +1,402 @@ + + + AboutWidget + + + Qt::NonModal + + + + 0 + 0 + 816 + 704 + + + + + 0 + 0 + + + + + 650 + 500 + + + + + 16777215 + 16777215 + + + + About pgModeler Schema Editor + + + + :/images/images/schemafile.png:/images/images/schemafile.png + + + + 4 + + + 4 + + + 4 + + + 4 + + + 6 + + + + + + 0 + 0 + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + + + + :/images/images/schemafile.png + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + pgModeler Schema Editor + + + Qt::AlignCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + true + + + + + + + 0.0.0 + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 129 + 0 + + + + + + + + + 0 + 129 + 0 + + + + + + + + + 128 + 128 + 128 + + + + + + + + + 50 + true + false + + + + (BUILD_NUM) + + + Qt::AlignCenter + + + -1 + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + false + + + + QFrame::NoFrame + + + Create, edit and verify the syntax of files written in pgModeler's schema micro-language. You can also tweak the tool's syntax highlighting settings to be used by the main GUI application. + + + Qt::PlainText + + + Qt::AlignJustify|Qt::AlignTop + + + true + + + 0 + + + Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + License + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + QFrame::Sunken + + + QAbstractScrollArea::AdjustToContents + + + false + + + QTextEdit::WidgetWidth + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier'; font-size:11pt;">pgModeler - PostgreSQL Database Modeler<br />Copyright 2006-2021 - Raphael Araújo e Silva<br /><br />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 version 3.<br /><br />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.<br /><br />The complete text of GPLv3 is at LICENSE file on pgModeler's source code root directory. Also, you can get the complete GNU General Public License at &lt;</span><a href="http://www.gnu.org/licenses"><span style=" font-family:'Courier'; font-size:11pt; text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses</span></a><span style=" font-family:'Courier'; font-size:11pt;">&gt;</span></p></body></html> + + + false + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + + pgModeler is proudly a brazilian software! + + + + + + + + + :/images/images/brazil_flag.png + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Raphael Araújo e Silva &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.io</span></a>&gt;</p></body></html> + + + Qt::AutoText + + + 5 + + + true + + + + + + + + + + + + diff --git a/apps/pgmodeler-se/ui/schemaeditorform.ui b/apps/pgmodeler-se/ui/schemaeditorform.ui new file mode 100644 index 0000000000..6b93bc0bdb --- /dev/null +++ b/apps/pgmodeler-se/ui/schemaeditorform.ui @@ -0,0 +1,959 @@ + + + SchemaEditorForm + + + + 0 + 0 + 916 + 629 + + + + + 800 + 600 + + + + pgModeler Schema Editor + + + + :/images/images/schemafile.png:/images/images/schemafile.png + + + + 0 + + + 0 + + + 0 + + + 4 + + + 4 + + + 6 + + + + + Qt::Horizontal + + + 4 + + + false + + + + + 0 + + + 4 + + + 0 + + + 0 + + + 6 + + + + + + 16777215 + 16777215 + + + + QTabWidget::North + + + true + + + + + + + + false + + + + 0 + + + 4 + + + 4 + + + 0 + + + 6 + + + + + + 0 + 0 + + + + Syntax file: + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 4 + + + 4 + + + 4 + + + 6 + + + 6 + + + + + false + + + Save && apply + + + + :/icons/icons/save.png:/icons/icons/save.png + + + + 22 + 22 + + + + Qt::ToolButtonTextBesideIcon + + + + + + + + 25 + 25 + + + + + 24 + 24 + + + + + + + Qt::AutoText + + + :/icons/icons/alert.png + + + true + + + + + + + false + + + Apply only + + + + :/icons/icons/confirm.png:/icons/icons/confirm.png + + + + 22 + 22 + + + + Qt::ToolButtonTextBesideIcon + + + + + + + false + + + Reload + + + + :/icons/icons/refresh.png:/icons/icons/refresh.png + + + + 22 + 22 + + + + Qt::ToolButtonTextBesideIcon + + + + + + + + 0 + 0 + + + + + 50 + false + false + false + true + + + + The syntax settings below have changed. Click <strong>Save & apply</strong> to persit the modifications to config file and apply them; <strong>Apply only</strong> to use the modified settings on-the-fly on the current editor without save the changes to the configuration file; or <strong>Reload</strong> to load the file again from the last time that it was saved. <strong>NOTE:</strong> switching to another editor tab will cause all modifications below to be lost. + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 0 + + + + <p>Instead of loading the configuration file at user's local storage, loads the template one inside the pgModeler's installation folder.</p> + + + Use template configuration file + + + + + + + 0 + + + + XML + + + + 6 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + DTD + + + + 6 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + + + 3 + + + 0 + + + 3 + + + 4 + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + Save changes to another file + + + Save as + + + + :/icons/icons/saveas.png:/icons/icons/saveas.png + + + + 25 + 25 + + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Exit + + + + :/icons/icons/exit.png:/icons/icons/exit.png + + + + 25 + 25 + + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Open a new editor + + + New + + + + :/icons/icons/new.png:/icons/icons/new.png + + + + 25 + 25 + + + + Ctrl+N + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + Save changes + + + Save + + + + :/icons/icons/save.png:/icons/icons/save.png + + + + 25 + 25 + + + + Ctrl+S + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Load files + + + Load + + + + :/icons/icons/open.png:/icons/icons/open.png + + + + 25 + 25 + + + + Ctrl+L + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + About + + + + :/icons/icons/help.png:/icons/icons/help.png + + + + 25 + 25 + + + + F1 + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + Choose the syntax highlighting mode + + + Syntax + + + + :/icons/icons/xmlcode.png:/icons/icons/xmlcode.png + + + + 25 + 25 + + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextUnderIcon + + + true + + + Qt::NoArrow + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + Apply identation to all open editors + + + Indent all + + + + :/icons/icons/ident.png:/icons/icons/ident.png + + + + 25 + 25 + + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + Save all + + + + :/icons/icons/saveall.png:/icons/icons/saveall.png + + + + 25 + 25 + + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + Close all + + + + :/icons/icons/close.png:/icons/icons/close.png + + + + 25 + 25 + + + + Qt::ToolButtonTextUnderIcon + + + true + + + + + + + + + + 4 + + + 2 + + + 4 + + + 2 + + + 6 + + + + + + 0 + 0 + + + + + 127 + 0 + + + + + + + + + + Qt::PlainText + + + :/images/images/pgmodeler_name.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + diff --git a/apps/pgmodeler-se/ui/sourceeditorwidget.ui b/apps/pgmodeler-se/ui/sourceeditorwidget.ui new file mode 100644 index 0000000000..3f151f14cb --- /dev/null +++ b/apps/pgmodeler-se/ui/sourceeditorwidget.ui @@ -0,0 +1,241 @@ + + + SourceEditorWidget + + + + 0 + 0 + 1212 + 736 + + + + Form + + + + 4 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + 6 + + + 2 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Validate the syntax of the schema file + + + Validate + + + + :/icons/icons/validatesch.png:/icons/icons/validatesch.png + + + + 25 + 25 + + + + F5 + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + false + + + Qt::NoArrow + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Apply custom indentation to the code + + + Indent + + + + :/icons/icons/ident.png:/icons/icons/ident.png + + + + 25 + 25 + + + + Ctrl+I + + + QToolButton::MenuButtonPopup + + + Qt::ToolButtonTextBesideIcon + + + false + + + Qt::NoArrow + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Find + + + + :/icons/icons/findtext.png:/icons/icons/findtext.png + + + + 25 + 25 + + + + Ctrl+F + + + true + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + false + + + Qt::NoArrow + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + diff --git a/apps/pgmodeler/pgmodeler.pro b/apps/pgmodeler/pgmodeler.pro new file mode 100644 index 0000000000..1108381c84 --- /dev/null +++ b/apps/pgmodeler/pgmodeler.pro @@ -0,0 +1,30 @@ +include(../apps.pri) + +TEMPLATE = app +TARGET = pgmodeler + +unix:LIBS += $$QMAKE_LIBS_EXECINFO +windows:RC_FILE=res/windows_ico.qrc +windows:RCC_DIR=src/ +windows: DESTDIR = $$PWD + +HEADERS += src/pgmodelerapp.h + +SOURCES += src/main.cpp \ + src/pgmodelerapp.cpp + +# Deployment settings +target.path = $$BINDIR +INSTALLS = target + +macx { + macdeps.files = $$PWD/res/Resources $$PWD/res/Info.plist $$PWD/res/PkgInfo + macdeps.path = $$PREFIX + + macscript.files = $$PWD/res/startapp + macscript.path = $$BINDIR + + INSTALLS += macdeps macscript +} + + diff --git a/main/res/Info.plist b/apps/pgmodeler/res/Info.plist similarity index 97% rename from main/res/Info.plist rename to apps/pgmodeler/res/Info.plist index 330902878e..ea50a82e16 100644 --- a/main/res/Info.plist +++ b/apps/pgmodeler/res/Info.plist @@ -33,7 +33,7 @@ CFBundleSignature ???? CFBundleVersion - 0.8.0 + 0.9.4 CSResourcesFileMapped NSPrincipalClass diff --git a/main/res/PkgInfo b/apps/pgmodeler/res/PkgInfo similarity index 100% rename from main/res/PkgInfo rename to apps/pgmodeler/res/PkgInfo diff --git a/main/res/Resources/empty.lproj b/apps/pgmodeler/res/Resources/empty.lproj similarity index 100% rename from main/res/Resources/empty.lproj rename to apps/pgmodeler/res/Resources/empty.lproj diff --git a/main/res/Resources/pgmodeler.icns b/apps/pgmodeler/res/Resources/pgmodeler.icns similarity index 100% rename from main/res/Resources/pgmodeler.icns rename to apps/pgmodeler/res/Resources/pgmodeler.icns diff --git a/main/res/Resources/pgmodeler_dbm.icns b/apps/pgmodeler/res/Resources/pgmodeler_dbm.icns similarity index 100% rename from main/res/Resources/pgmodeler_dbm.icns rename to apps/pgmodeler/res/Resources/pgmodeler_dbm.icns diff --git a/main/res/windows_ico.ico b/apps/pgmodeler/res/windows_ico.ico similarity index 100% rename from main/res/windows_ico.ico rename to apps/pgmodeler/res/windows_ico.ico diff --git a/main/res/windows_ico.qrc b/apps/pgmodeler/res/windows_ico.qrc similarity index 100% rename from main/res/windows_ico.qrc rename to apps/pgmodeler/res/windows_ico.qrc diff --git a/main/res/windows_ico1.ico b/apps/pgmodeler/res/windows_ico1.ico similarity index 100% rename from main/res/windows_ico1.ico rename to apps/pgmodeler/res/windows_ico1.ico diff --git a/apps/pgmodeler/src/main.cpp b/apps/pgmodeler/src/main.cpp new file mode 100644 index 0000000000..b6889231a1 --- /dev/null +++ b/apps/pgmodeler/src/main.cpp @@ -0,0 +1,139 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +#include "pgmodelerapp.h" +#include "mainwindow.h" + +#ifndef Q_OS_WIN +#include "execinfo.h" +#endif + +void startCrashHandler(int signal) +{ + QFile output; + QString lin, cmd; + + /** At the moment the backtrace function does not exists on MingW (Windows) this way + the code that generates the stacktrace is available only on Linux/Unix systems */ +#ifndef Q_OS_WIN + void *stack[30]; + size_t stack_size; + char **symbols=nullptr; + stack_size = backtrace(stack, 30); + symbols = backtrace_symbols(stack, stack_size); +#endif + + cmd=QString("\"%1\"").arg(GlobalAttributes::getPgModelerCHandlerPath()) + QString(" -style ") + GlobalAttributes::DefaultQtStyle; + + //Creates the stacktrace file + output.setFileName(GlobalAttributes::getTemporaryFilePath(GlobalAttributes::StacktraceFile)); + output.open(QFile::WriteOnly); + + if(output.isOpen()) + { + lin=QString("** pgModeler crashed after receive signal: %1 **\n\nDate/Time: %2 \nVersion: %3 \nBuild: %4 \n") + .arg(signal) + .arg(QDateTime::currentDateTime().toString(QString("yyyy-MM-dd hh:mm:ss"))) + .arg(GlobalAttributes::PgModelerVersion) + .arg(GlobalAttributes::PgModelerBuildNumber); + + lin+=QString("Compilation Qt version: %1\nRunning Qt version: %2\n\n") + .arg(QT_VERSION_STR) + .arg(qVersion()); + + output.write(lin.toStdString().c_str(), lin.size()); + +#ifndef Q_OS_WIN + for(size_t i=0; i < stack_size; i++) + { + lin=QString("[%1] ").arg(stack_size-1-i) + QString(symbols[i]) + QString("\n"); + output.write(lin.toStdString().c_str(), lin.size()); + } + free(symbols); +#else + lin=QString("** Stack trace unavailable on Windows system **"); + output.write(lin.toStdString().c_str(), lin.size()); +#endif + + output.close(); + } + + /* Changing the working dir to the main executable in order to call the crash handler + if the PGMODELER_CHANDLER_PATH isn't set */ + QDir dir; + dir.cd(QApplication::applicationDirPath()); + + exit(1 + system(cmd.toStdString().c_str())); +} + +int main(int argc, char **argv) +{ + try + { + /* Registering the below classes as metatypes in order to make + * them liable to be sent through signal parameters */ + qRegisterMetaType("ObjectType"); + qRegisterMetaType("Exception"); + qRegisterMetaType("ValidationInfo"); + qRegisterMetaType("ObjectsDiffInfo"); + + //Install a signal handler to start crashhandler when SIGSEGV or SIGABRT is emitted + signal(SIGSEGV, startCrashHandler); + signal(SIGABRT, startCrashHandler); + + PgModelerApp::setAttribute(Qt::AA_UseHighDpiPixmaps); + PgModelerApp::setAttribute(Qt::AA_EnableHighDpiScaling); + PgModelerApp app(argc,argv); + int res=0; + + //Loading the application splash screen + QSplashScreen splash; + QPixmap pix(QPixmap(QString(":images/images/pgmodeler_splash.png"))); + splash.setPixmap(pix); + splash.setMask(pix.mask()); + splash.show(); + app.processEvents(); + + //Creates the main form + MainWindow fmain; + + fmain.show(); + splash.finish(&fmain); + + //Loading models via command line on MacOSX are disabled until the file association work correclty on that system +#ifndef Q_OS_MAC + QStringList params=app.arguments(); + params.pop_front(); + + //If the user specifies a list of files to be loaded + if(!params.isEmpty()) + fmain.loadModels(params); +#endif + + res = app.exec(); + app.closeAllWindows(); + + return res; + } + catch(Exception &e) + { + QTextStream ts(stdout); + ts << e.getExceptionsText(); + return enum_cast(e.getErrorCode()); + } +} diff --git a/apps/pgmodeler/src/pgmodelerapp.cpp b/apps/pgmodeler/src/pgmodelerapp.cpp new file mode 100644 index 0000000000..61c2161e16 --- /dev/null +++ b/apps/pgmodeler/src/pgmodelerapp.cpp @@ -0,0 +1,158 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ +#include "pgmodelerapp.h" +#include "globalattributes.h" +#include "messagebox.h" +#include "attributes.h" + +PgModelerApp::PgModelerApp(int &argc, char **argv) : Application(argc,argv) +{ + QTranslator *main_translator=nullptr, *plugin_translator=nullptr; + QFile ui_style(GlobalAttributes::getTmplConfigurationFilePath("", + GlobalAttributes::UiStyleConf + + GlobalAttributes::ConfigurationExt)); + QString plugin_name, plug_lang_dir, plug_lang_file; + QStringList dir_list; + QDir dir; + + try + { + //Creating the initial user's configuration + createUserConfiguration(true); + } + catch(Exception &e) + { + Messagebox msgbox; + msgbox.show(e); + } + + //Checking if the user specified another widget style using the -style param + bool using_style=false; + + for(int i=0; i < argc && !using_style; i++) + using_style=QString(argv[i]).contains("-style"); + + //If no custom style is specified we force the usage of Fusion (the default for Qt and pgModeler) + if(!using_style) + setStyle(GlobalAttributes::DefaultQtStyle); + + //Changing the current working dir to the executable's directory in + QDir::setCurrent(this->applicationDirPath()); + + //Adding paths which executable will find plugins and it's dependecies + this->addLibraryPath(this->applicationDirPath()); + + //If pgModeler bundles plugins, add the root plugins path to lib search paths + if(dir.exists(GlobalAttributes::getPluginsDir())) + this->addLibraryPath(GlobalAttributes::getPluginsDir()); + + //Check if the temporary dir exists, if not, creates it. + if(!dir.exists(GlobalAttributes::getTemporaryDir())) + { + if(!dir.mkdir(GlobalAttributes::getTemporaryDir())) + { + Messagebox msg; + msg.show(Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotWritten).arg(GlobalAttributes::getTemporaryDir()), + ErrorCode::FileDirectoryNotWritten, __PRETTY_FUNCTION__,__FILE__,__LINE__)); + } + } + + //Trying to identify if the user defined a custom UI language in the pgmodeler.conf file + QString conf_file = GlobalAttributes::getConfigurationFilePath(GlobalAttributes::GeneralConf); + QFile input; + QString lang_id = QLocale::system().name(); + + input.setFileName(conf_file); + + if(input.open(QFile::ReadOnly)) + { + QString buf = QString(input.readAll()); + QRegExp regexp = QRegExp(QString("(%1)(.*)(=)(\\\")(.)+(\\\")(\\\n)").arg(Attributes::UiLanguage)); + int idx = regexp.indexIn(QString(buf)); + + //Extract the value of the ui-language attribute in the conf file + lang_id = buf.mid(idx, regexp.matchedLength()); + lang_id.remove(Attributes::UiLanguage); + lang_id.remove(QChar('"')).remove(QChar('=')).remove(QChar('\n')); + } + + //Tries to load the main ui translation according to the system's locale + main_translator=new QTranslator(this); + main_translator->load(lang_id, GlobalAttributes::getLanguagesDir()); + this->installTranslator(main_translator); + + //Trying to load plugins translations + dir_list=QDir(GlobalAttributes::getPluginsDir() + + GlobalAttributes::DirSeparator, + QString("*"), QDir::Name, QDir::AllDirs | QDir::NoDotAndDotDot).entryList(); + + while(!dir_list.isEmpty()) + { + plugin_name=dir_list.front(); + dir_list.pop_front(); + + //Configure the path to "lang" subdir at current plugin directory + plug_lang_dir=GlobalAttributes::getPluginsDir() + + GlobalAttributes::DirSeparator + plugin_name + + GlobalAttributes::DirSeparator + QString("lang") + + GlobalAttributes::DirSeparator; + + plug_lang_file=plugin_name + QString(".") + lang_id; + + //Check if the .qm file exists for the current plugin. If so create and install a translator + if(QFileInfo(plug_lang_dir + plug_lang_file + QString(".qm")).exists()) + { + plugin_translator=new QTranslator(this); + plugin_translator->load(plug_lang_file, plug_lang_dir); + this->installTranslator(plugin_translator); + } + } + + //Loading app style sheet + ui_style.open(QFile::ReadOnly); + + //Raises an error if ui style is not found + if(!ui_style.isOpen()) + { + Messagebox msg; + msg.show(Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotAccessed).arg(ui_style.fileName()), + ErrorCode::FileDirectoryNotAccessed,__PRETTY_FUNCTION__,__FILE__,__LINE__)); + } + else + this->setStyleSheet(ui_style.readAll()); +} + +bool PgModelerApp::notify(QObject *receiver, QEvent *event) +{ + try + { + return QApplication::notify(receiver,event); + } + catch(Exception &e) + { + Messagebox msg_box; + msg_box.show(e); + return false; + } + catch(...) + { + Messagebox msg_box; + msg_box.show(tr("Unknown exception caught!"), Messagebox::ErrorIcon); + return false; + } +} diff --git a/apps/pgmodeler/src/pgmodelerapp.h b/apps/pgmodeler/src/pgmodelerapp.h new file mode 100644 index 0000000000..39f7b22b30 --- /dev/null +++ b/apps/pgmodeler/src/pgmodelerapp.h @@ -0,0 +1,40 @@ +/* +# PostgreSQL Database Modeler (pgModeler) +# +# Copyright 2006-2021 - Raphael Araújo e Silva +# +# 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 version 3. +# +# 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. +# +# The complete text of GPLv3 is at LICENSE file on source code root directory. +# Also, you can get the complete GNU General Public License at +*/ + +/** +\ingroup pgmodeler +\class PgModelerApp +\brief This class inherits from QApplication and has the notify() method modified + to treat the exceptions raised by pgModeler components. +*/ + +#ifndef PGMODELER_APP_H +#define PGMODELER_APP_H + +#include "application.h" +#include +#include +#include + +class PgModelerApp: public Application { + public: + PgModelerApp(int & argc, char ** argv); + bool notify(QObject * receiver, QEvent * event); +}; + +#endif diff --git a/conf/connections.conf b/assets/conf/connections.conf similarity index 100% rename from conf/connections.conf rename to assets/conf/connections.conf diff --git a/conf/defaults/connections.conf b/assets/conf/defaults/connections.conf similarity index 100% rename from conf/defaults/connections.conf rename to assets/conf/defaults/connections.conf diff --git a/assets/conf/defaults/diff-presets.conf b/assets/conf/defaults/diff-presets.conf new file mode 100644 index 0000000000..47c1baa3c2 --- /dev/null +++ b/assets/conf/defaults/diff-presets.conf @@ -0,0 +1,23 @@ + + + + + diff --git a/assets/conf/defaults/example.dbm b/assets/conf/defaults/example.dbm new file mode 100644 index 0000000000..a19f1a289f --- /dev/null +++ b/assets/conf/defaults/example.dbm @@ -0,0 +1,238 @@ + + + + + + + + + + + + ] $br +%end + + $br + $br + +%if %not {split} %and {index} %then + {index} +%end + +{objects} + +[ ] + + $br + $br diff --git a/assets/schemas/datadict/index.sch b/assets/schemas/datadict/index.sch new file mode 100644 index 0000000000..c0395517c4 --- /dev/null +++ b/assets/schemas/datadict/index.sch @@ -0,0 +1,56 @@ +# Template code for data dictionary generation +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {split} %then + [ + + + Data dictionary generated by pgModeler + + + ] +%end + +$br [

Data dictionary index

] + +$br [ ]
    +$br [ ]
  • [Database: ] {name} + +%if {table} %then + $br [ ]

  • Tables + $br [ ]
      + {table} + $br [ ]
    + $br [ ]
  • +%end + +%if {foreigntable} %then + $br [ ]

  • [Foreign tables] + $br [ ]
      + {foreigntable} + $br [ ]
    + $br [ ]
  • +%end + +%if {view} %then + $br [ ]

  • Views + $br [ ]
      + {view} + $br [ ]
    + $br [ ]
  • +%end + +$br [ ]
+$br + +%if {split} %then + + [ ] + + $br + +%end diff --git a/assets/schemas/datadict/item.sch b/assets/schemas/datadict/item.sch new file mode 100644 index 0000000000..939097954b --- /dev/null +++ b/assets/schemas/datadict/item.sch @@ -0,0 +1,11 @@ +# Template code for data dictionary generation +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {split} %then + %set {link} {item} [.html] +%else + %set {link} \# {item} +%end + +$br [ ]
  • {item}
  • diff --git a/assets/schemas/datadict/link.sch b/assets/schemas/datadict/link.sch new file mode 100644 index 0000000000..7351e3d2e7 --- /dev/null +++ b/assets/schemas/datadict/link.sch @@ -0,0 +1,11 @@ +# Template code for data dictionary generation +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {split} %then + %set {link} {name} [.html] +%else + %set {link} \# {name} +%end + + {name} diff --git a/assets/schemas/datadict/styles.sch b/assets/schemas/datadict/styles.sch new file mode 100644 index 0000000000..71d164d01e --- /dev/null +++ b/assets/schemas/datadict/styles.sch @@ -0,0 +1,223 @@ +# Template code for data dictionary generation +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[body { +font-family: sans-serif; +color: \#333; +margin-left: 2em; +margin-top: 2em; +background-color: white; +} + +footer { +margin-top: 3em; +margin-bottom: .5em; +font-size: 75%; +} + +h3 { +margin-bottom: .5em; +} + +a { +color: \#4182c3; +text-decoration: none; +} + +a:hover { +color: \#080; +text-decoration: underline; +} + +\#index { +background-color: \#f8f9fa; +margin-block-end: 1.5em; +list-style: none; +display: inline-block; +padding: 1em; +border: 1px solid \#c0c0c0; +border-radius: 4px 4px 4px 4px; +} + +\#index li { +list-style: none; +margin: 0; +} + +\#index > li > ul { +padding-inline-start: 1em; +} + +.table, .foreigntable, .view { +font-size: 11pt; +border-collapse: collapse; +margin-top: 3em; +margin-bottom: 1em; +} + +.table caption { +background-color: \#d2f3ff; +} + +.foreigntable caption { +background-color: \#94f0b1; +} + +.view caption { +background-color: \#ffd8a1; +} + +.table, +.table caption, +.table th, +.table td { +border: 1px solid \#b4d0da; +} + +.foreigntable, +.foreigntable caption, +.foreigntable th, +.foreigntable td { +border: 1px solid \#6aad80; +} + +.view, +.view caption, +.view th, +.view td { +border: 1px solid \#ba7c00; +} + +.table caption, +.foreigntable caption, +.view caption { +border-bottom: 0; +} + +.table th, +.table .title, +.table .label{ +background-color: \#e9f8ff; +} + +.foreigntable th, +.foreigntable .title, +.foreigntable .label { +background-color: \#e2ffed; +} + +.view th, +.view .title, +.view .label { +background-color: \#ffebd2; +} + +.type-label { +float: right; +color: \#212529; +font-size: 70%; +font-weight: bold; +background-color: \#f8f9fa; +padding: 5px; +border-radius: 4px 4px 4px 4px; +} + +caption { +border-radius: 5px 5px 0 0; +} + +.nav-link { +font-size: 85%; +background-color: \#f2f2f3; +padding: 5px; +border-radius: 4px 4px 4px 4px; +color: \#212529; +font-weight: bold; +text-decoration: none; +margin-right: .5em; +} + +.nav-link:hover { +color: white; +background-color: \#007bff; +} + +td, th, caption, .title { +margin: 0; +padding: .3em; +} + +.title, th { +font-weight: bold; +text-align: center; +color: \#535c67; +} + +.data-type, .value, .constr-type { +font-family: monospace; +text-align: center; +} + +.constr-type { +color: \#24486c; +} + +.data-type { +color: \#b00; +} + +.bool-field { +text-align: center; +color: \#080; +} + +.label { +font-weight: bold; +color: \#444f53; +width: 1px; +white-space: nowrap; +} + +.tab-name { +font-size: 112%; +} + +.tab-description { +font-style: italic; +padding: .5em; +} + +.nested-tab-parent { +padding: 0; +} + +.nested-tab { +font-size: 11pt; +width: 100%; +border-collapse: collapse; +} + +.nested-tab > tbody > tr, +.nested-tab > tr{ +padding: 0; +} + +.nested-tab td { +border-bottom: 0; +border-left: 0; +} + +.nested-tab > tbody > tr:first-child td, +.nested-tab > tr:first-child td { +border-top: 0; +} + +.nested-tab td:last-child { +border-right: 0; +} + +.max-td-wth { +max-width: 500px; +} + +] diff --git a/assets/schemas/datadict/table.sch b/assets/schemas/datadict/table.sch new file mode 100644 index 0000000000..627eb41081 --- /dev/null +++ b/assets/schemas/datadict/table.sch @@ -0,0 +1,139 @@ +# Template code for data dictionary generation +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({type-class} == "table") %then + %set {colspan} 8 +%else + %set {colspan} 5 +%end + + +
    +$br [ ] +$br [ ] + +%if {comment} %then + $br [ ] + $br [ ] + $br [ ] +%end + +%if {columns} %then + $br [ ] + $br [ ] + $br [ ] + + %if ({type-class} == "table") %then + $br [ ] + $br [ ] + $br [ ] + %end + + $br [ ] + $br [ ] + $br [ ] + $br [ ] +%else + $br [ ] + $br [ ] + $br [ ] +%end + +$br [ ] +$br [ ] + +%if {columns} %then + {columns} +%end + +%if {constraints} %then + $br [ ] + $br [ ] + $br [ ] +%end + +$br [ ] + + +%if {inherit} %or {partitioned-table} %or {partition-tables} %then + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] $br +%end + +$br
    +$br [ ] {schema}.{name} +$br [ ] {type} +$br [ ]
    + {comment} + $br [ ]
    Name[Data type]PKFKUQ[Not null][Default value]Description
    + $br [ ] [No columns] + $br [ ]
    + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + + {constraints} + + $br [ ]
    Constraints
    NameTypeColumn(s)ReferencesExpressionDescription
    + $br [ ]
    + $br [ ] + + %if {inherit} %then + $br [ ] + $br [ ] + $br [ ] + $br [ ] + %end + + %if {partitioned-table} %then + $br [ ] + $br [ ] + $br [ ] + $br [ ] + %end + + %if {partition-tables} %then + $br [ ] + $br [ ] + $br [ ] + $br [ ] + %end + + $br [ ]
    Inherits: {inherit}
    [Partition of:]{partitioned-table}
    [Partitions:]{partition-tables}
    + $br [ ]
    $br + + +%if {index} %then + $br
    + + %if {split} %and {previous} %then + $br [ ] ← $sp {previous} + %end + + %if {split} %then + $br [ ] + %else + $br [ ] + %end + + [↑ Index] + + %if {split} %and {next} %then + $br [ ] {next} $sp → + %end + + $br
    $br +%end diff --git a/assets/schemas/datadict/view.sch b/assets/schemas/datadict/view.sch new file mode 100644 index 0000000000..4795f6352f --- /dev/null +++ b/assets/schemas/datadict/view.sch @@ -0,0 +1,80 @@ +# Template code for data dictionary generation +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + + +$br [ ] +$br [ ] + +%if {comment} %then + $br [ ] + $br [ ] + $br [ ] +%end + +%if {columns} %then + $br [ ] + $br [ ] + $br [ ] + $br [ ] +%else + $br [ ] + $br [ ] + $br [ ] +%end + +$br [ ] +$br [ ] + +%if {columns} %then + {columns} +%end + +$br [ ] + + +%if {references} %then + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] $br +%end + +$br
    +$br [ ] {schema}.{name} +$br [ ] {type} +$br [ ]
    + {comment} + $br [ ]
    Name[Data type]
    + $br [ ] [No columns] + $br [ ]
    + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ] + $br [ ]
    References: {references}
    + $br [ ]
    $br + +%if {index} %then + $br
    + + %if {split} %and {previous} %then + $br [ ] ← $sp {previous} + %end + + %if {split} %then + $br [ ] + %else + $br [ ] + %end + + [↑ Index] + + %if {split} %and {next} %then + $br [ ] {next} $sp → + %end + + $br
    $br +%end diff --git a/assets/schemas/sql/aggregate.sch b/assets/schemas/sql/aggregate.sch new file mode 100644 index 0000000000..953f0d71c2 --- /dev/null +++ b/assets/schemas/sql/aggregate.sch @@ -0,0 +1,35 @@ +# SQL definition for aggregate functions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE AGGREGATE ] {name} [ (]{types}[) (] $br +$tb [SFUNC = ] {transition}, $br +$tb [STYPE = ] {state-type} $br +%if {final} %then $tb [,FINALFUNC = ] {final} $br %end +%if {initial-cond} %then $tb [,INITCOND = ] {initial-cond} $br %end +%if {sort-op} %then $tb [,SORTOP = ] {sort-op} $br %end +); + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/cast.sch b/assets/schemas/sql/cast.sch new file mode 100644 index 0000000000..e2f868ba02 --- /dev/null +++ b/assets/schemas/sql/cast.sch @@ -0,0 +1,44 @@ +# SQL definition for type casts +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: cast] ( {source-type} [,] {destiny-type} ) [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE CAST (] {source-type} [ AS ] {destiny-type} ) $br + +%if {io-cast} %then + $tb [WITH INOUT ] +%else + %if {function} %then + $tb [WITH FUNCTION ] {function} + %else + $tb [WITHOUT FUNCTION] + %end +%end + +%if {cast-type} %then + $br $tb [AS ] {cast-type} +%end + +; + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/collation.sch b/assets/schemas/sql/collation.sch new file mode 100644 index 0000000000..2e12e9b19c --- /dev/null +++ b/assets/schemas/sql/collation.sch @@ -0,0 +1,92 @@ +# SQL definition for collations +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} != "9.0") %then + + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + %set {ddl-end} $br [-- ddl-end --] $br + %set {attr-sep} [,] $br + + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + [CREATE COLLATION ] {name} + + %if {collation} %then + [ FROM ] {collation} + %else + [ (] $br + + %if {locale} %then + [ LOCALE = '] + + {locale} + + %if {locale-mod} %then + @ {locale-mod} + %end + + ['] + %else + %if {lc-ctype} %then + [ LC_CTYPE = '] + + {lc-ctype} + + %if {lc-ctype-mod} %then + @ {lc-ctype-mod} + %end + + ['] + %end + + %if {lc-collate} %then + %if {lc-ctype} %then {attr-sep} %end + [ LC_COLLATE = '] + + {lc-collate} + + %if {lc-collate-mod} %then + @ {lc-collate-mod} + %end + + ['] + %end + %end + + %if ({pgsql-ver} >=f "10.0") %then + %if {provider} %then + %if {locale} %or {lc-collate} %or {lc-ctype} %then {attr-sep} %end + [ PROVIDER =] '{provider}' + %end + %end + + %if ({pgsql-ver} >=f "12.0") %then + %if {locale} %or {lc-collate} %or {lc-ctype} %or {provider} %then {attr-sep} %end + [ DETERMINISTIC = ] {deterministic} + %end + + $br [)] + %end + + ; + + {ddl-end} + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end diff --git a/assets/schemas/sql/column.sch b/assets/schemas/sql/column.sch new file mode 100644 index 0000000000..38dbd9d823 --- /dev/null +++ b/assets/schemas/sql/column.sch @@ -0,0 +1,81 @@ +# SQL definition for columns +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {decl-in-table} %then + $tb +%else + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + %if {table} %then + [ALTER TABLE ] {table} [ ADD COLUMN ] + %end +%end + +{name} $sp {type} + +%if {not-null} %then + [ NOT NULL] +%end + +%if ({pgsql-ver} >=f "10.0") %and {identity-type} %then + [ GENERATED ] {identity-type} [ AS IDENTITY ] + + %if {increment} %or {min-value} %or {max-value} %or {start} %or {cache} %or {cycle} %then + [(] + %end + + %if {increment} %then + [ INCREMENT BY ] {increment} + %end + + %if {min-value} %then + [ MINVALUE ] {min-value} + %end + + %if {max-value} %then + [ MAXVALUE ] {max-value} + %end + + %if {start} %then + [ START WITH ] {start} + %end + + %if {cache} %then + [ CACHE ] {cache} + %end + + %if {cycle} %then + [ CYCLE] + %end + + %if {increment} %or {min-value} %or {max-value} %or {start} %or {cache} %or {cycle} %then + [ )] + %end +%else + %if ({pgsql-ver} >=f "12.0") %and {generated} %then + [ GENERATED ALWAYS AS (] {default-value} [) STORED] + %else + %if {default-value} %then + [ DEFAULT ] {default-value} + %end + %end +%end + +%if {decl-in-table} %then + [,] +%else + [;] + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + $br [-- ddl-end --] $br + $br +%end + +%if %not {decl-in-table} %and {comment} %then + {comment} $br +%end + +$br diff --git a/assets/schemas/sql/comment.sch b/assets/schemas/sql/comment.sch new file mode 100644 index 0000000000..62529d17a7 --- /dev/null +++ b/assets/schemas/sql/comment.sch @@ -0,0 +1,20 @@ +# SQL definition for comments +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {comment} %or ({comment}=="unset") %then + [COMMENT ON ] {sql-object} $sp {signature} [ IS ] + + %if ({comment}=="unset") %then + '' + %else + %if {escape-comment} %then E %end + '{comment}' + %end + + ; $br + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + [-- ddl-end --] $br +%end diff --git a/assets/schemas/sql/confparam.sch b/assets/schemas/sql/confparam.sch new file mode 100644 index 0000000000..47ef58b327 --- /dev/null +++ b/assets/schemas/sql/confparam.sch @@ -0,0 +1,5 @@ +# SQL definition for functions/procedures configuration parameters definition +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb [SET ] {name} [ = ] {value} $br diff --git a/assets/schemas/sql/constraint.sch b/assets/schemas/sql/constraint.sch new file mode 100644 index 0000000000..eed812ff6a --- /dev/null +++ b/assets/schemas/sql/constraint.sch @@ -0,0 +1,83 @@ +# SQL definition for constraints +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {decl-in-table} %then + $tb +%else + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + + %if {table} %then + [-- ] {drop} + [ALTER TABLE ] {table} [ ADD ] + %end +%end + +[CONSTRAINT ] {name} + +%if {ck-constr} %then + [ CHECK ] ({expression}) + + %if {no-inherit} %then [ NO INHERIT] %end + +%end + +%if {pk-constr} %then [ PRIMARY KEY ] ({src-columns}) %end +%if {uq-constr} %then [ UNIQUE ] ({src-columns}) %end + +%if {ex-constr} %then + [ EXCLUDE ] $br + $tb + + %if {index-type} %then + [USING ] {index-type} + %end + + ( {elements} $br $tb ) +%end + +%if {pk-constr} %or {uq-constr} %then + %if {factor} %then + %if {decl-in-table} %then $br $tb %end + [ WITH (FILLFACTOR = ] {factor} [)] + %end +%end + +%if {tablespace} %then + $br + %if {decl-in-table} %then $tb %end + %if {pk-constr} %or {uq-constr} %or {ex-constr} %then [USING INDEX TABLESPACE ] {tablespace} %end +%end + +%if {ex-constr} %and {expression} %then + $sp WHERE $sp ( {expression}) +%end + +%if {fk-constr} %then + [ FOREIGN KEY ] ({src-columns}) $br + + %if {decl-in-table} %then $tb %end + [REFERENCES ] {ref-table} $sp ({dst-columns}) + $sp {comparison-type} $br + + %if {decl-in-table} %then $tb %end + [ON DELETE ] {del-action} [ ON UPDATE ] {upd-action} +%end + +%if {deferrable} %then + [ DEFERRABLE ] {defer-type} +%end + +%if {decl-in-table} %then [,] +%else + [;] $br + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + [-- ddl-end --] $br +%end + +%if %not {decl-in-table} %and {comment} %then + {comment} $br +%end + +$br diff --git a/assets/schemas/sql/conversion.sch b/assets/schemas/sql/conversion.sch new file mode 100644 index 0000000000..4333199c9c --- /dev/null +++ b/assets/schemas/sql/conversion.sch @@ -0,0 +1,33 @@ +# SQL definition for encoding conversions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +CREATE %if {default} %then [ DEFAULT] %end + +[ CONVERSION ] {name} $br +$tb [FOR ] '{src-encoding}' [ TO ] '{dst-encoding}' $br +$tb [FROM ] {function}; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/database.sch b/assets/schemas/sql/database.sch new file mode 100644 index 0000000000..c89d451a5e --- /dev/null +++ b/assets/schemas/sql/database.sch @@ -0,0 +1,68 @@ +# SQL definition for databases +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE DATABASE ] {name} + +%if {template} %then + $br $tb [TEMPLATE = ] {template} +%end + +%if {encoding} %then + $br $tb [ENCODING = ] {encoding} +%end + +%if {lc-collate} %then + $br $tb [LC_COLLATE = ] {lc-collate} +%end + +%if {lc-ctype} %then + $br $tb [LC_CTYPE = ] {lc-ctype} +%end + +%if {tablespace} %then + $br $tb [TABLESPACE = ] {tablespace} +%end + +%if {owner} %then + $br $tb [OWNER = ] {owner} +%end + +%if {connlimit} %then + $br $tb [CONNECTION LIMIT = ] {connlimit} +%end + +%if ({pgsql-ver} >=f "9.5") %then + %if ({is-template} == "true") %then + $br $tb [IS_TEMPLATE = ] {is-template} + %end + + %if ({allow-conns} == "false") %then + $br $tb [ALLOW_CONNECTIONS = ] {allow-conns} + %end +%end + +; + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/dbmodel.sch b/assets/schemas/sql/dbmodel.sch new file mode 100644 index 0000000000..0aff805c15 --- /dev/null +++ b/assets/schemas/sql/dbmodel.sch @@ -0,0 +1,57 @@ +# SQL definition for database model +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- Database generated with pgModeler (PostgreSQL Database Modeler).] $br +[-- pgModeler version: ] {pgmodeler-ver} $br +[-- PostgreSQL version: ] {pgsql-ver} $br +[-- Project Site: pgmodeler.io] $br +[-- Model Author: ] + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {author} %then + {author} +%else + --- +%end + +$br + +%if {export-to-file} %then + %if {role} %then {role} %end + + %if {tablespace} %then + [-- Tablespaces creation must be performed outside a multi lined SQL file. ] $br + [-- These commands were put in this file only as a convenience.] $br + [-- ] $br + {tablespace} $br + %end + + $br + + [-- Database creation must be performed outside a multi lined SQL file. ] $br + [-- These commands were put in this file only as a convenience.] $br + [-- ] $br + {database} $br +%end + +%if {function} %then + [SET check_function_bodies = false;] + + {ddl-end} $br +%end + +%if {schema} %then + {schema} + [SET search_path TO ] {search-path}; + {ddl-end} $br +%end + +%if {shell-types} %then {shell-types} %end +%if {objects} %then {objects} %end +%if {permission} %then {permission} %end + +$br diff --git a/assets/schemas/sql/domain.sch b/assets/schemas/sql/domain.sch new file mode 100644 index 0000000000..db830fffa4 --- /dev/null +++ b/assets/schemas/sql/domain.sch @@ -0,0 +1,47 @@ +# SQL definition for domains +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE DOMAIN ] {name} [ AS ] {type} + +%if ({pgsql-ver} != "9.0") %and {collation} %then + $br $tb [COLLATE ] {collation} +%end + +%if {default-value} %then + $br $tb [DEFAULT ] {default-value} +%end + +%if {not-null} %then + $br $tb [NOT NULL] +%end + +%if {constraints} %then + {constraints} +%end + +; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/domconstraint.sch b/assets/schemas/sql/domconstraint.sch new file mode 100644 index 0000000000..0e8c6beb2c --- /dev/null +++ b/assets/schemas/sql/domconstraint.sch @@ -0,0 +1,5 @@ +# SQL definition for domain's check constraint +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$br $tb CONSTRAINT $sp {name} $sp CHECK $sp ({expression}) diff --git a/assets/schemas/sql/drop.sch b/assets/schemas/sql/drop.sch new file mode 100644 index 0000000000..cd957794ed --- /dev/null +++ b/assets/schemas/sql/drop.sch @@ -0,0 +1,28 @@ +# SQL command to drop an object +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {collation} %and ({pgsql-ver} != "9.0") %or %not {collation} %then + %if %not {domain} %and {constraint} %or {column} %then + %if %not {decl-in-table} %then + [ALTER TABLE ] {table} [ DROP ] {sql-object} [ IF EXISTS ] + %end + %else + [DROP ] {sql-object} [ IF EXISTS ] + %end + + %if {column} %or {constraint} %and %not {decl-in-table} %or {extension} %then + {name} + %else + {signature} + %end + + %if {cascade} %and %not {database} %and %not {tablespace} %and %not {role} %and %not {usermapping} %then + [ CASCADE] + %end + + ; + + $br [-- ddl-end --] $br + +%end diff --git a/assets/schemas/sql/element.sch b/assets/schemas/sql/element.sch new file mode 100644 index 0000000000..4f9d417a60 --- /dev/null +++ b/assets/schemas/sql/element.sch @@ -0,0 +1,22 @@ +# SQL definition for operator class elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {function} %then + $tb FUNCTION $tb {stg-number} $tb {signature} +%end + +%if {operator} %then + $tb OPERATOR $tb {stg-number} $tb {signature} + + %if ({pgsql-ver} != "9.0") %then + %if {opfamily} %then + [ FOR ORDER BY ] {opfamily} + %else + [ FOR SEARCH ] + %end + %end +%end + +%if {storage} %then + $tb STORAGE $tb {type} +%end diff --git a/assets/schemas/sql/eventtrigger.sch b/assets/schemas/sql/eventtrigger.sch new file mode 100644 index 0000000000..9d0b3cb730 --- /dev/null +++ b/assets/schemas/sql/eventtrigger.sch @@ -0,0 +1,39 @@ +# SQL definition for event triggers +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} >=f "9.3") %then + + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + %set {ddl-end} $br [-- ddl-end --] $br + + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + [CREATE EVENT TRIGGER ] {name} + $br $tb [ON ] {event} + + %if {filter} %then + $br $tb [WHEN ] {filter} + %end + + $br $tb [EXECUTE PROCEDURE ] {function}; + + {ddl-end} + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end diff --git a/assets/schemas/sql/excelement.sch b/assets/schemas/sql/excelement.sch new file mode 100644 index 0000000000..9163aa22a4 --- /dev/null +++ b/assets/schemas/sql/excelement.sch @@ -0,0 +1,32 @@ +# SQL definition for exclude constraints elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$br $tb $sp $sp + +%if {column} %then + {column} +%else + %if {expression} %then + {expression} + %end +%end + +%if {opclass} %then + $sp {opclass} +%end + +%if {use-sorting} %then + %if {asc-order} %then + [ ASC ] + %else + [ DESC ] + %end + + %if {nulls-first} %then + [NULLS FIRST] + %else + [NULLS LAST] + %end +%end + +[ WITH ] {operator} diff --git a/assets/schemas/sql/extension.sch b/assets/schemas/sql/extension.sch new file mode 100644 index 0000000000..14a8f7f7d4 --- /dev/null +++ b/assets/schemas/sql/extension.sch @@ -0,0 +1,45 @@ +# SQL definition for extensions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} != "9.0") %then + + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + %set {ddl-end} $br [-- ddl-end --] $br + + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + [CREATE EXTENSION ] {name} $br + + %if {schema} %then + [WITH SCHEMA ] {schema} + %end + + %if {cur-version} %then + $br [VERSION ] '{cur-version}' + %end + + %if {old-version} %then + $br [FROM ] '{old-version}' + %end + + ; + + {ddl-end} + + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end diff --git a/assets/schemas/sql/foreigndatawrapper.sch b/assets/schemas/sql/foreigndatawrapper.sch new file mode 100644 index 0000000000..c5e8376b67 --- /dev/null +++ b/assets/schemas/sql/foreigndatawrapper.sch @@ -0,0 +1,53 @@ +# SQL definition for foreign data wrappers +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE ] {sql-object} $sp {name} + +%if ({pgsql-ver} >=f "9.1") %then + $br + + %if %not {handler} %then + [NO HANDLER] + %else + [HANDLER ] {handler} + %end +%end + +$br + +%if %not {validator} %then + [NO VALIDATOR] +%else + [VALIDATOR ] {validator} +%end + +%if {options} %then + $br [OPTIONS (] {options} ) +%end + +; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/foreignserver.sch b/assets/schemas/sql/foreignserver.sch new file mode 100644 index 0000000000..da01329494 --- /dev/null +++ b/assets/schemas/sql/foreignserver.sch @@ -0,0 +1,45 @@ +# SQL definition for foreign server +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE SERVER ] {name} + +%if {type} %then + [ TYPE ] '{type}' +%end + +%if {version} %then + [ VERSION ] '{version}' +%end + +$br [FOREIGN DATA WRAPPER ] {fdw} + +%if {options} %then + $br [OPTIONS (] {options} ) +%end + +; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/foreigntable.sch b/assets/schemas/sql/foreigntable.sch new file mode 100644 index 0000000000..7208e3c690 --- /dev/null +++ b/assets/schemas/sql/foreigntable.sch @@ -0,0 +1,80 @@ +# SQL definition for foreign tables +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE FOREIGN TABLE ] {name} + +%if ({pgsql-ver} >=f "10.0") %and {partitioned-table} %then + $br [PARTITION OF ] {partitioned-table} $sp +%end + +%if %not {partitioned-table} %or ({pgsql-ver} =f "10.0") %and {partitioned-table} %then + $br [FOR VALUES ] {partition-bound-expr} +%end + +%if {ancestor-table} %then $br [ INHERITS(] {ancestor-table} [)] %end +$br [SERVER ] {server} +%if {options} %then $br [OPTIONS (] {options} [)] %end + +; + +{ddl-end} + +%if {gen-alter-cmds} %then + %if {columns} %then $br {columns} %end + %if {constraints} %then $br {constraints} %end +%end + +%if {comment} %then {comment} %end +%if {cols-comment} %then {cols-comment} %end +%if {owner} %then {owner} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +%if {initial-data} %then + $br {initial-data} $br +%end + +$br diff --git a/assets/schemas/sql/function.sch b/assets/schemas/sql/function.sch new file mode 100644 index 0000000000..3e9a232c26 --- /dev/null +++ b/assets/schemas/sql/function.sch @@ -0,0 +1,90 @@ +# SQL definition for functions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE FUNCTION ] {name} $sp ( %if {parameters} %then {parameters} %end ) $br +$tb [RETURNS ] + +%if {return-table} %then + [TABLE ] ( {return-table} ) +%else + %if {returns-setof} %then [SETOF ] %end + {return-type} +%end + +$br + + +$tb [LANGUAGE ] {language} $br + +%if ({pgsql-ver} >=f "9.5") %and {transform-types} %then + $tb TRANSFORM {transform-types} $br +%end + +%if {window-func} %then + $tb WINDOW $br +%end + +$tb {function-type} $sp %if {leakproof} %then LEAKPROOF %end $br + +$tb {behavior-type} $br +$tb {security-type} $br + +%if ({pgsql-ver} >=f "9.6") %then + $tb {parallel-type} $br +%end + +$tb [COST ] {execution-cost} $br + +%if {returns-setof} %then + $tb [ROWS ] {row-amount} $br +%end + +%if {config-params} %then + {config-params} +%end + +$tb [AS ] + +%if {library} %then + '{library}' + + %if {symbol} %then + [, ] '{symbol}' + %end +%else + %if ({language} == "internal") %then + '{definition}' + %else + [$$] + + $br {definition} $br + [$$] + %end +%end + +; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/genericsql.sch b/assets/schemas/sql/genericsql.sch new file mode 100644 index 0000000000..3e889437f3 --- /dev/null +++ b/assets/schemas/sql/genericsql.sch @@ -0,0 +1,13 @@ +# SQL definition for generic sql objects +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: Generic SQL Object --] $br + +{definition} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +$br [-- ddl-end --] $br + +$br diff --git a/assets/schemas/sql/idxelement.sch b/assets/schemas/sql/idxelement.sch new file mode 100644 index 0000000000..b2ca055470 --- /dev/null +++ b/assets/schemas/sql/idxelement.sch @@ -0,0 +1,34 @@ +# SQL definition for index elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$br $tb + +%if {column} %then + {column} +%else + %if {expression} %then + ({expression}) + %end +%end + +%if ({pgsql-ver} != "9.0") %and {collation} %then + [ COLLATE ] {collation} +%end + +%if {opclass} %then + $sp {opclass} +%end + +%if {use-sorting} %then + %if {asc-order} %then + [ ASC ] + %else + [ DESC ] + %end + + %if {nulls-first} %then + [NULLS FIRST] + %else + [NULLS LAST] + %end +%end diff --git a/assets/schemas/sql/index.sch b/assets/schemas/sql/index.sch new file mode 100644 index 0000000000..b6e6574e7b --- /dev/null +++ b/assets/schemas/sql/index.sch @@ -0,0 +1,78 @@ +# SQL definition for indexes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE ] %if {unique} %then [UNIQUE ] %end [INDEX ] + +%if {concurrent} %then + [ CONCURRENTLY ] +%end + +{name} [ ON ] {table} + +%if {index-type} %then + $br [USING ] {index-type} +%end + +$br ( {elements} $br ) + +%if {expression} %then + $br ({expression}) $sp +%end + +%if ({pgsql-ver} >=f "11.0") %and {include-cols} %then + $br [INCLUDE ] ({include-cols}) +%end + +%if {stg-params} %then + $br [WITH (] + + %if {factor} %then + [FILLFACTOR = ] {factor} + %end + + %if {fast-update} %then + %if {factor} %then [, ] %end + [FASTUPDATE = ON] + %end + + %if {buffering} %and ({pgsql-ver} >=f "9.2") %then + %if {factor} %then [, ] %end + [BUFFERING = ON] + %end + + [)] +%end + +%if {tablespace} %then + $br [TABLESPACE ] {tablespace} +%end + +%if {predicate} %then + $br [WHERE (] {predicate} [)] +%end + +; + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/language.sch b/assets/schemas/sql/language.sch new file mode 100644 index 0000000000..7c50ea7f69 --- /dev/null +++ b/assets/schemas/sql/language.sch @@ -0,0 +1,52 @@ +# SQL definition for procedural languages +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE ] + +%if {trusted} %then + + %if {handler} %then + [TRUSTED ] + %end +%end + +[ LANGUAGE ] {name} + +%if {handler} %then + $br $tb [HANDLER ] {handler} +%end + +%if {validator} %then + $br [VALIDATOR ] {validator} +%end + +%if {inline} %then + $br [INLINE ] {inline} +%end + +; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/opclass.sch b/assets/schemas/sql/opclass.sch new file mode 100644 index 0000000000..f078ed7f11 --- /dev/null +++ b/assets/schemas/sql/opclass.sch @@ -0,0 +1,38 @@ +# SQL definition for operator classes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE OPERATOR CLASS ] {name} +%if {default} %then [ DEFAULT ] %end + +[ FOR TYPE ] {type} $br +[ USING ] {index-type} + +%if {family} %then [ FAMILY ] {family} %end +[ AS] $br + +{elements}; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/operator.sch b/assets/schemas/sql/operator.sch new file mode 100644 index 0000000000..96c87cc5ca --- /dev/null +++ b/assets/schemas/sql/operator.sch @@ -0,0 +1,65 @@ +# SQL definition for operators +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE OPERATOR ] {name} [ (] + +$br $tb [PROCEDURE = ] {operfunc} + +%if {left-type} %then + $br $tb [, LEFTARG = ] {left-type} +%end + +%if {right-type} %then + $br $tb [, RIGHTARG = ] {right-type} +%end + +%if {commutator-op} %then + $br $tb [, COMMUTATOR = ] OPERATOR({commutator-op}) +%end + +%if {negator-op} %then + $br $tb [, NEGATOR = ] OPERATOR({negator-op}) +%end + +%if {restriction} %then + $br $tb [, RESTRICT = ] {restriction} +%end + +%if {join} %then + $br $tb [, JOIN = ] {join} +%end + +%if {hashes} %then + $br $tb [, HASHES ] +%end + +%if {merges} %then + $br $tb [, MERGES ] +%end + +); + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/opfamily.sch b/assets/schemas/sql/opfamily.sch new file mode 100644 index 0000000000..b164024db6 --- /dev/null +++ b/assets/schemas/sql/opfamily.sch @@ -0,0 +1,29 @@ +# SQL definition for operator family +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE OPERATOR FAMILY ] {name} [ USING ] {index-type}; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/parameter.sch b/assets/schemas/sql/parameter.sch new file mode 100644 index 0000000000..1c0e958320 --- /dev/null +++ b/assets/schemas/sql/parameter.sch @@ -0,0 +1,22 @@ +# SQL definition for function parameters +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {variadic} %then + VARIADIC $sp +%else + %if {in} %then IN $sp %end + %if {out} %then OUT $sp %end +%end + +%if {reduced-form} %then + {type}, $sp +%else + {name} $sp {type} + + %if {default-value} %then + [ DEFAULT ] {default-value} + %end + + , $sp +%end diff --git a/assets/schemas/sql/partitionkey.sch b/assets/schemas/sql/partitionkey.sch new file mode 100644 index 0000000000..ef28c88691 --- /dev/null +++ b/assets/schemas/sql/partitionkey.sch @@ -0,0 +1,19 @@ +# SQL definition for partition key elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {column} %then + {column} +%else + %if {expression} %then + ({expression}) + %end +%end + +%if {collation} %then + [ COLLATE ] {collation} +%end + +%if {opclass} %then + $sp {opclass} +%end diff --git a/assets/schemas/sql/permission.sch b/assets/schemas/sql/permission.sch new file mode 100644 index 0000000000..8fecaf6785 --- /dev/null +++ b/assets/schemas/sql/permission.sch @@ -0,0 +1,71 @@ +# SQL definition for permissions on objects +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] PERMISSION [ --] + +%if {privileges} %then + + $br + + %if {revoke} %then + [REVOKE ] + %else + [GRANT ] + %end + + {privileges} $br + + %if {parent} %then + $sp $sp [ ON TABLE ] {parent} $br + %else + $sp $sp [ ON ] {type} $sp {object} $br + %end + + $sp $sp %if {revoke} %then [ FROM ] %else [ TO ] %end + + %if {roles} %then + {roles} + + %if {revoke} %and {cascade} %then + [ CASCADE] + %end + %else + PUBLIC + %end + + ; $br +%end + + +%if {privileges-gop} %then + + $br + + %if {revoke} %then + [REVOKE GRANT OPTION FOR ] + %else + [GRANT ] + %end + + {privileges-gop} $br + + %if {parent} %then + $sp $sp [ ON TABLE ] {parent} $br + %else + $sp $sp [ ON ] {type} $sp {object} $br + %end + + $sp $sp + + %if {revoke} %then + [ FROM ] {roles} + %if {cascade} %then [ CASCADE] %end ; $br + %else + [ TO ] {roles} [ WITH GRANT OPTION]; $br + %end +%end + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +[-- ddl-end --] $br $br diff --git a/assets/schemas/sql/policy.sch b/assets/schemas/sql/policy.sch new file mode 100644 index 0000000000..4d903f24b5 --- /dev/null +++ b/assets/schemas/sql/policy.sch @@ -0,0 +1,57 @@ +# SQL definition for policy +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} >=f "9.5") %then + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + %set {ddl-end} $br [-- ddl-end --] $br + + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + [CREATE POLICY ] {name} [ ON ] {table} + + %if ({pgsql-ver} >=f "10.0") %then + %if {permissive} %then + $br $tb [AS PERMISSIVE] + %else + $br $tb [AS RESTRICTIVE] + %end + %end + + $br $tb [FOR ] {command} + $br $tb [TO ] + + %if {roles} %then + {roles} + %else + PUBLIC + %end + + %if {using-exp} %then + $br $tb [USING (] {using-exp} [)] + %end + + %if {check-exp} %then + $br $tb [WITH CHECK (] {check-exp} [)] + %end + + ; + + {ddl-end} + + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end diff --git a/assets/schemas/sql/procedure.sch b/assets/schemas/sql/procedure.sch new file mode 100644 index 0000000000..3dc11e494b --- /dev/null +++ b/assets/schemas/sql/procedure.sch @@ -0,0 +1,59 @@ +# SQL definition for procedures +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} >=f "11.0") %then + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + %set {ddl-end} $br [-- ddl-end --] $br + + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + [CREATE PROCEDURE ] {name} $sp ( %if {parameters} %then {parameters} %end ) $br + $tb [LANGUAGE ] {language} $br + + %if {transform-types} %then + $tb TRANSFORM {transform-types} $br + %end + + $tb {security-type} $br + + %if {config-params} %then + {config-params} + %end + + $tb [AS ] + + %if {library} %then + '{library}' + + %if {symbol} %then + [, ] '{symbol}' + %end + %else + [$$] + + $br {definition} $br + [$$] + %end + + ; + + {ddl-end} + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end diff --git a/assets/schemas/sql/relationship.sch b/assets/schemas/sql/relationship.sch new file mode 100644 index 0000000000..ae16320a6a --- /dev/null +++ b/assets/schemas/sql/relationship.sch @@ -0,0 +1,17 @@ +# SQL definition for relationships +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {rel1n} %then + {constraints} +%end + +#%if {relgen} %then +# [ALTER TABLE ] {table} [ INHERIT ] {ancestor-table}; $br $br +#%end + +%if {relnn} %then + {table} + {constraints} +%end + diff --git a/assets/schemas/sql/role.sch b/assets/schemas/sql/role.sch new file mode 100644 index 0000000000..1672a8ccff --- /dev/null +++ b/assets/schemas/sql/role.sch @@ -0,0 +1,56 @@ +# SQL definition for type roles +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE ROLE ] {name} [ WITH ] + +%if {superuser} %then $br $tb SUPERUSER %end +%if {createdb} %then $br $tb CREATEDB %end +%if {createrole} %then $br $tb CREATEROLE %end +%if {inherit} %then $br $tb INHERIT %end +%if {login} %then $br $tb LOGIN %end + +%if {replication} %and ({pgsql-ver} != "9.0") %then $br $tb REPLICATION %end +%if {bypassrls} %and ({pgsql-ver} >=f "9.5") %then $br $tb BYPASSRLS %end + +%if {password} %then + $br $tb + + %if {encrypted} %then + ENCRYPTED + %else + UNENCRYPTED + %end + + [ PASSWORD ] '{password}' +%end + +%if {connlimit} %then $br $tb [CONNECTION LIMIT ] {connlimit} %end +%if {validity} %then $br $tb [VALID UNTIL ] '{validity}' %end + +%if {member-roles} %then $br $tb [ROLE ] {member-roles} %end +%if {admin-roles} %then $br $tb [ADMIN ] {admin-roles} %end +; + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/rule.sch b/assets/schemas/sql/rule.sch new file mode 100644 index 0000000000..49f30926c7 --- /dev/null +++ b/assets/schemas/sql/rule.sch @@ -0,0 +1,43 @@ +# SQL definition for rules +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE RULE ] {name} [ AS ] {event-type} $br +$tb [TO ] {table} $br + +%if {condition} %then + $tb [WHERE ] {condition} $br +%end + +$tb [DO ] {exec-type} $sp + +%if {commands} %then + ({commands}) +%else + NOTHING +%end + +; + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/schema.sch b/assets/schemas/sql/schema.sch new file mode 100644 index 0000000000..8eec1257f8 --- /dev/null +++ b/assets/schemas/sql/schema.sch @@ -0,0 +1,29 @@ +# SQL definition for schemas +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE SCHEMA ] {name}; + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/sequence.sch b/assets/schemas/sql/sequence.sch new file mode 100644 index 0000000000..3ea2b13772 --- /dev/null +++ b/assets/schemas/sql/sequence.sch @@ -0,0 +1,67 @@ +# SQL definition for sequences +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE SEQUENCE ] {name} $br + +%if {increment} %then + $tb [INCREMENT BY ] {increment} $br +%end + +%if {min-value} %then + $tb [MINVALUE ] {min-value} $br +%end + +%if {max-value} %then + $tb [MAXVALUE ] {max-value} $br +%end + +%if {start} %then + $tb [START WITH ] {start} $br +%end + +%if {cache} %then + $tb [CACHE ] {cache} $br +%end + +%if {cycle} %then + $tb CYCLE +%else + $tb [NO CYCLE] +%end + +$br + +$tb [OWNED BY ] +%if {owner-col} %then {owner-col} %else NONE %end +; $br + +%if {owner-col} %and %not {col-is-identity} %then + $br + [ALTER TABLE ] {table} [ ALTER COLUMN ] {column} $br + [ SET DEFAULT nextval('] {name} ['::regclass);] +%end + +{ddl-end} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/sessionopts.sch b/assets/schemas/sql/sessionopts.sch new file mode 100644 index 0000000000..f6e6a32060 --- /dev/null +++ b/assets/schemas/sql/sessionopts.sch @@ -0,0 +1,13 @@ +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {function} %then + [SET check_function_bodies = false;] + {ddl-end} $br +%end + +%if {search-path} %then + [SET search_path TO ] {search-path}; + {ddl-end} $br +%end diff --git a/assets/schemas/sql/table.sch b/assets/schemas/sql/table.sch new file mode 100644 index 0000000000..b60ad58122 --- /dev/null +++ b/assets/schemas/sql/table.sch @@ -0,0 +1,113 @@ +# SQL definition for tables +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE] + +%if ({pgsql-ver} != "9.0") %and {unlogged} %then + [ UNLOGGED] +%end + +[ TABLE ] {name} + +%if ({pgsql-ver} >=f "10.0") %and {partitioned-table} %then $br [PARTITION OF ] {partitioned-table} $sp %end + +%if %not {partitioned-table} %or ({pgsql-ver} =f "10.0") %and {partitioned-table} %then + %if {partition-bound-expr} %then + $br [FOR VALUES ] {partition-bound-expr} + %else + DEFAULT + %end +%end + +%if ({pgsql-ver} >=f "10.0") %and {partitioning} %then $br [PARTITION BY ] {partitioning} [ (] {partitionkey} [)] %end +%if {ancestor-table} %then $br [ INHERITS(] {ancestor-table} [)] %end +%if ({pgsql-ver} <=f "11.0") %and {oids} %then $br [WITH ( OIDS = TRUE )] %end + +%if {tablespace} %then + $br [TABLESPACE ] {tablespace} +%end + +; + +{ddl-end} + +%if {gen-alter-cmds} %then + %if {columns} %then $br {columns} %end + %if {constraints} %then $br {constraints} %end +%end + +%if {comment} %then {comment} %end +%if {cols-comment} %then {cols-comment} %end +%if {owner} %then {owner} %end + +%if ({pgsql-ver} >=f "9.5") %and {rls-enabled} %then + [ALTER TABLE ] {name} [ ENABLE ROW LEVEL SECURITY;] + + {ddl-end} + + %if {rls-forced} %then + [ALTER TABLE ] {name} [ FORCE ROW LEVEL SECURITY;] + + {ddl-end} + %end +%end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +%if {initial-data} %then + $br {initial-data} $br +%end + +$br diff --git a/assets/schemas/sql/tablespace.sch b/assets/schemas/sql/tablespace.sch new file mode 100644 index 0000000000..c651b84514 --- /dev/null +++ b/assets/schemas/sql/tablespace.sch @@ -0,0 +1,34 @@ +# SQL definition for tablespaces +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE TABLESPACE ] {name} $br + +%if {owner} %then + $tb [OWNER ] {owner} $br +%end + +$tb [LOCATION ] {directory}; $br + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/transform.sch b/assets/schemas/sql/transform.sch new file mode 100644 index 0000000000..b3020d74a6 --- /dev/null +++ b/assets/schemas/sql/transform.sch @@ -0,0 +1,48 @@ +# SQL definition for transforms +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} >=f "9.5") %then + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + %set {ddl-end} $br [-- ddl-end --] $br + + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + [CREATE TRANSFORM FOR ] {type} [ LANGUAGE ] {language} [ (] + + # One of the two function should be defined otherwise the code generation will fail + + %if {fromsql} %or %not {tosql} %then + $br $tb [FROM SQL WITH FUNCTION ] {fromsql} + %end + + %if {fromsql} %and {tosql} %then + , + %end + + %if {tosql} %or %not {fromsql} %then + $br $tb [TO SQL WITH FUNCTION ] {tosql} + %end + + $br [);] + + {ddl-end} + + %if {comment} %then + {comment} + %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end diff --git a/assets/schemas/sql/trigger.sch b/assets/schemas/sql/trigger.sch new file mode 100644 index 0000000000..af4a317d9e --- /dev/null +++ b/assets/schemas/sql/trigger.sch @@ -0,0 +1,59 @@ +# SQL definition for triggers +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE ] +%if {constraint} %then [CONSTRAINT ]%end +[TRIGGER ] {name} $br +$tb {firing-type} $sp {events} $br + +$tb [ON ] {table} $br + +%if {constraint} %then + %if {ref-table} %then + $tb [FROM ] {ref-table} $br + %end + + %if {deferrable} %then + $tb [DEFERRABLE ] {defer-type} $br + %else + $tb [NOT DEFERRABLE ] $br + %end +%end + +%if {old-table-name} %or {new-table-name} %and ({pgsql-ver} >=f "10.0") %then + $tb REFERENCING + %if {old-table-name} %then [ OLD TABLE AS ] {old-table-name} %end + %if {new-table-name} %then [ NEW TABLE AS ] {new-table-name} %end + $br +%end + +$tb [FOR EACH ] %if {per-line} %then ROW %else STATEMENT %end $br + +%if {condition} %then $tb WHEN $sp ({condition}) $br %end + +$tb [EXECUTE PROCEDURE ] {trigger-func}( +%if {arguments} %then {arguments} %end ); + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/typeattribute.sch b/assets/schemas/sql/typeattribute.sch new file mode 100644 index 0000000000..975df2dea8 --- /dev/null +++ b/assets/schemas/sql/typeattribute.sch @@ -0,0 +1,10 @@ +# SQL definition for user defined type attributes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ ] {name} $sp {type} + +%if ({pgsql-ver} != "9.0") %and {collation} %then + [ COLLATE ] {collation} +%end + +, $br diff --git a/assets/schemas/sql/usermapping.sch b/assets/schemas/sql/usermapping.sch new file mode 100644 index 0000000000..649dd34de7 --- /dev/null +++ b/assets/schemas/sql/usermapping.sch @@ -0,0 +1,38 @@ +# SQL definition for user mapping +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE USER MAPPING FOR ] + +%if {owner} %then {owner} %else PUBLIC %end $br + +[SERVER ] {server} + +%if {options} %then + $br [OPTIONS (] {options} ) +%end + +; + +{ddl-end} + +%if {comment} %then {comment} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/sql/usertype.sch b/assets/schemas/sql/usertype.sch new file mode 100644 index 0000000000..d1396e6681 --- /dev/null +++ b/assets/schemas/sql/usertype.sch @@ -0,0 +1,86 @@ +# SQL definition for user defined types +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +[CREATE TYPE ] {name} + +%if {reduced-form} %then + ; {ddl-end} $br +%else + %if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br + %end + + %if {base} %then + [ (] $br + %else + [ AS] $br + %end + + %if {composite} %then + ( $br {typeattrib} $br ); + %end + + %if {enumeration} %then + [ENUM ] ( + %if {labels} %then {labels} %end + [);] + %end + + %if ({pgsql-ver} >=f "9.2") %and {range} %then + [RANGE (] $br + [SUBTYPE = ] {subtype} + + %if {collation} %then $br [, COLLATE = ] {collation} %end + %if {opclass} %then $br [, SUBTYPE_OPCLASS = ] {opclass} %end + %if {canonical} %then $br [, CANONICAL = ] {canonical} %end + %if {subtypediff} %then $br [, SUBTYPE_DIFF = ] {subtypediff} %end + + ); + %end + + %if {base} %then + %if {input} %then $tb [INPUT = ] {input}, $br %end + %if {output} %then $tb [OUTPUT = ] {output} $br %end + %if {receive} %then $tb [, RECEIVE = ] {receive} $br %end + %if {send} %then $tb [, SEND = ] {send} $br %end + %if {tpmodin} %then $tb [, TYPMOD_IN = ] {tpmodin} $br %end + %if {tpmodout} %then $tb [, TYPMOD_OUT = ] {tpmodout} $br %end + %if {analyze} %then $tb [, ANALYZE = ] {analyze} $br %end + %if {internal-length} %then $tb [, INTERNALLENGTH = ] {internal-length} $br %end + %if {by-value} %then $tb [, PASSEDBYVALUE ] $br %end + %if {alignment} %then $tb [, ALIGNMENT = ] {alignment} $br %end + %if {storage} %then $tb [, STORAGE = ] {storage} $br %end + %if {default-value} %then $tb [, DEFAULT = ] {default-value} $br %end + %if {element} %then $tb [, ELEMENT = ] {element} $br %end + %if {delimiter} %then $tb [, DELIMITER = ] '{delimiter}' $br %end + %if {like-type} %then $tb [, LIKE = ] {like-type} $br %end + %if {category} %then $tb [, CATEGORY = ] '{category}' $br %end + %if {preferred} %then $tb [, PREFERRED = ] true $br %end + %if {collatable} %then $tb [, COLLATABLE = ] true $br %end + + ); + %end + + {ddl-end} + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + {ddl-end} + %end + + $br +%end + + diff --git a/assets/schemas/sql/view.sch b/assets/schemas/sql/view.sch new file mode 100644 index 0000000000..370c160c21 --- /dev/null +++ b/assets/schemas/sql/view.sch @@ -0,0 +1,68 @@ +# SQL definition for views +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[-- object: ] {name} [ | type: ] {sql-object} [ --] $br +[-- ] {drop} + +# This is a special token that pgModeler recognizes as end of DDL command +# when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! +%set {ddl-end} $br [-- ddl-end --] $br + +%if {prepended-sql} %then + {prepended-sql} + {ddl-end} $br +%end + +[CREATE ] + +%if ({pgsql-ver} >=f "9.3") %then + %if {recursive} %then + [RECURSIVE ] + %else + %if {materialized} %then + [MATERIALIZED ] + %end + %end +%end + +VIEW $sp {name} + +%if {columns} %then + [ (] {columns} [)] +%end + +$br + +%if ({pgsql-ver} >=f "9.3") %then + %if {materialized} %and {tablespace} %then + TABLESPACE $sp {tablespace} $br + %end +%end + +[AS ] $br + +#Commom table expression (CTE) +%if {cte-exp} %then + [WITH ] {cte-exp} +%end + +$br {definition} + +%if ({pgsql-ver} >=f "9.3") %then + %if {materialized} %and {with-no-data} %then + $br [WITH NO DATA] + %end +%end + +{ddl-end} + +%if {comment} %then {comment} %end +%if {owner} %then {owner} %end + +%if {appended-sql} %then + {appended-sql} + {ddl-end} +%end + +$br diff --git a/assets/schemas/xml/aggregate.sch b/assets/schemas/xml/aggregate.sch new file mode 100644 index 0000000000..e5f45ab60f --- /dev/null +++ b/assets/schemas/xml/aggregate.sch @@ -0,0 +1,31 @@ +# XML definition for aggregate functions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br +{schema} +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +%if {types} %then {types} %end + +{state-type} +{transition} +%if {final} %then {final} %end +%if {sort-op} %then {sort-op} %end + $br $br diff --git a/assets/schemas/xml/appendedsql.sch b/assets/schemas/xml/appendedsql.sch new file mode 100644 index 0000000000..7a0464e8b3 --- /dev/null +++ b/assets/schemas/xml/appendedsql.sch @@ -0,0 +1,9 @@ +# XML definition for appendend SQL commands +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +#Creates element envolving the appended-sql +#The tag is converted to in order +#to not cause syntax errors on the schema parser + +$tb $br diff --git a/assets/schemas/xml/basetype.sch b/assets/schemas/xml/basetype.sch new file mode 100644 index 0000000000..a01de4f8e2 --- /dev/null +++ b/assets/schemas/xml/basetype.sch @@ -0,0 +1,36 @@ +# XML definition for native types +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb [ $br diff --git a/assets/schemas/xml/cast.sch b/assets/schemas/xml/cast.sch new file mode 100644 index 0000000000..c9cc112517 --- /dev/null +++ b/assets/schemas/xml/cast.sch @@ -0,0 +1,33 @@ +# XML definition for type casts +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +{source-type} +{destiny-type} + +%if {function} %then {function} %end + + $br $br diff --git a/assets/schemas/xml/changelog.sch b/assets/schemas/xml/changelog.sch new file mode 100644 index 0000000000..1016268dc8 --- /dev/null +++ b/assets/schemas/xml/changelog.sch @@ -0,0 +1,9 @@ +# XML definition for database model changelog +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {entry} %then + $br $br + {entry} + $br +%end diff --git a/assets/schemas/xml/collation.sch b/assets/schemas/xml/collation.sch new file mode 100644 index 0000000000..d8112ed102 --- /dev/null +++ b/assets/schemas/xml/collation.sch @@ -0,0 +1,34 @@ +# XML definition for collations +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {reduced-form} %then $tb %end + + $br + + %if {schema} %then {schema} %end + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + + +%else + /> $br +%end diff --git a/assets/schemas/xml/column.sch b/assets/schemas/xml/column.sch new file mode 100644 index 0000000000..9e0a02bcc2 --- /dev/null +++ b/assets/schemas/xml/column.sch @@ -0,0 +1,52 @@ +# XML definition for columns +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb [ $br + +$tb {type} + +%if {comment} %then $tb {comment} %end + +$tb $br diff --git a/assets/schemas/xml/comment.sch b/assets/schemas/xml/comment.sch new file mode 100644 index 0000000000..7f00894063 --- /dev/null +++ b/assets/schemas/xml/comment.sch @@ -0,0 +1,9 @@ +# XML definition for comments +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +#Creates element envolving the comment +#The tag is converted to in order +#to not cause syntax errors on the schema parser + +$tb $br \ No newline at end of file diff --git a/assets/schemas/xml/confparam.sch b/assets/schemas/xml/confparam.sch new file mode 100644 index 0000000000..77ecd77962 --- /dev/null +++ b/assets/schemas/xml/confparam.sch @@ -0,0 +1,5 @@ +# XML definition for functions/procedures configuration parameters definition +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb $br diff --git a/assets/schemas/xml/constraint.sch b/assets/schemas/xml/constraint.sch new file mode 100644 index 0000000000..3e5f8e85ff --- /dev/null +++ b/assets/schemas/xml/constraint.sch @@ -0,0 +1,83 @@ +# XML definition for constraints +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {decl-in-table} %then $tb %end + +[ $br + +%if {tablespace} %then $tb {tablespace} %end + +%if {decl-in-table} %then $tb %end + +%if {src-columns} %then + $tb $br +%end + +%if {dst-columns} %then + %if {decl-in-table} %then $tb %end + $tb $br +%end + +%if {ex-constr} %then + {elements} +%end + +%if {ck-constr} %or {ex-constr} %then + %if {expression} %then + %if {decl-in-table} %then $tb %end + $tb $br + %end +%end + +%if {comment} %then $tb {comment} %end + +%if {decl-in-table} %then $tb %end + $br +%if %not {decl-in-table} %then $br %end diff --git a/assets/schemas/xml/conversion.sch b/assets/schemas/xml/conversion.sch new file mode 100644 index 0000000000..42b0ad54e3 --- /dev/null +++ b/assets/schemas/xml/conversion.sch @@ -0,0 +1,30 @@ +# XML definition for type encoding conversion +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +{schema} +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +{function} + + $br $br diff --git a/assets/schemas/xml/customidxs.sch b/assets/schemas/xml/customidxs.sch new file mode 100644 index 0000000000..ff20ceece3 --- /dev/null +++ b/assets/schemas/xml/customidxs.sch @@ -0,0 +1,6 @@ +# XML definition for custom object indexes in tables +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$br $tb [ $br +{objects} +$tb diff --git a/assets/schemas/xml/database.sch b/assets/schemas/xml/database.sch new file mode 100644 index 0000000000..e7b5c80860 --- /dev/null +++ b/assets/schemas/xml/database.sch @@ -0,0 +1,34 @@ +# XML definition for tablespaces +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +%if {owner} %then {owner} %end +%if {tablespace} %then {tablespace} %end +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + + $br $br diff --git a/assets/schemas/xml/dbmodel.sch b/assets/schemas/xml/dbmodel.sch new file mode 100644 index 0000000000..07edaf489a --- /dev/null +++ b/assets/schemas/xml/dbmodel.sch @@ -0,0 +1,80 @@ +# XML definition for database model +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + $br +[] $br + $br +%if {objects} %then {objects} %end +%if {permission} %then {permission} %end +%if {changelog} %then {changelog} %end + $br diff --git a/assets/schemas/xml/domain.sch b/assets/schemas/xml/domain.sch new file mode 100644 index 0000000000..0ceacbc5ff --- /dev/null +++ b/assets/schemas/xml/domain.sch @@ -0,0 +1,41 @@ +# XML definition for domains +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br +%else + + #%if {constraint} %then + # [ constraint=] "{constraint}" + #%end + + [ not-null=] %if {not-null} %then "true" %else "false" %end + %if {default-value} %then [ default-value=] "{default-value}" %end + + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + > $br + + {schema} + %if {owner} %then {owner} %end + %if {collation} %then {collation} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + {type} + + %if {constraints} %then + {constraints} + %end + + $br $br +%end diff --git a/assets/schemas/xml/domconstraint.sch b/assets/schemas/xml/domconstraint.sch new file mode 100644 index 0000000000..e074ad4ab7 --- /dev/null +++ b/assets/schemas/xml/domconstraint.sch @@ -0,0 +1,8 @@ +# XML definition for domain's check constraint +# PostgreSQL Version: 9.x +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb [] $br +$tb $tb $br +$tb [] $br diff --git a/schemas/xml/dtd/aggregate.dtd b/assets/schemas/xml/dtd/aggregate.dtd similarity index 100% rename from schemas/xml/dtd/aggregate.dtd rename to assets/schemas/xml/dtd/aggregate.dtd diff --git a/schemas/xml/dtd/baseelements.dtd b/assets/schemas/xml/dtd/baseelements.dtd similarity index 80% rename from schemas/xml/dtd/baseelements.dtd rename to assets/schemas/xml/dtd/baseelements.dtd index 9b963d26ce..41d2366878 100644 --- a/schemas/xml/dtd/baseelements.dtd +++ b/assets/schemas/xml/dtd/baseelements.dtd @@ -23,3 +23,10 @@ + + + + + + + diff --git a/schemas/xml/dtd/basetype.dtd b/assets/schemas/xml/dtd/basetype.dtd similarity index 100% rename from schemas/xml/dtd/basetype.dtd rename to assets/schemas/xml/dtd/basetype.dtd diff --git a/schemas/xml/dtd/cast.dtd b/assets/schemas/xml/dtd/cast.dtd similarity index 100% rename from schemas/xml/dtd/cast.dtd rename to assets/schemas/xml/dtd/cast.dtd diff --git a/assets/schemas/xml/dtd/changelog.dtd b/assets/schemas/xml/dtd/changelog.dtd new file mode 100644 index 0000000000..2b44a79887 --- /dev/null +++ b/assets/schemas/xml/dtd/changelog.dtd @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/assets/schemas/xml/dtd/collation.dtd b/assets/schemas/xml/dtd/collation.dtd new file mode 100644 index 0000000000..7a067b87be --- /dev/null +++ b/assets/schemas/xml/dtd/collation.dtd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/assets/schemas/xml/dtd/column.dtd b/assets/schemas/xml/dtd/column.dtd new file mode 100644 index 0000000000..0a8fde39b1 --- /dev/null +++ b/assets/schemas/xml/dtd/column.dtd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/schemas/xml/dtd/constraint.dtd b/assets/schemas/xml/dtd/constraint.dtd similarity index 96% rename from schemas/xml/dtd/constraint.dtd rename to assets/schemas/xml/dtd/constraint.dtd index be1946fbdb..55588c535c 100644 --- a/schemas/xml/dtd/constraint.dtd +++ b/assets/schemas/xml/dtd/constraint.dtd @@ -4,6 +4,7 @@ --> + diff --git a/schemas/xml/dtd/conversion.dtd b/assets/schemas/xml/dtd/conversion.dtd similarity index 100% rename from schemas/xml/dtd/conversion.dtd rename to assets/schemas/xml/dtd/conversion.dtd diff --git a/schemas/xml/dtd/customidxs.dtd b/assets/schemas/xml/dtd/customidxs.dtd similarity index 100% rename from schemas/xml/dtd/customidxs.dtd rename to assets/schemas/xml/dtd/customidxs.dtd diff --git a/schemas/xml/dtd/database.dtd b/assets/schemas/xml/dtd/database.dtd similarity index 100% rename from schemas/xml/dtd/database.dtd rename to assets/schemas/xml/dtd/database.dtd diff --git a/assets/schemas/xml/dtd/dbmodel.dtd b/assets/schemas/xml/dtd/dbmodel.dtd new file mode 100644 index 0000000000..3d3ce36055 --- /dev/null +++ b/assets/schemas/xml/dtd/dbmodel.dtd @@ -0,0 +1,105 @@ + + +%baseelements; + +%basetype; + +%object; + +%role; + +%tablespace; + +%database; + +%schema; + +%language; + +%parameter; + +%function; + +%usertype; + +%cast; + +%conversion; + +%operator; + +%opfamily; + +%opclass; + +%aggregate; + +%domain; + +%index; + +%rule; + +%trigger; + +%table; + +%sequence; + +%view; + +%textbox; + +%relationship; + +%permission; + +%collation; + +%extension; + +%tag; + +%customidxs; + +%eventtrigger; + +%genericsql; + +%policy; + +%foreigndatawrapper; + +%foreignserver; + +%usermapping; + +%foreigntable; + +%transform; + +%procedure; + +%changelog; + + + + + + + + + + + + + + + + + + + diff --git a/schemas/xml/dtd/domain.dtd b/assets/schemas/xml/dtd/domain.dtd similarity index 100% rename from schemas/xml/dtd/domain.dtd rename to assets/schemas/xml/dtd/domain.dtd diff --git a/schemas/xml/dtd/element.dtd b/assets/schemas/xml/dtd/element.dtd similarity index 100% rename from schemas/xml/dtd/element.dtd rename to assets/schemas/xml/dtd/element.dtd diff --git a/schemas/xml/dtd/eventtrigger.dtd b/assets/schemas/xml/dtd/eventtrigger.dtd similarity index 100% rename from schemas/xml/dtd/eventtrigger.dtd rename to assets/schemas/xml/dtd/eventtrigger.dtd diff --git a/schemas/xml/dtd/extension.dtd b/assets/schemas/xml/dtd/extension.dtd similarity index 100% rename from schemas/xml/dtd/extension.dtd rename to assets/schemas/xml/dtd/extension.dtd diff --git a/assets/schemas/xml/dtd/foreigndatawrapper.dtd b/assets/schemas/xml/dtd/foreigndatawrapper.dtd new file mode 100644 index 0000000000..78b4689c6e --- /dev/null +++ b/assets/schemas/xml/dtd/foreigndatawrapper.dtd @@ -0,0 +1,9 @@ + + + + + + diff --git a/assets/schemas/xml/dtd/foreignserver.dtd b/assets/schemas/xml/dtd/foreignserver.dtd new file mode 100644 index 0000000000..b9abb46e87 --- /dev/null +++ b/assets/schemas/xml/dtd/foreignserver.dtd @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/assets/schemas/xml/dtd/foreigntable.dtd b/assets/schemas/xml/dtd/foreigntable.dtd new file mode 100644 index 0000000000..647ef0e08e --- /dev/null +++ b/assets/schemas/xml/dtd/foreigntable.dtd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/schemas/xml/dtd/function.dtd b/assets/schemas/xml/dtd/function.dtd new file mode 100644 index 0000000000..180e0fcea1 --- /dev/null +++ b/assets/schemas/xml/dtd/function.dtd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/schemas/xml/dtd/genericsql.dtd b/assets/schemas/xml/dtd/genericsql.dtd similarity index 88% rename from schemas/xml/dtd/genericsql.dtd rename to assets/schemas/xml/dtd/genericsql.dtd index 40ec0a02f5..f1a1c8ea5a 100644 --- a/schemas/xml/dtd/genericsql.dtd +++ b/assets/schemas/xml/dtd/genericsql.dtd @@ -2,7 +2,7 @@ CAUTION: Do not modify this file directly on it's code unless you know what you are doing. Unexpected results may occur if the code is changed deliberately. --> - + diff --git a/schemas/xml/dtd/index.dtd b/assets/schemas/xml/dtd/index.dtd similarity index 92% rename from schemas/xml/dtd/index.dtd rename to assets/schemas/xml/dtd/index.dtd index f7d02fe9e3..4f6da04967 100644 --- a/schemas/xml/dtd/index.dtd +++ b/assets/schemas/xml/dtd/index.dtd @@ -1,9 +1,10 @@ - - + + diff --git a/schemas/xml/dtd/label.dtd b/assets/schemas/xml/dtd/label.dtd similarity index 100% rename from schemas/xml/dtd/label.dtd rename to assets/schemas/xml/dtd/label.dtd diff --git a/schemas/xml/dtd/language.dtd b/assets/schemas/xml/dtd/language.dtd similarity index 100% rename from schemas/xml/dtd/language.dtd rename to assets/schemas/xml/dtd/language.dtd diff --git a/assets/schemas/xml/dtd/metadata.dtd b/assets/schemas/xml/dtd/metadata.dtd new file mode 100644 index 0000000000..5dc502ee98 --- /dev/null +++ b/assets/schemas/xml/dtd/metadata.dtd @@ -0,0 +1,57 @@ + + +%baseelements; + + +%label; + + +%textbox; + + +%tag; + + +%object; + + +%genericsql; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/schemas/xml/dtd/object.dtd b/assets/schemas/xml/dtd/object.dtd new file mode 100644 index 0000000000..2047dd8dc2 --- /dev/null +++ b/assets/schemas/xml/dtd/object.dtd @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/schemas/xml/dtd/opclass.dtd b/assets/schemas/xml/dtd/opclass.dtd similarity index 100% rename from schemas/xml/dtd/opclass.dtd rename to assets/schemas/xml/dtd/opclass.dtd diff --git a/schemas/xml/dtd/operator.dtd b/assets/schemas/xml/dtd/operator.dtd similarity index 100% rename from schemas/xml/dtd/operator.dtd rename to assets/schemas/xml/dtd/operator.dtd diff --git a/schemas/xml/dtd/opfamily.dtd b/assets/schemas/xml/dtd/opfamily.dtd similarity index 100% rename from schemas/xml/dtd/opfamily.dtd rename to assets/schemas/xml/dtd/opfamily.dtd diff --git a/assets/schemas/xml/dtd/parameter.dtd b/assets/schemas/xml/dtd/parameter.dtd new file mode 100644 index 0000000000..23c9c3c698 --- /dev/null +++ b/assets/schemas/xml/dtd/parameter.dtd @@ -0,0 +1,10 @@ + + + + + + + diff --git a/schemas/xml/dtd/permission.dtd b/assets/schemas/xml/dtd/permission.dtd similarity index 77% rename from schemas/xml/dtd/permission.dtd rename to assets/schemas/xml/dtd/permission.dtd index f7db5da3d0..a470a5c0ca 100644 --- a/schemas/xml/dtd/permission.dtd +++ b/assets/schemas/xml/dtd/permission.dtd @@ -21,10 +21,3 @@ - - - - - - - diff --git a/schemas/xml/dtd/policy.dtd b/assets/schemas/xml/dtd/policy.dtd similarity index 93% rename from schemas/xml/dtd/policy.dtd rename to assets/schemas/xml/dtd/policy.dtd index bc5c4d06b3..eba99706e2 100644 --- a/schemas/xml/dtd/policy.dtd +++ b/assets/schemas/xml/dtd/policy.dtd @@ -4,6 +4,7 @@ --> + diff --git a/assets/schemas/xml/dtd/procedure.dtd b/assets/schemas/xml/dtd/procedure.dtd new file mode 100644 index 0000000000..0a2df993bb --- /dev/null +++ b/assets/schemas/xml/dtd/procedure.dtd @@ -0,0 +1,10 @@ + + + + + + + diff --git a/schemas/xml/dtd/relationship.dtd b/assets/schemas/xml/dtd/relationship.dtd similarity index 92% rename from schemas/xml/dtd/relationship.dtd rename to assets/schemas/xml/dtd/relationship.dtd index 01baad3ad9..6e51e3216b 100644 --- a/schemas/xml/dtd/relationship.dtd +++ b/assets/schemas/xml/dtd/relationship.dtd @@ -5,11 +5,13 @@ %label; - + + + - + diff --git a/schemas/xml/dtd/role.dtd b/assets/schemas/xml/dtd/role.dtd similarity index 93% rename from schemas/xml/dtd/role.dtd rename to assets/schemas/xml/dtd/role.dtd index da52230792..81062e2d4a 100644 --- a/schemas/xml/dtd/role.dtd +++ b/assets/schemas/xml/dtd/role.dtd @@ -1,4 +1,4 @@ - @@ -20,4 +20,4 @@ - + diff --git a/schemas/xml/dtd/rule.dtd b/assets/schemas/xml/dtd/rule.dtd similarity index 93% rename from schemas/xml/dtd/rule.dtd rename to assets/schemas/xml/dtd/rule.dtd index a340b78336..0ce3103323 100644 --- a/schemas/xml/dtd/rule.dtd +++ b/assets/schemas/xml/dtd/rule.dtd @@ -4,6 +4,7 @@ --> + diff --git a/schemas/xml/dtd/schema.dtd b/assets/schemas/xml/dtd/schema.dtd similarity index 87% rename from schemas/xml/dtd/schema.dtd rename to assets/schemas/xml/dtd/schema.dtd index 8e17e3fc82..86d5184de6 100644 --- a/schemas/xml/dtd/schema.dtd +++ b/assets/schemas/xml/dtd/schema.dtd @@ -4,6 +4,8 @@ --> + + diff --git a/schemas/xml/dtd/sequence.dtd b/assets/schemas/xml/dtd/sequence.dtd similarity index 100% rename from schemas/xml/dtd/sequence.dtd rename to assets/schemas/xml/dtd/sequence.dtd diff --git a/assets/schemas/xml/dtd/table.dtd b/assets/schemas/xml/dtd/table.dtd new file mode 100644 index 0000000000..a01ca763f6 --- /dev/null +++ b/assets/schemas/xml/dtd/table.dtd @@ -0,0 +1,36 @@ + + +%column; + +%constraint; + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schemas/xml/dtd/tablespace.dtd b/assets/schemas/xml/dtd/tablespace.dtd similarity index 100% rename from schemas/xml/dtd/tablespace.dtd rename to assets/schemas/xml/dtd/tablespace.dtd diff --git a/schemas/xml/dtd/tag.dtd b/assets/schemas/xml/dtd/tag.dtd similarity index 82% rename from schemas/xml/dtd/tag.dtd rename to assets/schemas/xml/dtd/tag.dtd index 72cdefd1f3..0fe1591be4 100644 --- a/schemas/xml/dtd/tag.dtd +++ b/assets/schemas/xml/dtd/tag.dtd @@ -8,4 +8,4 @@ - + diff --git a/schemas/xml/dtd/textbox.dtd b/assets/schemas/xml/dtd/textbox.dtd similarity index 87% rename from schemas/xml/dtd/textbox.dtd rename to assets/schemas/xml/dtd/textbox.dtd index 5c3c86984a..8c046ea264 100644 --- a/schemas/xml/dtd/textbox.dtd +++ b/assets/schemas/xml/dtd/textbox.dtd @@ -4,6 +4,7 @@ --> + @@ -11,3 +12,4 @@ + diff --git a/assets/schemas/xml/dtd/transform.dtd b/assets/schemas/xml/dtd/transform.dtd new file mode 100644 index 0000000000..b4215616cb --- /dev/null +++ b/assets/schemas/xml/dtd/transform.dtd @@ -0,0 +1,7 @@ + + + + diff --git a/schemas/xml/dtd/trigger.dtd b/assets/schemas/xml/dtd/trigger.dtd similarity index 87% rename from schemas/xml/dtd/trigger.dtd rename to assets/schemas/xml/dtd/trigger.dtd index 22d745cd16..6c6f8672f9 100644 --- a/schemas/xml/dtd/trigger.dtd +++ b/assets/schemas/xml/dtd/trigger.dtd @@ -4,6 +4,7 @@ --> + @@ -18,3 +19,5 @@ + + diff --git a/assets/schemas/xml/dtd/usermapping.dtd b/assets/schemas/xml/dtd/usermapping.dtd new file mode 100644 index 0000000000..bf99399153 --- /dev/null +++ b/assets/schemas/xml/dtd/usermapping.dtd @@ -0,0 +1,9 @@ + + + + + + diff --git a/schemas/xml/dtd/usertype.dtd b/assets/schemas/xml/dtd/usertype.dtd similarity index 93% rename from schemas/xml/dtd/usertype.dtd rename to assets/schemas/xml/dtd/usertype.dtd index 6883df89ee..223d14841e 100644 --- a/schemas/xml/dtd/usertype.dtd +++ b/assets/schemas/xml/dtd/usertype.dtd @@ -1,8 +1,8 @@ - - + @@ -19,7 +19,7 @@ - + diff --git a/assets/schemas/xml/dtd/view.dtd b/assets/schemas/xml/dtd/view.dtd new file mode 100644 index 0000000000..b2329b4971 --- /dev/null +++ b/assets/schemas/xml/dtd/view.dtd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/schemas/xml/element.sch b/assets/schemas/xml/element.sch new file mode 100644 index 0000000000..6eae11f925 --- /dev/null +++ b/assets/schemas/xml/element.sch @@ -0,0 +1,16 @@ +# XML definition for operator classes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb [ $br +$tb {definition} +$tb $br diff --git a/assets/schemas/xml/entry.sch b/assets/schemas/xml/entry.sch new file mode 100644 index 0000000000..e02105c8d6 --- /dev/null +++ b/assets/schemas/xml/entry.sch @@ -0,0 +1,4 @@ +# XML definition for database model changelog entries +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb diff --git a/assets/schemas/xml/enumeration.sch b/assets/schemas/xml/enumeration.sch new file mode 100644 index 0000000000..adbdeb919c --- /dev/null +++ b/assets/schemas/xml/enumeration.sch @@ -0,0 +1,4 @@ +# XML definition for enumeration labels in user-defined types +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb [ $br \ No newline at end of file diff --git a/assets/schemas/xml/eventtrigger.sch b/assets/schemas/xml/eventtrigger.sch new file mode 100644 index 0000000000..193c3d4ca0 --- /dev/null +++ b/assets/schemas/xml/eventtrigger.sch @@ -0,0 +1,28 @@ +# XML definition for event triggers +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end +%if {function} %then {function} %end +%if {filter} %then {filter} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + + $br $br + diff --git a/assets/schemas/xml/excelement.sch b/assets/schemas/xml/excelement.sch new file mode 100644 index 0000000000..ce18833fcb --- /dev/null +++ b/assets/schemas/xml/excelement.sch @@ -0,0 +1,31 @@ +# XML definition for exclude constraint elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb $tb $br + +%if {column} %then + $tb $tb $tb [ $br +%else + #%if {expression} %then + $tb $tb $tb $br + #%end +%end + +%if {opclass} %then + $tb $tb $tb {opclass} +%end + +#%if {operator} %then +$tb $tb $tb {operator} +#%end + +$tb $tb $br diff --git a/assets/schemas/xml/extension.sch b/assets/schemas/xml/extension.sch new file mode 100644 index 0000000000..ee6e0659fd --- /dev/null +++ b/assets/schemas/xml/extension.sch @@ -0,0 +1,37 @@ +# XML definition for extensions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +%if {schema} %then + {schema} +%end + +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + + $br $br + diff --git a/assets/schemas/xml/foreigndatawrapper.sch b/assets/schemas/xml/foreigndatawrapper.sch new file mode 100644 index 0000000000..73978ed4dd --- /dev/null +++ b/assets/schemas/xml/foreigndatawrapper.sch @@ -0,0 +1,37 @@ +# XML definition for indexes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {reduced-form} %then + $tb +%end + +[ $br +%else + %if {options} %then + [ options=] "{options}" + %end + + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + > $br + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + %if {handler} %then {handler} %end + %if {validator} %then {validator} %end + + $br $br +%end diff --git a/assets/schemas/xml/foreignserver.sch b/assets/schemas/xml/foreignserver.sch new file mode 100644 index 0000000000..6b70ee4f51 --- /dev/null +++ b/assets/schemas/xml/foreignserver.sch @@ -0,0 +1,41 @@ +# XML definition for servers +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {reduced-form} %then $tb %end + +[ $br +%else + %if {type} %then + [ type=] "{type}" + %end + + %if {version} %then + [ version=] "{version}" + %end + + %if {options} %then + [ options=] "{options}" + %end + + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + > $br + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + %if {fdw} %then {fdw} %end + + $br $br +%end diff --git a/assets/schemas/xml/foreigntable.sch b/assets/schemas/xml/foreigntable.sch new file mode 100644 index 0000000000..d3003cc12b --- /dev/null +++ b/assets/schemas/xml/foreigntable.sch @@ -0,0 +1,42 @@ +# XML definition for tables +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +{schema} +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end +{server} +%if {tag} %then {tag} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end +{position} + +%if {columns} %then {columns} %end +%if {constraints} %then {constraints} %end + +%if {col-indexes} %then {col-indexes} %end +%if {constr-indexes} %then {constr-indexes} %end + +%if {initial-data} %then + $tb $br + + $br $tb $br +%end + + + $br $br diff --git a/assets/schemas/xml/function.sch b/assets/schemas/xml/function.sch new file mode 100644 index 0000000000..0b2e8f9a63 --- /dev/null +++ b/assets/schemas/xml/function.sch @@ -0,0 +1,85 @@ +# XML definition for functions +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {reduced-form} %then $tb %end + + $br +%else + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + $br + $tb $tb window-func=%if {window-func} %then "true" %else "false" %end $br + + %if {leakproof} %then $tb $tb leakproof="true" $br %end + + $tb $tb returns-setof=%if {returns-setof} %then "true" %else "false" %end $br + $tb $tb behavior-type="{behavior-type}" $br + $tb $tb function-type="{function-type}" $br + $tb $tb security-type="{security-type}" $br + $tb $tb parallel-type="{parallel-type}" $br + $tb $tb execution-cost="{execution-cost}" $br + $tb $tb row-amount="{row-amount}" + > $br + + {schema} + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + %if {language} %then {language} %end + + $tb $br + + %if {return-table} %then + {return-table} + %else + {return-type} + %end + + $tb $br + + %if {transform-types} %then + $tb [ $br + %end + + %if {config-params} %then + {config-params} + %end + + %if {parameters} %then {parameters} %end + + + %if {library} %then + $tb [ $br + + %else + $tb $br + %end + + $br $br +%end diff --git a/assets/schemas/xml/genericsql.sch b/assets/schemas/xml/genericsql.sch new file mode 100644 index 0000000000..427d36ac09 --- /dev/null +++ b/assets/schemas/xml/genericsql.sch @@ -0,0 +1,20 @@ +# XML definition for generic sql objects +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +$tb $br + +%if {objects} %then {objects} %end + + $br $br diff --git a/assets/schemas/xml/idxelement.sch b/assets/schemas/xml/idxelement.sch new file mode 100644 index 0000000000..5ded204a04 --- /dev/null +++ b/assets/schemas/xml/idxelement.sch @@ -0,0 +1,31 @@ +# XML definition for indexes elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb $tb $br + +%if {column} %then + $tb $tb $tb [ $br +%else + #%if {expression} %then + $tb $tb $tb $br + #%end +%end + +%if {collation} %then + $tb $tb {collation} +%end + +%if {opclass} %then + $tb $tb $tb {opclass} +%end + +$tb $tb $br diff --git a/assets/schemas/xml/index.sch b/assets/schemas/xml/index.sch new file mode 100644 index 0000000000..90d826d639 --- /dev/null +++ b/assets/schemas/xml/index.sch @@ -0,0 +1,46 @@ +# XML definition for indexes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[ $br + +%if {tablespace} %then {tablespace} %end +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +{elements} + +%if {predicate} %then + $tb $br +%end + +%if {include-cols} %then + $tb [] $br +%end + + $br $br diff --git a/assets/schemas/xml/info.sch b/assets/schemas/xml/info.sch new file mode 100644 index 0000000000..8804384dd9 --- /dev/null +++ b/assets/schemas/xml/info.sch @@ -0,0 +1,108 @@ +# XML definition for a single object's metadata +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%set {space} $br $tb $tb + +$tb [ $br + %if {position} %then {position} %end + %if {appended-sql} %then $tb {appended-sql} %end + %if {prepended-sql} %then $tb {prepended-sql} %end + $tb +%else + [/>] +%end + +$br diff --git a/assets/schemas/xml/label.sch b/assets/schemas/xml/label.sch new file mode 100644 index 0000000000..a1dca9825a --- /dev/null +++ b/assets/schemas/xml/label.sch @@ -0,0 +1,6 @@ +# XML definition for relationship label positioning +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb $br \ No newline at end of file diff --git a/assets/schemas/xml/language.sch b/assets/schemas/xml/language.sch new file mode 100644 index 0000000000..b6aa89b898 --- /dev/null +++ b/assets/schemas/xml/language.sch @@ -0,0 +1,34 @@ +# XML definition for schemas +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {reduced-form} %then $tb %end + +[] $br +%else + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + [ trusted=] %if {trusted} %then "true" %else "false" %end + + [>]$br + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + %if {handler} %then {handler} %end + %if {validator} %then {validator} %end + %if {inline} %then {inline} %end + + $br $br +%end diff --git a/assets/schemas/xml/metadata.sch b/assets/schemas/xml/metadata.sch new file mode 100644 index 0000000000..b0cba3a577 --- /dev/null +++ b/assets/schemas/xml/metadata.sch @@ -0,0 +1,11 @@ +# XML definition for graphical object metada file +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + $br +[] $br + $br +%if {info} %then {info} %end + diff --git a/assets/schemas/xml/object.sch b/assets/schemas/xml/object.sch new file mode 100644 index 0000000000..083ab828d7 --- /dev/null +++ b/assets/schemas/xml/object.sch @@ -0,0 +1,15 @@ +# XML definition for custom index for a single column or constraint +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {index} %then $tb %end +$tb [ $br diff --git a/assets/schemas/xml/opclass.sch b/assets/schemas/xml/opclass.sch new file mode 100644 index 0000000000..2ec0dccd06 --- /dev/null +++ b/assets/schemas/xml/opclass.sch @@ -0,0 +1,43 @@ +# XML definition for operator classes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br +%else + + [ index-type=] "{index-type}" + [ default=] %if {default} %then "true" %else "false" %end + + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + > $br + + {schema} + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + %if {family} %then + $tb [] $br + %end + + {type} + {elements} + + $br $br +%end diff --git a/assets/schemas/xml/operator.sch b/assets/schemas/xml/operator.sch new file mode 100644 index 0000000000..2e2767d309 --- /dev/null +++ b/assets/schemas/xml/operator.sch @@ -0,0 +1,45 @@ +# XML definition for schemas +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {reduced-form} %then $tb %end + +[ $br +%else + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + > $br + + {schema} + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + %if {left-type} %then {left-type} %end + %if {right-type} %then {right-type} %end + + + %if {commutator-op} %then {commutator-op} %end + %if {negator-op} %then {negator-op} %end + %if {operfunc} %then {operfunc} %end + %if {join} %then {join} %end + %if {restriction} %then {restriction} %end + + $br $br +%end diff --git a/assets/schemas/xml/opfamily.sch b/assets/schemas/xml/opfamily.sch new file mode 100644 index 0000000000..35c7d1626d --- /dev/null +++ b/assets/schemas/xml/opfamily.sch @@ -0,0 +1,30 @@ +# XML definition for operator families +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if {reduced-form} %then $tb %end + +[ $br +%else + [name=] "{name}" [ index-type=] "{index-type}" + + %if {protected} %then + [ protected=] "true" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + > $br + + {schema} + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + $br $br +%end diff --git a/assets/schemas/xml/parameter.sch b/assets/schemas/xml/parameter.sch new file mode 100644 index 0000000000..f1e0b99a33 --- /dev/null +++ b/assets/schemas/xml/parameter.sch @@ -0,0 +1,13 @@ +# XML definition for function parameters +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb [$br + +$tb {type} + +$tb $br diff --git a/assets/schemas/xml/partitionkey.sch b/assets/schemas/xml/partitionkey.sch new file mode 100644 index 0000000000..f26fe0eda2 --- /dev/null +++ b/assets/schemas/xml/partitionkey.sch @@ -0,0 +1,20 @@ +# XML definition for indexes elements +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb $tb $br + +%if {column} %then + $tb $tb $tb [ $br +%else + $tb $tb $tb $br +%end + +%if {collation} %then + $tb $tb {collation} +%end + +%if {opclass} %then + $tb $tb $tb {opclass} +%end + +$tb $tb $br diff --git a/assets/schemas/xml/permission.sch b/assets/schemas/xml/permission.sch new file mode 100644 index 0000000000..f5adef26ce --- /dev/null +++ b/assets/schemas/xml/permission.sch @@ -0,0 +1,48 @@ +# XML definition for grants +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + $br + + +$tb [] $br + +%if {roles} %then + $tb [] $br +%end + +$tb [] $br + + $br diff --git a/assets/schemas/xml/policy.sch b/assets/schemas/xml/policy.sch new file mode 100644 index 0000000000..136ae391d9 --- /dev/null +++ b/assets/schemas/xml/policy.sch @@ -0,0 +1,37 @@ +# XML definition for policies +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[ $br + +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +%if {roles} %then + $tb [] +%end + +%if {using-exp} %then + $br $tb [] +%end + +%if {check-exp} %then + $br $tb [] +%end + +$br + + diff --git a/assets/schemas/xml/position.sch b/assets/schemas/xml/position.sch new file mode 100644 index 0000000000..de227501b6 --- /dev/null +++ b/assets/schemas/xml/position.sch @@ -0,0 +1,5 @@ +# XML definition for object positioning +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb [ $br diff --git a/assets/schemas/xml/prependedsql.sch b/assets/schemas/xml/prependedsql.sch new file mode 100644 index 0000000000..7621633414 --- /dev/null +++ b/assets/schemas/xml/prependedsql.sch @@ -0,0 +1,9 @@ +# XML definition for prepended SQL commands +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +#Creates element envolving the prepended-sql +#The tag is converted to in order +#to not cause syntax errors on the schema parser + +$tb $br diff --git a/assets/schemas/xml/procedure.sch b/assets/schemas/xml/procedure.sch new file mode 100644 index 0000000000..4ba2a3246b --- /dev/null +++ b/assets/schemas/xml/procedure.sch @@ -0,0 +1,41 @@ +# XML definition for procedures +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + + $br + +{schema} + +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end +%if {language} %then {language} %end + +%if {transform-types} %then + $tb [ $br +%end + +%if {config-params} %then + {config-params} +%end + +%if {parameters} %then {parameters} %end + +%if {library} %then + $tb [ $br +%else + $tb $br +%end + + $br $br diff --git a/assets/schemas/xml/reference.sch b/assets/schemas/xml/reference.sch new file mode 100644 index 0000000000..14df973d5b --- /dev/null +++ b/assets/schemas/xml/reference.sch @@ -0,0 +1,30 @@ +# XML definition for view references +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +$tb $br + + $tb $tb $br + + %if {columns} %then {columns} %end + %if {ref-tables} %then {ref-tables} %end + + $tb $br +%else + /> $br +%end diff --git a/assets/schemas/xml/reftable.sch b/assets/schemas/xml/reftable.sch new file mode 100644 index 0000000000..53aae00f7e --- /dev/null +++ b/assets/schemas/xml/reftable.sch @@ -0,0 +1,5 @@ +# XML definition for view references +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb $tb [] $br diff --git a/assets/schemas/xml/relationship.sch b/assets/schemas/xml/relationship.sch new file mode 100644 index 0000000000..98f95bc21a --- /dev/null +++ b/assets/schemas/xml/relationship.sch @@ -0,0 +1,120 @@ +# XML definition for relationships +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br $br +%else + > $br + + %if {points} %then $tb $br $tb {points} $tb $br %end + %if {labels-pos} %then {labels-pos} %end + + %if %not {relgen} %and %not {reldep} %and %not {relpart} %then + %if {columns} %then {columns} %end + %if {constraints} %then {constraints} %end + %end + + %if {original-pk} %then + {original-pk} + %end + + %if {special-pk-cols} %then + $tb [ $br + %end + + %if {partition-bound-expr} %then + $tb $br + %end + + $br $br +%end diff --git a/assets/schemas/xml/role.sch b/assets/schemas/xml/role.sch new file mode 100644 index 0000000000..5d31e4bcdb --- /dev/null +++ b/assets/schemas/xml/role.sch @@ -0,0 +1,40 @@ +# XML definition for roles +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {reduced-form} %then $tb %end +[ $br +%else + %if {superuser} %then $br [ superuser="true"] %end + %if {createdb} %then $br [ createdb="true"] %end + %if {replication} %then $br [ replication="true"] %end + %if {createrole} %then $br [ createrole="true"] %end + %if {inherit} %then $br [ inherit="true"] %end + %if {login} %then $br [ login="true"] %end + %if {bypassrls} %then $br [ bypassrls="true"] %end + %if {encrypted} %then $br [ encrypted="true"] %end + %if {connlimit} %then $br [ connlimit=]"{connlimit}" %end + %if {validity} %then $br [ validity=]"{validity}" %end + %if {password} %then $br [ password=]"{password}" %end + + %if {protected} %then + $br [ protected="true"] + %end + + %if {sql-disabled} %then + $br [ sql-disabled="true"] + %end + + > $br + + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + %if {member-roles} %then $tb [] $br %end + %if {admin-roles} %then $tb [] $br %end + + $br $br +%end diff --git a/assets/schemas/xml/rule.sch b/assets/schemas/xml/rule.sch new file mode 100644 index 0000000000..4dac32a6d1 --- /dev/null +++ b/assets/schemas/xml/rule.sch @@ -0,0 +1,37 @@ +# XML definition for indexes +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +%if {comment} %then $tb {comment} %end + +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +%if {condition} %then + $tb $tb $br +%end + +%if {commands} %then + $tb $tb $br +%end + + $br $br diff --git a/assets/schemas/xml/schema.sch b/assets/schemas/xml/schema.sch new file mode 100644 index 0000000000..a79856e4dd --- /dev/null +++ b/assets/schemas/xml/schema.sch @@ -0,0 +1,46 @@ +# XML definition for schemas +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +%if {reduced-form} %then $tb %end +[ $br +%else + %if {layers} %then + [ layers=]"{layers}" + %end + + %if {alias} %then + $sp alias="{alias}" + %end + + %if {protected} %then + [ protected=] "true" + %end + + %if {rect-visible} %then + [ rect-visible=] "true" + %end + + %if {fill-color} %then + [ fill-color=] "{fill-color}" + %end + + %if {sql-disabled} %then + [ sql-disabled=] "true" + %end + + %if {faded-out} %then + [ faded-out=] "true" + %end + + > $br + + %if {owner} %then {owner} %end + %if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} %end + %if {prepended-sql} %then {prepended-sql} %end + + $br $br +%end diff --git a/assets/schemas/xml/sequence.sch b/assets/schemas/xml/sequence.sch new file mode 100644 index 0000000000..8ac931141d --- /dev/null +++ b/assets/schemas/xml/sequence.sch @@ -0,0 +1,47 @@ +# XML definition for sequences +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. +[ $br + +{schema} +%if {owner} %then {owner} %end +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + $br $br diff --git a/assets/schemas/xml/style.sch b/assets/schemas/xml/style.sch new file mode 100644 index 0000000000..8529e0bcf1 --- /dev/null +++ b/assets/schemas/xml/style.sch @@ -0,0 +1,7 @@ +# XML definition for object tag styles +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb [